Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
python3 MPPSolar datalogger (alpha)
#1
i m trying to read from generic Pip inverter from win, but no luck.

It works on Raspberry.


anyone can help?
( Need to comment CMD="…....")
Code:
import serial, time
import struct, string
import shutil  
import os
import csv
from ctypes import c_ubyte, c_ushort
from pathlib import Path
from serial import Serial

#from influxdb import InfluxDBClient
percorso=Path('./DATA.txt')
def CalcoloCRC( str ):

   crc_ta = [ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, \
                    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef ]

   lunghezza = len(str)

   Calcolo = list(str)

   crc = 0

   for idx in range(0,lunghezza):
       da=c_ubyte((c_ubyte(crc>>8).value)>>4).value
       crc = c_ushort(crc << 4).value
       crc = c_ushort(crc ^ crc_ta[da^c_ubyte(c_ubyte(ord(Calcolo[idx])).value >> 4).value]).value
       da = (c_ubyte(crc>>8).value) >> 4
       crc <<= 4
       crc = c_ushort(crc ^ crc_ta[ da ^ ( ord(Calcolo[idx]) & 0x0f )]).value

   bCRCLow = c_ubyte(crc).value
   bCRCHign = c_ubyte(crc>>8).value

   if ( bCRCLow==0x28 or bCRCLow==0x0d or bCRCLow==0x0a ):
       bCRCLow += 1

   if ( bCRCHign==0x28 or bCRCHign==0x0d or bCRCHign==0x0a ):
       bCRCHign += 1

   crc = c_ushort(bCRCHign).value << 8
   crc += bCRCLow;
   return crc

class Inverter:
   def __init__(self,serialport):

       self.ser = serial.Serial()
       self.ser.port = serialport
       self.ser.baudrate = 2400
       self.ser.bytesize = serial.EIGHTBITS    #number of bits per bytes
       self.ser.parity = serial.PARITY_NONE    #set parity check: no parity
       self.ser.stopbits = serial.STOPBITS_ONE #number of stop bits
       self.ser.timeout = 1                    #non-block read
       self.ser.xonxoff = False                #disable software flow control
       self.ser.rtscts = False                 #disable hardware (RTS/CTS) flow control
       self.ser.dsrdtr = False                 #disable hardware (DSR/DTR) flow control
       self.ser.writeTimeout = 2               #timeout for write

       try:
           self.ser.open()
           print("connesso")
       except Exception as e:
           print ("error open serial port: " + str(e))
           exit()

       if self.ser.isOpen():
           try:
               print("pulisco input e output")
               self.ser.flushInput()   #flush input buffer, discarding all its contents
               self.ser.flushOutput()  #flush output buffer, aborting current output
                           #and discard all that is in buffer
           except Exception as e1:
                              # print ("error communicating...: " )
               print ("error communicating...: " + str(e1))
       else:
           print ("cannot open serial port ")

   def QueryCMD(self,CMD):
       try:
           print ("invio comandi")
           print (CMD)
           self.ser.write(CMD + struct.pack('!H',CalcoloCRC(CMD)) + '\x0D')
           time.sleep(1)  #give the serial port sometime to receive the data
           self.response = self.ser.readline()
           print ("response" + str (self.response))
           self.CRCSENT = ord(self.response[-3]) * 256 + ord(self.response[-2])
           if ( CalcoloCRC(self.response[:-3]) == self.CRCSENT ):
               return self.response[:-3]
               print ("crc passato")
           else:
               return -1
               print ("crc errato")
       except:
           print ("eccezione!!!")
        #   return -1

   def Update(self):
       print ("aggiorno")
       CMD = self.QueryCMD("QPIGS")
       print("cmd ricevuto: ")
       CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
       print (CMD)
       
       if(CMD == -1):
           
           print("errorer lettura dati gpigs")
           return -1
       print ("qpigs ok")
       CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
       all = str.split(CMD[1:])
       self.grid_voltage = float(all[0])
       self.grid_frequency = float(all[1])
       self.ac_output_voltage = float(all[2])
       self.ac_output_frequency = float(all[3])
       self.ac_output_apparent_power = int(all[4])
       self.ac_output_active_power = int(all[5])
       self.output_load_percent = int(all[6])
       self.bus_voltage = float(all[7])
       self.battery_voltage = float(all[8])
       self.battery_charging_current = int(all[9])
       self.battery_capacity = int(all[10])
       self.heatsink_temperature = int(all[11])
       self.pv_current = int(all[12])
       self.pv_voltage = float(all[13])
       self.battery_voltage_scc = float(all[14])
       self.battery_discharge_current = int(all[15])
       self.pv_power = int(all[19])
       self.line_power = self.ac_output_active_power - self.pv_power
       CMD = self.QueryCMD("QMOD")
       if (CMD == -1):
           print ("qmod errato")
           return -1
       CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
       mode = CMD[1:]
       self.isLineMode = 0
       if ( mode == "L" ):
           print ("line mode")
           self.isLineMode = 1
       self.isBatteryMode = 0
       if ( mode == "B" ):
           print ("battery mode")
           self.isBatteryMode = 1
       CMD = self.QueryCMD("QPIWS")
       CMD= "230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
       if (CMD == -1):
                       print ("QPIWS")
                       return -1
       self.inverter_fault = CMD[1:2]
       self.BusOvervolt = CMD[2:3]
       self.BusUndervolt = CMD[3:4]
       self.SoftStartFail = CMD[4:5]
       self.LineFail = CMD[5:6]
       self.PvShort = CMD[6:7]
       self.InvVoltLow = CMD[7:8]
       self.InvVolrHigh = CMD[8:9]
       self.OverTemp = CMD[9:10]
       self.BatteryVoltHigh = CMD[10:11]
       self.BatteryVoltLow = CMD[11:12]
       
       return 0

