Using an SCT-013 to calculate "low overhead" instantaneous power monitoring, is this method missing something?

So Robert, is the standard use model for the emonLIB to do continuous samples/calculations for 10cycles (200ms) and then extrapolate that use out 10 seconds…Or Is it to sample/calculate for one cycle (20ms) every second during the 10 seconds. What is the method that is normally used? Something in between? (I hope I have my units right in those assumptions)

Also, based on your experience/knowledge (dBC, others?), what do you think would be a minimum number of samples per cycle (using both current and voltage) to “accurately for what you think I might need for my pool project calculate power for the waveform that dBC posted of his washing machine. emonLIB uses 55pairs/cycle, could it be significantly less? Probably not down to the absolute theoretical minimum “four” previously mentioned for a possible PLL solution, especially given this unusual waveform…10? 20?

Thanks…

Edit: so I have been reading through some other threads on this site and apparently I have blindly stumbled (with all your help of course) onto some of the issues faced in designing and using power monitors. So I went back and added this caveat to my number of samples question:

accurately ”for what you think I might need for my pool project”

Neither - but nearer the first than the second. It doesn’t extrapolate, it simply reports the 200 ms average that it measures every 10 s. It’s emonCMS (or something else - Grafana maybe) that will “join the dots” and give you pseudo-continuous curve which can be integrated over time to give the energy value.

From what you’ve written, 10 s might be too long - it certainly fails when you have something like an induction hob in the kitchen, or a burst-mode energy diverter - but it arose from the need to equitably share access to emoncms.org among many users.

I think an empirical approach would serve you well. Print that picture at a reasonable size, put some pencil dots (have an eraser handy) on the curve at the spacing you think outlines the curve with sufficient fidelity, and see how far apart horizontally they are.

1 Like

The other thing to note about that washing machine trace is it’s not particularly repetitive (at least at 50Hz). That second positive peak is about 3.6 divisions while the last negative one is about 2.6.

Sorry to keep asking questions but I’m working out some things, mostly my understanding, haha. So why not report it 50 times in 10 seconds…is there a limitation somewhere?

OR…why not calculate & sample for 10 seconds continuously and then report it?

Or possibly you can point me in a direction, if the use model is documented…
Thanks.

Yeah, I did notice that…another dagger for my “find the peaks” strategy…if my pool pump is operating in a similar fashion.

Taking the easy one first…

As far as I’m aware, the reasons aren’t documented. You need to know the history.

It wouldn’t be 50 times in 10 seconds. If you were using all four c.t. inputs, it would be 12–13 times in 10 seconds, because the channels are checked sequentially. And the limitation is emoncms.org, as I mentioned above. emoncms.org preceded emoncms on the Raspberry Pi by many years. Although some users had access to a “full-size” server, there was no standard way to have local storage before the emonPi was introduced.

That’s called emonLibCM, and it’s been the standard sketch for the emonTx since mid-October, 2019. You can get the latest release and documentation at EmonLibCM - Version 2.2.1 (Released 30/10/2021)
The Atmel '328P spends roughly half its time processing the interrupts from the ADC, which probably doesn’t - unless your processor is significantly faster - leave a lot of time to do other things. For example, it can use the RFM69CW radio as a transmitter because that has an internal buffer that can be filled as it wishes, it cannot use the RFM12B because that doesn’t have an internal buffer and the timing of each byte sent to the transmitter is critical. So the “classic” JeeLib library can’t be used with emonLibCM.

The particle.io Photon (at least the one I could find) uses the STM32F205 ARM Cortex M3 processor running at 120 MHz, so, significantly faster than the '328p :slight_smile:

Which might help, but…

emonLibCM lets the ADC free run, so it’s the balance between the time between ADC interrupts delivering the latest sample and the time to process the last one, that counts. If the Photon works the same way, and the ADC is the same speed pro-rata, then you get more samples per cycle and exactly the same proportion of time to do other things, and it’s no help. If the ADC is faster pro rata, you’re worse off. Either way, you probably need to trigger the ADC off a timer to keep it at around the 50 or so samples per cycle. That ‘feels’ a decent number and should be good to the 25th harmonic or thereabouts, where there should be very little power, and conveniently forgetting anti-alias filters.

When deciding parameters like this, you really need to start from the answer to “How much significant power is there above what frequency?” A good guide will be the rules and limits for harmonic injection where you live.

