How to accumulate power readings?

I am monitoring power usage and charge on various systems on a boat. I walked into this thinking it was simple.... hah!

The goal was to gather data such as 60 samples for an hour, 48 samples for 24 hours, daily, whatever. Displaying average current, voltage and power for a timeframe with a simple touchscreen on the switchboard.

I have an ina3221 3 channel current/voltage monitor set up which is working fine for real time data viewing.

I programmed an accumulator which would accumulate the average current, voltage and calculate the power for a time frame. This quickly became complicated.

The question is if I'm reinventing something that is already out there? Surely someone has gone through all this already.

Here are things I've run into:

  • Dealing with the first reading because there's no previous reference.
  • Time between samples isn't strict so that is taken care of with time delta between readings.
  • When the accumulator reaches it's time interval, eg. 1 min, but the timing isn't exactly at the end of the interval so the in between value needs to be calculated and the remainder handled.
  • What if the sensor goes off for a period? What data to record?
  • Then how to deal with the next higher timeframe accumulator. Eg. 1 min readings passed to the half hour accumulator. I tried to abstract this with an object orientated class but I haven't thought it all through how that works.
  • Calculating how long the accumulator can run before running out of memory (currently ESP32).
  • There's a rollover of millis() or micros(). I could get a realtime clock but again more complexity.
  • How fast to sample readings? It means calculating error rates at different frequencies and balancing memory requirements of the accumulated value.

I didn't see any of this when I started.

InfluxDB can handle all this. A time series database with retention policies that downsample data depending on age. That requires a high powered piece of hardware. I'm trying to minimize battery usage. I considered using a logging module then another device to process the data with influxDB when required but I should be able to do most of it on an ESP32.

There are multichannel monitors with power accumulators. Eg. PAC1954. It means waiting for another device and there's no average current or voltage. It half does a job.

Sample errors get huge at the low end for higher powered circuits. Eg. 0 to 200amps.
Ina3221: 160% error at 100ma vs Ina228 has 2% at 100ma. It's great. But no accumulator on board the chip so back to a software accumulator.

Take your first reading inside setup() along with your timestamp, then the main loop() will always have a previous sample

Why not? Look at the Blink Without Delay example (File->examples-02.digital->Blink Without Delay) to see how to track elapsed time. If you are takeing samples every minute, you should have lots of idle time.

???

  • What if the sensor goes off for a period? What data to record?
  • Then how to deal with the next higher timeframe accumulator. Eg. 1 min readings passed to the half hour accumulator. I tried to abstract this with an object orientated class but I haven't thought it all through how that works.
  • Calculating how long the accumulator can run before running out of memory (currently ESP32).

irrelevant to track elapsed time unless you are trying to track time greater than 50 days. That is the beauty of unsigned math. millis() - startTime will always be correct, even if millis() is less than startTime due to rollover

1 Like