#####################################################################
##                                                                 ##
##     MAIN                                                        ##
#####################################################################


sp5000 = Inverter("COM1")  
#client = InfluxDBClient('localhost', ?', 'roor', '', 'fotovoltaico')

while True:
   if (sp5000.Update() == 0):
       with open('DATA.txt', mode='a') as csv_file:
                   fieldnames = ['grid_voltage','grid_frequency' ,'ac_output_voltage',  'ac_output_frequency', 'ac_output_frequency','ac_output_apparent_power',   'ac_output_active_power', 'output_load_percent','bus_voltage','battery_voltage','battery_charging_current','battery_capacity','heatsink_temperature','pv_current','pv_voltage','battery_voltage_scc','battery_discharge_current','isLineMode','isBatteryMod',       'inverter_fault','BusOvervolt','BusUndervolt','SoftStartFail','LineFail','PvShort','InvVoltLow','InvVolrHigh','OverTemp','BatteryVoltHigh','BatteryVoltLow','PvPower','LinePower']
          # fieldnames=[]
                   writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
                   if percorso.is_file():
                       writer.writerow({"grid_voltage":str(sp5000.grid_voltage),"grid_frequency": str(sp5000.grid_frequency),"ac_output_voltage": str(sp5000.ac_output_voltage),"ac_output_frequency": str(sp5000.ac_output_frequency),"ac_output_apparent_power": str(sp5000.ac_output_apparent_power),          "ac_output_active_power": str(sp5000.ac_output_active_power), "output_load_percent": str(sp5000.output_load_percent),  "bus_voltage": str(sp5000.bus_voltage),  "battery_voltage": str(sp5000.battery_voltage),  "battery_charging_current": str(sp5000.battery_charging_current),    "battery_capacity": str(sp5000.battery_capacity),  "heatsink_temperature": str(sp5000.heatsink_temperature),"pv_current": str(sp5000.pv_current), "pv_voltage": str(sp5000.pv_voltage),   "battery_voltage_scc": str(sp5000.battery_voltage_scc),   "battery_discharge_current": str(sp5000.battery_discharge_current),  "isLineMode": str(sp5000.isLineMode),   "isBatteryMod": str(sp5000.isBatteryMode), "inverter_fault": str(sp5000.inverter_fault),"BusOvervolt": str(sp5000.BusOvervolt),"BusUndervolt": str(sp5000.BusUndervolt), "SoftStartFail": str(sp5000.SoftStartFail),"LineFail": str(sp5000.LineFail),"PvShort": str(sp5000.PvShort),  "InvVoltLow": str(sp5000.InvVoltLow),    "InvVolrHigh": str(sp5000.InvVolrHigh),  "OverTemp": str(sp5000.OverTemp),  "BatteryVoltHigh": str(sp5000.BatteryVoltHigh),   "BatteryVoltLow": str(sp5000.BatteryVoltLow),   "PvPower": str(sp5000.pv_power),   "LinePower": str(sp5000.line_power)
                        })
                       print ("sto salvando su file")
                   else:
                       writer.writeheader()  # file doesn't exist yet, write a header
                       print ("non sto scrivendo su file")
           
           
           # str(sp5000.grid_voltage)
   else:
       print ("non ci siamo")
   #client.write_points(json_body)
   time.sleep(5)