Thanks Robert, that post explains a lot! I might have been able to discover that info by digging around but it definitely would have taken a much looonger. I am over my head with single phase and hadn’t even thought about the larger picture, haha.

I did add the voltage testing to my “bench setup”…it’s actually pretty nice/clean. I really hadn’t thought about the slight changes in voltage (RMS) having much impact on the power calculation, but it does occasionally deviate more than I expected…I don’t know if that is “whole house deviation” or a local drop to my power center,etc. I have not yet implemented the RMS power algorithm on my samples because I am still figuring out what I want to do with sampling.

After a hitch with the interrupt (actually a bug in the Photon OS that we found a workaround for), I setup my code to use interrupts and it seems that I have some latitude there, of course depending on the sample rate. I do want to “look” at the actual pool pump current waveform but that is a ways out due to grandkids/covid.

About Sampling…

I know how tedious/laborious responding to newbies can get so I hope no-one feels obligated to answer these questions…I perfectly understand.

  1. There appears to be an emphasis on starting sampling right at/after the beginning (zero crossing) of a cycle. It seems to me that if you sample for a full or half cycle, it doesn’t make any difference where you start. Is that incorrect?

  2. I have been thinking about “single cycle reconstruction” (my made-up term, there probably is a standard term for this which I just haven’t found) by sampling over multiple cycles. From an intuitive level, it makes sense to me but I am unclear what the cost is (besides probably some accuracy). The simplest example of what I am thinking is if you want to take 50 samples/sec. What problems would be introduced by taking sample #s 1,3,5,7,etc on the first cycle and taking sample #s 2,4,6,8, etc on the 2nd to “piece together” a waveform. It seems that it is a poor-man’s method of “averaging”, to some extent.

I guess the goal is to lessen the performance impact to my code…haha @Greebo, I am not going to try to sample full speed (50/sec). That is an option that seems close (for single phase) with the Photon, but in that case it would probably be a stand-along program that I would use only to characterize, not as a permanent part of my pool controller firmware (too much impact).

Anyway, thanks again for the help.

It’s not incorrect, but the practical point is if you don’t fit an exact integer number of samples into an exact number of wavelengths, you get an “end effect” of a fractional sample. It’s best not to have that error, but if it’s unavoidable, it’s least bad to have that error where the amplitude is small.

You’re relying on the average coming good. That’s going to be questionable with your loads varying with the frequency you’ve talked about - only a couple of seconds before you change the load on the pump again? You wouldn’t actually need to “piece together” a waveform, because you’re only squaring each sample and adding them all together to get the rms average, so as long as your sample rate in not locked to mains and you start and finish as close as possible to a zero crossing, it might work out with sufficient accuracy for your needs.

I’d just point out that the Atmel '328P in emonLib samples at about 2500 samples per second, to you about 42 samples per cycle. In emonLibCM, you get one sample every 104 µs, so roughly 9600 samples per second.

1 Like

Here’s a fresh capture of that washing machine with V included. Given the motor is DC, maybe it’s a SMPS topping up its reservoir cap as much as required, each half cycle:

Over 15 consecutive cycles, the average power was 472W. If you calculate average power over each of the 30 half cycles the result varies from 246W to 589W. If you calculate it over each of the 15 cycles, the result varies from 409W to 536W.

Oops Robert, sorry about that mistype…my intent was to refer to an earlier remark by you that indicated 50 samples/cycle might be an ideal sample rate to account for all harmonics in the power calculations.

I think, for single phase calculations, the Particle.io Photon COULD do that, but would probably require calls to system functions directly (Photon has an Open OS) rather than to “user available functions” for such things as the analog conversions and interrupt timing. But, I won’t be doing that.

That is a very nice, CLEAN trace. I’ve actually looked at some oscilloscopes recently to see if there are any cheap ones that might be useful to me (for more than this one power calculation for my pool pump, haha). I don’t think I am going to justify the purchase.

But, I do have a question:

Is 472W (average over the 15 cycles) “constant” for the long term measurement? I imagine it would be really close…

That’s actually out of my energy monitor. It effectively gives you a scope on each circuit breaker. Once you’ve decided you’re only interested in 2kHz worth of bandwidth you can filter hard with LPFs and digital filters and you end up with a much cleaner picture than you would with a real oscilloscope that’s good for 100MHz or 1GHz.

