Battery powered sensor AC voltage drift

I built a battery powered voltage sensor that uses a PCB transfromer instead of a hard to find bulky AC-AC adapter. I wanted it to look the least invasive so from the tiny box, there’s only a wire with a plug on the other hand.
It uses an NRF24L01+ to feed the data to the gateway. As with many other pesky NRF24L01+ modules, that one failed to enter deep sleep mode and kept the power usage at about 1.8mA during the sleep stages instead of the normal approx. 50µA. And not keeping an eye on the graph to see the battery draining out, it died within a few days.
However, I could see a slope in the voltage reported by the sensor along with the battery percentage going down.
So it seems that when the battery voltage drops, the measurements are affected as well. I made a rough calculation of about a 10% drift just before the battery was depleted.
Is there any way of avoiding this other than using two 3.7V batteries and a step-down converter that would drop the 7.4V to a constant 3.3V? Maybe use the Arduino 1.1V internal referance voltage? Two batteries raise the cost, they would drain faster due to the regulator’s quiescent current and make the sensor bulkier so I’d rather go for a smarter alternative if possible.

You hint that you might be using an Atmel 328P. If you happen to be using emonLib, then if you don’t specify the emonTxV3 bit, the library can measure the ADC reference voltage to maintain calibration as the supply voltage falls.
Or you could look at the step-up regulator that’s used in the emonTH.

How can I do that? I am using ATmega328P with emonLib, however, I only found this in the EmonLib.h:

#if defined emonTxV3
   int SupplyVoltage=3300;
   int SupplyVoltage = readVcc();

Should I just add int SupplyVoltage=readVcc(); at the very top of the sketch or just comment out the whole if statement in the EmonLib.h and replace with the above variable?

As I mentioned, I’d like to keep the costs and footprint at a minimum without sacrificing the sensor’s accuracy, thus using a voltage regulator is the last resort. For that particular sensor, I could switch to using a 5V AC-DC adapter and a MCP1702-3302E/TO instead of the CR123 battery, however I don’t like having to use two outlets, one for the AC-AC transformer input and one for the AC-DC adapter.
I may also use a 14250 3.7V battery and an MCP1700-3002E/TO, however this would mean that when the battery reaches 3.0V, I’d have to consider it depleted for its purpose even if it would still drive the ATmega328P and the NRF24L01+ module for a couple of more years.
Another option I took into consideration was to use a map() function that would dinamically adjust the calibration variable according to the battery voltage but this would only work for a linear drift. And I’m not even sure that the tests performed with a variable voltage PSU would apply in real world with a battery.

I think you need to read up on how preprocessor directives work. In the header file, it includes one line or the other depending on whether you have previously defined “emonTxV3” with a #define. Therefore, all you do is not include that, and, if you trace through what the library does, you’ll see how if figures out what the “external” reference voltage (the battery voltage) actually is, using the internal reference. Bear in mind that although the internal reference is very stable, its value is not known accurately, therefore look in Resources > Building Blocks to see how to accurately calibrate your system.

Neither do we! That’s why we have the power supply arrangement that we have in the emonTx. That probably won’t be suitable for you without redesigning it, as the current required for your radio is likely to be much larger.

I did not included the

#define emonTxV3

directive in my sketch.

However, it may be that my code interferes with the EmonLib. I have this in my sketch:

