Python logging of PCM 60x charge controller
My MPP Solar PCM 60x charge controller has a serial-port connection, but the software that “comes with it” only runs on Windows (I need something for Linux). It turns out that a number of people have already invented this wheel, and I was able to use their efforts to hack a simple python script for crude logging.
I got the serial query string from a piece of code in the solarsnoop project on GitHub, and the details of the return string are explained in a documentation pdf that I found on another GitHub project. I also had a look at the solar-sis project, and it might be worth coming back to when I want fancier things later on. For now I made a Jupyter notebook with the following code:
import serial import time import datetime import numpy as np QPIGS = b"\x51\x50\x49\x47\x53\xB7\xA9\x0D" ser = serial.Serial(port='/dev/ttyACM0',baudrate=2400,timeout=2) log_duration = 10*60*60 # seconds data = [] times = [] start = datetime.datetime.now() while (datetime.datetime.now() - start).seconds < log_duration: ser.write(QPIGS) result = ser.read(70) ser.read() ser.read() times.append(datetime.datetime.now()) data.append(result) time.sleep(60) # Processing the logged strings into useful data numdata = np.zeros((len(data), 7)) nptimes = np.zeros(len(times), dtype='datetime64[ms]') for i, entry in enumerate(data): nptimes[i] = np.datetime64(times[i]) # When it gets dark the PCM 60x goes to sleep and returns # empty strings if len(entry) > 40: numdata[i, 0] = float(entry[1:6].decode()) numdata[i, 1] = float(entry[7:12].decode()) numdata[i, 2] = float(entry[13:18].decode()) numdata[i, 3] = float(entry[19:24].decode()) numdata[i, 4] = float(entry[25:30].decode()) numdata[i, 5] = float(entry[31:35].decode()) numdata[i, 6] = float(entry[36:40].decode()) # Keep only the lines that have data data_present = np.where(numdata[:,1] > 0) numdata = numdata[data_present] nptimes = nptimes[data_present] # Save to log files np.savetxt('20180919_solar_charge_log.csv', numdata) np.savetxt('20180919_solar_charge_log_times.csv', nptimes, fmt='%s')
This gave me what I needed – the ability to “look at” the solar charging process despite being away from home during the sunny part of the day. The next step is nice visualisation, and Google Sheets gives me a fast and easy way to put logged data on the cloud. I followed this helpful tutorial for setting up Google Docs API and interacting with a Google Sheets spreadsheet from python. It didn’t work immediately, and I think the authentication details may have changed slightly since that tutorial was written. I found the following works nicely.
import gspread from oauth2client.service_account import ServiceAccountCredentials scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] creds = ServiceAccountCredentials.from_json_keyfile_name('my_secret.json', scope) client = gspread.authorize(creds) sheet = client.open("my_solar_charge_log").sheet1 header = ["Time", "Battery V", "Charging A", "Charging W"] sheet.insert_row(header, 1) for i, line in enumerate(numdata): row = [str(nptimes[i])[11:19], line[1], line[2], line[5] ] sheet.insert_row(row, i+2) time.sleep(1.5) # Avoid the 100 queries in 100s access limit
Once the data was in Google Sheets I could make nice interactive plots to embed here. I found a nice trick for adding arbitrary text labels to a plot. I hope to set up a live chart that can track the charging in real-time.
One thought on “Python logging of PCM 60x charge controller”