It’s hard to say with any certainty because in this case the underlying load is so dynamic. As Robert mentions above, if you want to average your way to the correct result you really need the actual load to be very stable, and all too often they’re not. Here’s the big picture of that load above:


In that case, the power is averaged over 500 cycles with no gaps between samples (i.e. every cycle gets measured). I’m not sure where I was on that graph when I took the high resolution sample but it certainly passes through 472W. On almost any timescale (from 10 msecs to 10 seconds) it’s a very dynamic load, so hard to measure accurately by random sampling, but easy to measure accurately by continuous sampling.

[EDIT] correction: the logs show the high res trace was taken at 10:05 (to the nearest minute)

Perhaps more relevant to your project is what my pool circuit looks like:


That’s pool+chlorinator on that breaker. You can just make out regular divots in that plateau. If you zoom in:

Like yours, my pool cleaner is on the output side of the pump, and every ~5 mins its reverse thruster valve opens. That picks it up and dumps it somewhere else in the pool. That’s enough of a change in flow rates to show up at the energy monitor as a ~15W divot.

dBC, wow, I hadn’t even considered those traces being from your energy monitor, but it makes sense.

If I am understanding correctly, that long trace is made up of continuous sampling/calculating for 10 seconds at a time. So, even though the graph is shown as a continuous line, it really is made up of discrete points (reported every 10 seconds) connected by the graphing program.

I’m trying to figure out exactly what information I want to get/characterize (in my project) and it comes down to this. I want to see what impact my (eventual) changes to my pool’s cleaning system does to my pump’s Energy Factor, which is calculated as (1000s of gallons pumped per kWh).

I won’t necessarily need 10-second chunks of power, especially considering I might not have the corresponding 10-second chunks of pump GPM that correspond to that power. Whatever I end up collecting (GPM & wattage)I will be accumulated and averaged over one (or more) complete zone of my pool’s cleaning system (about 5 minutes) in order to compare it to my sytem’s “pre-change” Energy Factor.

I agree that the trace from your pool will be closer to my pump’s operation, but I expect there to be larger variations in the wattage and GPM on my cleaning system. Typically my IFCS runs about 800 watts at the plateaus (in my previous diagram). In the valleys, I expect that to go up as high as 1100 watts.

Exactly right. You can actually see the points if you zoom in even further:

Actually, the same is true of the scope-like per-cycle trace, but in that case the datapoints are every 250 usecs. In the latest version of that energy monitor they’re every 125 usecs (8 kHz is the fundamental beat of the energy IC), but that one is still on the bench in the lab so I couldn’t easily point it at my pool pump or washing machine.

1 Like

I have been doing some testing with my new “sketch”. I have some more planned but wanted to check if I am off base on a couple assumptions. As it turns out, a dedicated Photon seems to be very capable of doing the real-time calculations necessary for continuous power measurements. I still haven’t dragged the setup out to my pool pad area, but I am getting close.

In this code posting, I have stripped down the code to a minimum (NO multi-cycle summing/averaging, etc). This code just takes a SINGLE cycle of data at a time and reports the power. Surprising to me, for all my “lab testing” including crock pots, hair dryer, floor fan…the power reading matches the Watts Meter within ~1% for all cases except at the very low end…with just a SINGLE CYCLE of sampling. Obviously these “lab loads” must be very regular, including the small motor devices that I am testing.

(1) So after talking me out of using “Apparent Power” as “good enough” (thanks to the knowledge/advice of all those that have helped), I have moved toward the opposite extreme: what good is Apparent Power? For use cases such as mine, is there an advantage to calculating RMS Voltage, RMS Current, power factor rather than going straight to the Real Power number?

(2) Also, I assumed (probably incorrectly) that the voltage and current offsets (due to the DC biasing of the sampling circuits), could be calculated/measured one time and then used exclusively as a constant…that’s shown in my “sketch”. I assumed that these values would be based on the actual resistances of the voltage dividers implemented, which I wouldn’t expect to change that much. It’s worked well the last couple days, but today they are off from my previous measurement. Is that variance “expected” and the reason why these offsets are calculated dynamically? Or did I just bump my breadboard?

Anywhere, here is the “sketch”…probably the only thing of interest for those following this, is the ISR routine itself which “calculates” the instantaneous power (Sample_ISR). In this minimized code, the sample rate is 333uSec (50 samples/cycle @ x60mHzx 60Hz).