long readVcc() {
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  while (bit_is_set(ADCSRA,ADSC));
  uint8_t low  = ADCL;
  uint8_t high = ADCH;
  long result = (high<<8) | low;
  result = 1125300L / result;
  return result;

I’m using it to report the sensor’s battery status to the gateway.
Unfortunately I’m a few hundreds kilometers away from the sensors in question so there’s no way to test it now but I will do some tests with a CT sensor and an adjustable voltage regulator using the original function name as well as renaming it and get back with my findings.

We know the original library works, as do the demonstration sketches. Why don’t you download known working versions and then see what you have?
I don’t have time at the moment to investigate code that’s been changed.

I just finished testing a CT sensor with a variable voltage regulator. It’s clear that be battery voltage has no effect whatsoever on the reported current usage. I tested between 1.8-3.5V. Except for the large spikes during the voltage variations, the reported current values are very steady throughout the entire range.
I will build another voltage sensor and perform the same tests as that is built with an entirely different circuitry.
Thank you for your support with this.

So, that has quickly and easily removed several possibilities from your list, and you need to look elsewhere. Of course, the 328P is only guaranteed to operate over the range stated on the data sheet, and if the supply goes outside that range even for an instant, nothing is certain. I’d suggest that you need to make sure that the transmitter is not turned on while measurement is in progress, and you have sufficient capacitors in parallel with the battery to help it support any short current surges.

If you’re running it at 16MHz I think you need to ensure Vcc never drops below 3.78V if I’ve done the arithmetic correctly.

There’s no reason to run the ATmega328 at 16MHz. That would require an external crystal oscillator and it would drain the battery faster. I’m not sure that this would have an impact on the speed of the measurements though.
I noticed that the standard sketch takes 1480 readings of the current. I lowered that to 500 to shorten the awake cycles while keeping the measurements relatively noise free.
I wonder though if a large capacitor and a diode would smooth the AC curve up to the point that only 10 readings or so would provide a steady reading :thinking:.
That would greatly improve battery life as one thing I learned during my experiments is to use fast conversion sensors (eg. the fast Si7021 instead of the sloooow DHT22 or avoid the DS18B20 unless I don’t care about the resolution that much).


You can still run the ADC at 125kHz but the maths will take twice as long. See also About ATMEGA328P with 8Mhz internal oscillator crystal. Standalone

What is it you’re trying to measure? Real power? Do you want a steady reading, or an accurate reading? If you want an accurate measurement of Real power, you want those AC signals to be as undistorted from the original as possible.

I concur. Any sort of filter on the input signals will distort the truth.

The goal is measuring the real power. My limited experience with electronics tells me that a capacitor would smooth the spikes. The standard sketch requires 1480 measurements to return the current usage RMS, each yielding fairly large spikes. However I’m not suggesting using a supercap that has a high inertia and could indeed distort the truth up to the point that you wouldn’t be able to distinguish a hairdryer running for 5 minutes. But maybe a small cap in the range of nF would lower the required polls to 10 or so. That would have a serious impact on the ATmega328 awake/sleep cycles and battery life.
Steady or accurate? It depends on the resolution you’re considering. Yes, looking at time resolutions in the miliseconds range, a cap may distort the truth and hide microbursts but is anyone out there who’s storing historical power usage statistics down to miliseconds?
So I’m not considering that an alternative way of normalizing the read values distorts the truth, unless of course a huge capacitor is used.

It would indeed do that, but of course there will be other unwanted effects too. You can read up about low pass filters to see what those are.

It does not do that. I don’t understand what you mean there. There will of course be steps between samples, you reduce the steps by sampling ever more frequently.

I think you have totally and completely misunderstood the concept here. The processor does not sleep between samples. If you are using emonLib, we measure a ~200 ms sample of the alternating wave, compute the rms, transmit the result and then sleep for 10 s.

Just bear in mind that some of us round here have made our living with electronics and electrical engineering for some tens of years.

I will do that.

I mean the value of each of the 1480 samples taken during a readout.

It’s not the case, but perhaps I wasn’t clear enough. I was refering to the cycles between the reports. Eg. the 60 seconds that the sensor enters deep sleep before waking up to take the next mesurement. 200ms is a very long time to keep the sensor awake during readouts while aiming for using a single cell for years. This is why I don’t use the the DHT22 and not even the way faster HTU21D or SHT21 but chose to use the super-fast high resolution Si7021.
I didn’t make the math just yet, but an educated guess tells me that a 200ms/10s cycle gets you a few months on a battery while I aim for at least 5 years with a CR123 or 14650.
Thus my obsession with very fast conversion times.

I totally agree and this is why I’m seeking advice with the elders :stuck_out_tongue: as I barely scratched the surface with electronics.

Now you have me totally confused. What have humidity and temperature sensors got to do with sampling a waveform to measure rms? Nothing. Those are two quite separate problems.

Generally speaking, you can trade speed for current, or current for speed. If you want more speed, it tends to cost you more current. If you want less current, you must accept less speed. Therefore I think you are wrong to think that by spending less time doing something by doing it faster, you will automatically extend the battery life. In general, that won’t be the case.

:laughing: sorry about that. No, they have nothing in common, it was merely a comparison meant to highlight that I am aiming for the shortest conversion times possible.
Taking 1480 samples for a readout takes a few hundreds miliseconds. I need to have an accurate reading within less than 50ms ideally. I asked wether a small capacitor would smooth the readings up to a point that an accurate current usage value can be generated by 10 samples instead of 1480 and thus shortening the awake stage.
And considering that the sensor uses about 8mA while awake and only about 60µA when sleeping, I do want to keep the reading time to a minimum. That does have a great impact on the battery life.
You may already be familiar with this article:
And if not, you may already know most of stuff there, but it’s a great resource for beginners starting to tackle with the battery powered sensor nodes.

The reason for using 1480 samples was because, at the sampling rate that emonLib achieved, it equated to roughly 200 ms, which is an integral number of cycles in both 50 Hz and 60 Hz systems and is long enough for the “end effect” - the error caused by not having an exact number of complete cycles - to be insignificant. If you can be sure that your mains frequency is stable, then measuring one complete cycle should give exactly the same rms value as measuring 10 or 12 cycles.
(1662 samples is the optimal value now that the library has been better optimised for speed.)
But you cannot measure less than ½ cycle, which assumes you have no even-order harmonics present. If you do have even-order harmonics (i.e. there is some half-wave rectification happening somewhere), then you must measure the complete cycle, or an integral multiple of complete cycles.
Nyquist states that you must have at least two samples per cycle of the highest order harmonic that you wish to measure. If you have 10 samples per cycle that means the 5th harmonic. Any power carried in harmonics above that will be lost to you if you have an effective anti-alias filter, and if you don’t, those frequencies will appear as an alias and create even more errors. Whether significant harmonics will be generated will depend entirely of the behaviour of the loads on your system.

I understand (or at least most of it :-P). You mentioned though that anti-alias filter. Is that something that would help this purpose? And if so, how many cycles would require for an accurate reading? Or does such a setup complicate things up to a point that it becomes unreasonably to use? I’ve seen a few schematics for such a filter but I can’t say if it’s feasible or not considering that it clutters the PCB a bit.