python3 MPPSolar datalogger (alpha)

Joined
Aug 10, 2018
Messages
242
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)
 
Help with what, how to get it to work on Windows?
Are you saying on windows the command CMDdoesn't work? I think you have a serial port issue not code issue if it works on a RPI.

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


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.
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.
 
Back
Top