Energy monitoring and creating a code black hole...

 I want to improve my energy monitoring system, which is currently based on a Chinese Tuya device, which uses a CT clamp, and is interrogated every 30 seconds by a Python script on an RPi. This device talks to the Tuya cloud, and accessing it locally on the LAN requires a Tuya developer account and lots of shenanigans. it is also about 3% out, which is boring.

Ideally I'd just get someone to fit a wireless-enabled inline device which actually measures the current, rather than using a CT clamp. However, these don't seem to exist, so I'd need

  • An inline device like an Eastern SDM120M, which does ModBus, sadly over RS485, which is a PitA
  • Another device to use ModBus to interrogate the SDM120, and do something with the data
The OpenEnergyMonitoring (OEM) approach is to use a RPi in conjunction with a RS485-USB converter plugged into the RPi's USB ports. I have obtained a PZEM-016 CT-based power monitor, which is apparently 1% accurate, which also has ModBus over RS485, and I've successfully connected to it and collected data using an RPi running a Python script. 

What more could I want? Well, the RPi is a power hungry thing, compared to ESP8266/ESP32, both of which have WiFi and sufficient smarts to do the job. The OEM RPi is used to run the EmonCMS/Hub software, which collects all the monitoring data from various sources and aggregates them for analysis etc. I already have one of those, running elsewhere than my meter cupboard, and I don't want to move it. Obviously, the USB connection has a limited range, although I suppose I could try a lengthy RS485 connection, it's designed for that after all. 

in order to avoid another RPi, I've tried using an M5StickC, one of which I'm already using to collect heat pump data. That uses a serial connection to poll the HP's data registers, and broadcasts the findings over MQTT for collection and analysis on my EmonCMS instance. Great! Learning from this, I obtained another M5StickC and an RS485 "hat" for it. However, I cannot get this combination to work! I have tried C++, Python and the crappy Blocks-style IDE provided online by M5 - nothing happens.

A friend of mine brought his scope round to check things out. We can see signals, albeit lower voltage than expected, using the RPi/laptop, RS485-USB adapter and a Python script using minimal-modbus. Hurray. But nothing seems to happen at all using the M5StickC/RS485 adapter. Sigh.

Anyway, as part of all this, I thought I might use the TFT screen (80x160, ST7735 controlled) from microPython on the M5StickC. Hey, why not? So I found something close, and adapted it to work on the M5StickC, which required finding a lib for the AXP192 that controls the screen's power, amongst other things on the device. A bit of fiddling with screen size, offsets and inversion, and bingo, the demo code works fine - this article was extremely helpful and most encouraging. 

I checked out the Adafruit ST7735 C++ driver, and found it uses a very neat structure to hold all the commands (15 in all!) and associated parameter data to initialise the screen, which saves considerable code and thus memory. I thought I'd try the same in Python, which didn't take me too long to set up - that works too, and would be much more maintainable, arguably. That was most satisfying.

However, investigating Python memory usage, I discover that even "simple" structures like my list of lists, use vast amounts of memory!! For example, the command list structure looks like

Rcmd1= ((ST77XX_SWRESET, 150, msec,bytearray([])),
        (ST77XX_SLPOUT,  255, msec,bytearray([])),
        (ST77XX_FRMCTR1, 0,msec,            #  3: Framerate ctrl - normal mode, 3 arg:
            bytearray([0x01, 0x2C, 0x2D])), #     Rate = fosc/(1x2+40) * (LINE+2C+2D)
        (ST77XX_FRMCTR2, 0, msec,           #  4: Framerate ctrl - idle mode, 3 args:
            bytearray([0x01, 0x2C, 0x2D]))  #     Rate = fosc/(1x2+40) * (LINE+2C+2D))

Each bytearray consumes a minimum of 56 bytes (empty) and 159 for 12 entries. Ouch. Not to mention the actual script and libs that have to be loaded on. So perhaps the 15 separate calls with highly distributed commands and parameter sets is a more efficient use of space in the Python world. Damn.

Why Python anyway? It just seems more convenient and less fiddly than C/C++, but it looks like I'd be better off doing that. It's not like there aren't loads of examples of how to do things. Hey ho. The refactoring was fun though. I shall continue to use Python for anything that handles data, accesses web-based APIs, or demonstrating the feasibility of an idea before maybe turning it into C[++].

Comments

Popular posts from this blog

Replacing Coffee Machine Pump (Dualit Espressivo)

Multiple SHT30 sensors on a single I2C bus with Sonoff-Tasmota

Towards a better doorbell...