#include "SparkIntervalTimer.h"

#define PUBLISH_TIME 2000        // 1000ms = every second
#define FREQUENCY 60             // 60 = 60Hz, 50 = 50Hz
#define SAMPLES_PER_CYCLE 50
#define ISR_SAMPLE_INTERVAL (int) (1000000/(FREQUENCY*SAMPLES_PER_CYCLE))  // in uSec
// The following constant is experimentally determined using a watts meter 
//    = (Power Reading on Watts Meter) / power_uncalibrated
// eliminates need to use/calculate RMS voltage/current
#define POWER_CALIBRATION_CONSTANT  7.804232804232804e-4 

IntervalTimer myTimer;

volatile long power_uncalibrated;  
unsigned long currentMillis, prior_publish_time;
bool timer_started = false; 
volatile bool sample_is_complete = false;

//Forward Function Declaration
void Sample_ISR(void);

void setup() {
  pinMode(D7, OUTPUT);  //BUG: required to enable the interrupt/IntervalTimer function...BUG on the PHOTON
  setADCSampleTime(ADC_SampleTime_144Cycles);  // Approx Conversion Times: 480=80us, 144=27us, 84=14us
}

void loop() {
  currentMillis = millis();

//Setup the ISR Current & Voltage Sampling Rate
  if (!timer_started) {
    myTimer.begin(Sample_ISR, ISR_SAMPLE_INTERVAL, uSec, TIMER7);
    timer_started = true;
  }

// Print the latest available power values every PUBLISH_TIME 
  if (sample_is_complete && ((currentMillis - prior_publish_time) >= PUBLISH_TIME)) {
    Serial.printlnf("Power: %.1f Watts   sTime: %.2fms   power(raw): %d", power_uncalibrated * POWER_CALIBRATION_CONSTANT, (ISR_SAMPLE_INTERVAL/1000.0), power_uncalibrated);
    prior_publish_time = currentMillis;
    sample_is_complete = false;
  }

}



void Sample_ISR(void) {

#define VOLTAGE_OFFSET 2034   // previously measured offset
#define CURRENT_OFFSET 2018   // previously measured offset
static long sumP;
static uint32_t sample_counter = 0; 
int16_t i_sample, v_sample;

  if (!sample_is_complete) {
    i_sample = analogRead(A0)-CURRENT_OFFSET;  
    v_sample = analogRead(A1)-VOLTAGE_OFFSET; 
    sumP += v_sample * i_sample;      //Sum the instantaneous power
    sample_counter++;
  }

  if (sample_counter >= SAMPLES_PER_CYCLE) {
    power_uncalibrated = sumP/sample_counter;
    sample_counter = 0;
    sumP = 0;
    sample_is_complete = true; 
  }
}


SAMPLE OUTPUT from this sketch (prints instantaneous power every 2 seconds)

Power: 230.3 Watts sTime: 0.33ms power(raw): 295116
Power: 230.9 Watts sTime: 0.33ms power(raw): 295897
Power: 231.6 Watts sTime: 0.33ms power(raw): 296746
Power: 231.6 Watts sTime: 0.33ms power(raw): 296776
Power: 232.3 Watts sTime: 0.33ms power(raw): 297621
Power: 231.2 Watts sTime: 0.33ms power(raw): 296268
Power: 231.2 Watts sTime: 0.33ms power(raw): 296289
Power: 231.7 Watts sTime: 0.33ms power(raw): 296892

This looks promising - I think you’re on the right track.

It’s a measure of the power you are apparently drawing if you measure voltage and current separately (using an ordinary multimeter, say) and multiply the readings. Hence the name.
It relates to power factor, which should be on the pump’s label, and hence to current, hence to the wire size, switch ratings etc you need to use. A poor power factor means higher current and so a bigger wire size, and the poor power factor means the load is highly inductive (or capacitive), which reflects on the rating of the switches you need to control it - a switch rated at say 10 A resistive might be only 2 A inductive.

Or in terms of relating to what your supplier charges you - not a lot. :laughing:

Indeed it is. Though you can expect both resistors to drift by about the same percentage, there’s no guarantee of that.

60 milliHertz ? an attack of digitus erroneous?