Building Lifepo4 Powerwall - atm 1400 cells growing

Reply
#2
Help with what, how to get it to work on Windows?
Are you saying on windows the command CMD doesn't work? I think you have a serial port issue not code issue if it works on a RPI.

Quote:from serial import Serial
is this pyserial or just general serial module, I've seen different modules but import looks the same?


Quote:   def Update(self):
       print ("aggiorno")
       CMD = self.QueryCMD("QPIGS")

Also, you should be using PEP8 guidance. 

ie functions are lowercase and underscores, classes are camel case defined.
Quote:   def QueryCMD(self, CMD):
should be really be
   def query_cmd(self, CMD):


and all caps signifies constants but above you're passing a variable, can get confusing to read as a 3rd part developer.
Join our discord channel for DIY discussions https://diyenergypack.com/invite.php?code=Gm9qh5W
(this chat is not directly affiliated with SecondLifeStorage)
Reply
#3
i haven t error on serial Port.

but MPPSolar reply Is : None

maybe Is a CRC error
Building Lifepo4 Powerwall - atm 1400 cells growing

Reply
#4
Try sending this string as your request string, instead of "QPIGS". It's encoded with CRC.
CMD = self.QueryCMD("\x51\x50\x49\x47\x53\xB7\xA9\x0D")

Make sure it's sent as ascii. I'm not sure how that's done in python, but nodejs has a flag for ascii.
Reply
#5
thanks Mike, but already done an no reply from pip
Building Lifepo4 Powerwall - atm 1400 cells growing

Reply
#6
found issue in CRC.
now trying to ready parallel inverter

ill post new version asap
Building Lifepo4 Powerwall - atm 1400 cells growing

Reply


Who read this thread?
30 User(s) read this thread:
hbpowerwall (07-28-2019, 02:23 AM), Riplash (07-28-2019, 04:43 PM), emuland-metroman (08-07-2019, 06:59 PM), Beholder (08-08-2019, 03:57 PM), Wolf (08-07-2019, 06:34 PM), Solardad (07-28-2019, 02:56 AM), stevelectric (08-09-2019, 01:32 PM), ajw22 (08-05-2019, 12:21 PM), RikH (08-01-2019, 10:25 PM), OffGridInTheCity (07-28-2019, 05:09 PM), juanjo57 (07-28-2019, 04:54 AM), stok (07-29-2019, 05:38 AM), pir8don (08-10-2019, 01:24 AM), norknid (07-28-2019, 06:38 PM), Ibiza (08-07-2019, 07:07 PM), Redpacket (07-29-2019, 01:25 PM), daromer (08-07-2019, 06:41 PM), Sean (08-07-2019, 08:56 PM), mike (07-28-2019, 03:47 PM), Korishan (08-07-2019, 07:47 PM), Franky Beuselinck (08-02-2019, 12:52 PM), Mike C (08-15-2019, 05:03 AM), jdeadman (08-07-2019, 07:23 PM), wim (07-29-2019, 02:36 PM), jesusangel (07-28-2019, 10:54 AM), tremors (07-28-2019, 02:07 AM), Geek (08-08-2019, 12:07 AM), Ivo Staelens (08-08-2019, 08:45 AM), ChrisD5710 (07-28-2019, 11:26 AM), dragonfly (08-12-2019, 07:23 AM)

Forum Jump:


Users browsing this thread: 1 Guest(s)