I note you’re using the calculated sample rate and count to determine what a cycle is. That will be OK if the frequency is tightly controlled where you are, and you’re only measuring over 1 cycle. In the UK, it’s guaranteed only within ±1%, so over 10 cycles we could be 5 sample pairs out - quite significant, which is why we are worried about the ‘end effect’ I mentioned earlier.

I presume that because your load is fluctuating, you’ll sample your one cycle fairly often.

I also see you’re not trying to take account of the phase and timing errors except as part of your overall calibration - phase errors coming from the current and voltage transformers, and timing from reading the voltage and current one after the other. If you calculate power factor, you could well find that swapping the order of reading will make a difference - in which case you need to get the power factor closest to unity with a pure resistance as your load. In emonLib and emonLibCM, we interpolate between successive voltage samples to apply the correction. You can expect the power factor to vary according to the load on the pump.

At the cost of accumulating the raw samples separately, you can correct the offsets after the event - calculate the average voltage and current for your 1 cycle (to give you the average error in each offset) then subtract the “offset power” from sumP.

1 Like

Robert, thanks for the reply…wow, there is a lot of information in that post!

Yes, haha…edited…I have been thinking in mSecs quite a bit.

I am going to see how my testing/characterization goes…For my purposes, I am hoping to ignore this frequency variation completely, :wink:. But, you will see that errors could compound based on my plans below (measuring over multiple cycles).

My goal is continuous (at whatever discrete minimum sample rate I end up with), but that will require some changes. I don’t want to overload my existing pool controller firmware with too many interrupts. I could implement a “fast/accurate” mode and ONLY use it during my characterization process. But, I’d rather keep it “on” all the time, if it turns out to give me “enough” accuracy…TBD.

Some of that was planned (ignoring the sample time differences between the v & I), some of my choices are through blind ignorance. Besides my pool pump, I am also planning on monitoring the power of my Stenner pumps (only one is on at a time). So I am keeping the other side of my voltage sample “free” so that I can sample the Stenner current on the other side (voltage sandwiched between the two current measurements). But as part of my efforts, I will definitely swap the order to see what impact it may have on accuracy, as you have suggested.

The Particle.io Photon’s implementation of analogRead() is interesting. It has 10-bit accuracy (which I probably don’t need), and in firmware it actually takes 5 successive adc readings and averages them to give the user the end result. The default, and most accurate, sample time for each of those adc readings is 480cycles (I don’t know the frequency), and that translates to an execution time of 80uSec for the analogRead(). To this point I have been running at a sample time of 144cycle/adc sample…which corresponds to about 27uSec execution time for analogRead(). It can go even faster, and I may test some of those values. I assume that lower execution time for the analogRead()s translate to less phase differential in the v/i readings.

Good idea, and I will look into this a bit later…partly because I want to explore this idea a bit more first:

I have tested a fair amount on an earlier idea I approached you with: spreading out samples over multiple cycles but still based on the discrete times associated with sampling over one cycle. Intuitively, it just makes a lot of sense to me…and with my simple resistive loads/hair dryer/floor fan testing, it has been as accurate as taking all the samples over a single cycle.

I realize that a relatively “quick” changing load (my pool pump during IFCS operation) is the situation that is going to stress this approach. So I am going to setup up some firmware monitors to see how much accuracy is lost by doing it.

Like my (50_samples/1_cycle testing), the power readings for (50-samples/1_distributed_cycle) were within ~1% of actual for all my simple test cases.

Possible Sample Rates for 60Hz & 50 samples/“cycle”

333 uSec, 50 samples are taken across 1 cycle
1 mSec, 50 samples are taken across 3 successive cycles
3 mSec, 50 samples are taken across 9 successive cycles
9 mSec, 50 samples are taken across 27 successive cycles
27 mSec, 50 samples are taken across 81 successive cycles
There are also more scattered in between some of those (most, but not all odd numbers such as 7ms, 11mSec, 13mSec, 17mSecs, more)

For all but the last (27mSec), the accuracy of using these various sample times was undifferentiated through my manual readings. But I want to implement some in-program checks before I test my pool pump so that I can be more accurate in my assessment. Based on the numbers I get from my pool pump, I obviously would choose the lowest sample rate that I think I need for my purpose.

Anyway, that’s where I am headed for a bit. I hope it makes sense.

That will be OK if the frequency is tightly controlled where you are,…

The North American grid frequency drift is actually quite small.
Typically on the order of ±0.05 Hz.

2 Likes