New library to read Arduino VCC supply level without resistors for battery powered sensor nodes that do not use a voltage regulator but connect directly to the batteries ;-)


  • Hero Member

    OK, now we are recapping the investigation JeeLabs did a year ago.

    I recommend these articles:
    http://jeelabs.org/2013/05/15/what-if-we-want-to-know-the-battery-state/
    http://jeelabs.org/2013/05/16/measuring-the-battery-without-draining-it/
    http://jeelabs.org/2013/05/17/zero-powe-battery-measurement/

    He did test the various circuits and values. The conclusion is that using a FET you can get the current drain even lower, but using 10 Mohm resistors and a cap he got the drain to sub-microamp.

    Once you get the drain down that low, the uC sleep current and battery self-discharge and capacitor leakage and any other sensors are going to dominate anyway. An open pin spec'd at +/- 1 uA, so even a sensor pin which you think is disabled may be drawing more current than that.

    Still, it can be fun to really go for the minimum possible.



  • @ ZEPH Good links. Pretty much says it all - including that in the cct posted above the divider could have leakage into the ADC I/P when the FET is off.

    Something else that's probably important is to measure the Voltage just before going into sleep, rather than when the CPU powers up. This gives a better indication of what the battery condition, because the measurement occurs a little while after the load has been applied to the battery. If you measure when the CPU powers up, the battery has the whole sleep time to "recover" from its last wake up. I'm pretty sure this could be demonstrated by making a start and end measurement and seeing what happens over time.


  • Mod

    @Zeph Nice, thank you for those links!


  • Contest Winner

    @Zeph Good. The third "conclusion" is pretty much what I had in mind as well. I am going to simulate it tonight, and see if it is possible to increase the resistor values. I think they are a bit small in my opinion, since it makes little use to reduce current consumption when doing the sampling, if the total consumption will be greater than using a low current divider.
    Regarding when to do the sampling, I agree with @a-lurker that this should not be done during boot. Rather, it could be done on "every hundred sensor sample transmission" or something like that as a first action (i.e. not when radio is running), or as a last action before sleeping.
    Ideally, a lot of samples could be taken and an average calculated, but that would probably defeat the purpose; to reduce current consumption when determining battery level.

    I'll get back with what I find.

    By the way, if we want to go fancy, there are a few commercial alternatives that provide a lot of probably over-the-top features, but they might be quite power saving:
    Texas Instruments: bq2010, bq2018, bq2019, bq2023
    Maxim: MAX1660, MAX1780
    Nat Semi: LM3822, LM3824
    Dallas Semiconductor: DS2438, DS2760


  • Mod

    So, this whole thing turned into something else ๐Ÿ™‚
    Maybe the thread should be split so that it is clear where to look later...

    The question I have is this, and it concerns wiring.

    From other discussions I understand it is better to wire the radio separately with the cap as close to the vcc and gnd as possible.

    Now, when doing the supply level resistors etc. is it preferred/better to wire these separately as well or can I wire the board and sensor(s) direct after/to the setup.

    I hope my question is clear...


  • Admin

    I can split, but what should the topic be?


  • Mod

    @hek said:

    I can split, but what should the topic be?

    Something like 'improved wired battery check' or 'better (power saving) battery check'...


  • Contest Winner

    I have run some simulations on a low-power solution using this setup:
    sim_schem.png
    Sorry for the somewhat messy schematic. For those of you unfimiliar with LTspice, this is what the above is:
    V1 is the battery to be measured. It's nominal voltage in this case is set to 3.3V. The voltage is stepped from 3.3V to 0 in 0.5 increments in the simulation.
    For some noise suppression, it is decoupled with C2 but this makes little difference for the simulation I have made.
    The battery voltage is fed through a PMOS FET (M1) before it enters the voltage divider. Below, I will use the term open for the FET when it is not conducting current and closed when it is.
    The FET is by default tied in the open state using R3 as pull up to Vin. M1 is closed by grounding it's gate, or in this example by pulling Enable low from the MCU. V2 in this example serves as a crude simulation of the MCU grounding the Enable signal after 0.05s in the simulation time domain (simulation is executed for 0.1s).
    The neat feature here is C1, which isolates the MCU output pin from the FET, thus preventing leakage through the MCU. When Enable goes low, M1 is closed momentarily, before C1 regains the charge from the pull from R3 and is opened once again. The value of C1 and R3 can be picked to suit the speed of the MCU (the MCU needs to take the sample before M1 opens).
    When Enable is left floating, any charge pushed into C1 is fed back to Vin, and is thus "free".
    This also allows the voltage divider to span the entire ADC range (depending on what ADC is used, internal references and such).

    Below is the resulting waveforms when using a Fairchild FDS9934 as FET (somewhat equivalent breadboard-friendly component could be this).
    sim_wave.png

    Note here the large span of V(sample) as well as the peak current at the largest voltage level (2.4uA). The current remains constant for a brief period of time (decided by C1 and R3) and then dissipates down to 0, even if Enable is kept low. The current can be reduced by manipulating R1 and R2, but the circuit becomes more sensitive to noise as the current used decreases (as can be seen for lower currents in the simulation, where capacitances in the FET start to make a difference.


  • Mod

    @Anticimex nice, thank you!


  • Admin

    Great stuff @Anticimex . But I understand just a small bit of it. ๐Ÿ˜‰


  • Contest Winner

    Thanks guys,
    I'll happily elaborate more on the details, but perhaps it is best if you state some specific questions regarding parts of it that are difficult to comprehend. Imo, working with sensors should not require a degree in engineering, so nobody should "feel stupid" for asking questions ๐Ÿ™‚


  • Mod

    @Anticimex said:

    Imo, working with sensors should not require a degree in engineering, so nobody should "feel stupid" for asking questions ๐Ÿ™‚

    When I have questions I will ask ๐Ÿ™‚
    But, like @hek, I need to let things 'sink in'.
    And I really want to understand.
    To be honest I have learned a lot (and spent a lot) since I stumbled upon MySensors.
    Wonderful new hobby!


  • Hero Member

    As long as you connect VCC direct to the battery I do not understand why people opt for using an external voltage divider optionally with a FET to reduce standby current. Additional components and current consumption while only a possible small improvement in accuracy.

    For the voltage divider the ADC reading is 1023 x R2 / (R1 + R2) x Vcc

    For the 1.1 Volt reference the reading is 1023 x 1.1/Vcc

    If you are using +/- 10% resistors (or the FET resistance is not measured correct or varies), the accuracy is more or less matching the (uncalibrated) bandgap reference method.


  • Mod

    @daulagari I guess the discussion depends on whether you have a software-mindset or a hardware-mindset.
    The software guys currently seem to form a minority on this board...
    I still think, after all discussions and distractions, that this way of measuring can be very usefull, when you understand the limitations.


  • Contest Winner

    I have not studied what support for measuring Vcc is built into the Arduino, but if there are support for doing that, I am sure it should be adequate. Regarding the external circuitry, my point is just that if you are going for an external solution, you might just as well design it to consume a minimum amount of current, as that is a one-shot optimization. Yes, it is a couple of extra components, but to me, that outweigh the limitations of the simple voltage divider in the long run.
    Personally, I would even consider a battery management unit. Such a thing should be able to handle both charging (if you want that feature) as well as readback (with battery health compensation).


  • Hero Member

    @Yveaux

    I guess the discussion depends on whether you have a software-mindset or a hardware-mindset.

    Being on this forum you are likely not having a hardware- or software-mindset only ๐Ÿ˜‰

    @Anticimex:

    I have not studied what support for measuring Vcc is built into the Arduino

    I think a study is not needed, the ADC ref power is VCC and there is a 1.1 V bandgap in the Arduino that you can measure; that's the whole trick.

    Yes, somewhat more funky like a battery management unit can for sure make sense.


  • Contest Winner

    @daulagari I see. Then as the whole topic suggests, it should suffice to use internal functionality to determine battery level if batt level = vcc. But some form of external circuitry is required if vcc is regulated. And I don't see a big reason to put a lot of effort into making a high precision solution for monitoring battery of "our" small nodes. But the current proposal of a simple voltage divider is a bit too wasteful imo (off topic).


  • Hero Member

    @daulagari said:

    As long as you current VCC direct to the battery I do not understand why people opt for using an external voltage divider

    For the voltage divider the ADC reading is 1023 x R2 / (R1 + R2) x Vcc

    For the 1.1 Volt reference the reading is 1023 x 1.1/Vcc

    An external voltage divider is useful only if you are NOT connecting the measured battery directly to VCC (ie: useful only if you are using a regulator of some sort between VBatt and VCC - whether linear, buck or boost).

    Your first calculation doesn't take the reference in to account. The reading is really:
    1023/Vref x R2 / (R1+R2) * VBatt. If VBatt is also VCC and VRef is also VCC, then the ADC reading is based only on the constant resistor ratio, independent of battery power (VBatt and VRef cancel out if both are VCC).

    So when using the default VCC as Vref, the Vbatt voltage divider is only useful when VCC is NOT VBatt.. in that case, if VBatt is the same as VCC, using an external divider is not an alternate technique with wasted components, it's just a non-starter period.


  • Hero Member

    @Zeph: Fully agreed.

    Your first calculation doesn't take the reference in to account. The reading is really:
    1023/Vref x R2 / (R1+R2) * VBatt.

    My formula's were for the case VCC = Vbatt but yes your formula is more generic but reduces to the same when VCC = Vbatt.


  • Code Contributor

    @Yveaux The only comment i have to this lib now then I'm using it is that you should not use floats but int instead, and just have an imaginary decimal point and divide at later stage to save program memory..
    And talking about this, I should probably start a new thread talking about optimizations, There are some to be done in the mysensors-lib also..


  • Mod

    @Damme I'm fully aware of the use of floating point and the penalties that come with it, don't worry.
    But I just poored existing code into a library. I didn't put any effort in optimizing it.
    Btw Arduino sketches tend to be very inefficient on resource usage, starting by using a 16 bit int type...


  • Hero Member

    Thread Rival ... ๐Ÿ˜‰

    So in trying to understand and improve battery life (currently using V div on Step Reg. Vin (VBatt) in my sensors, why can't I just measure the VCC on AO without the V div as VBAT will never exceed VCC,?

    Trying to figure out what fundamental I'm missing here....


  • Mod

    @ServiceXp So you want to connect VCC of the ATMega to ana analog input pin to read the supply level?
    If this is your idea, then the ATMega will measure the voltage on an analog input relative to the supply voltage. If the supply voltage of the ATMega starts to drop, the relative voltage measured on the analog input will not change w.r.t. VCC.
    By using a voltage divider you bring the voltage to be measured within 0,..,1.1V range (roughly). The ATMega has an internal 1.1V voltage reference which will remain stable when VCC drops, and thus can be used to meaure the supply level using a voltage divider.


  • Hero Member

    @Yveaux said:

    @ServiceXp So you want to connect VCC of the ATMega to ana analog input pin to read the supply level?
    If this is your idea, then the ATMega will measure the voltage on an analog input relative to the supply voltage. If the supply voltage of the ATMega starts to drop, the relative voltage measured on the analog input will not change w.r.t. VCC.
    By using a voltage divider you bring the voltage to be measured within 0,..,1.1V range (roughly). The ATMega has an internal 1.1V voltage reference which will remain stable when VCC drops, and thus can be used to meaure the supply level using a voltage divider.

    1. No; vBatt to AO; MCU will be powered by Step Up Reg. vOut.

    2. The MCU supply voltage will never be lower then vBatt. (in the case of 2 AA Batteries). vBatt will always be lower then MCU VCC, In all reality MCU VCC will never change in a significant way, until Step Up Reg drops out.

    3. think it's this v1.1 ref. that may be confusing me, but it just seems like this method should work with out the V div for sensors using 2 AA batteries or any <3.3v power source. ๐Ÿ˜‰


  • Mod

    @ServiceXp OK, I didn't really get your description in the previous post them.
    When VCC is stable due to to the step up converter then it should also work to just reference analog input to vcc. This way your measuring range is 0,..,vcc, which is a lot more then 0,..,1.1v



  • Thread revival.

    I have a sensor powered by 2 AA batteries, does this still stand as a simple way to obtain their status? It was super easy to implement!



  • Would this library also work on a WEMOS D1, which is powered by a esp8266?

    Paai


  • Mod

    @Hans-Paijmans no, it's avr only


  • Mod

    On esp, ESP.getVcc() can be used. More info: https://www.letscontrolit.com/forum/viewtopic.php?t=130

    Edit: use MySensors' hwCPUVoltage() instead. See below for more information.



  • Hi,
    possible to read also internal VCC for SAMD21 and NRF5 platform core?
    MiKa


  • Mod

    @MiKa no, it's avr only


  • Mod

    @MiKa use hwCPUVoltage(), this works for AVR, SAMD and ESP8266. ESP8266 requires defining MY_SPECIAL_DEBUG though.



  • @mfalkvidd said in New library to read Arduino VCC supply level without resistors for battery powered sensor nodes that do not use a voltage regulator but connect directly to the batteries ๐Ÿ˜‰:

    @MiKa use hwCPUVoltage() this works for AVR, SAMD and ESP8266. ESP8266 requires defining MY_SPECIAL_DEBUG though.

    Thanks ! It works on SAMD21E board ๐Ÿ™‚





  • @Yveaux Hi, thanks for your work. Maybe Iยดm going over something that was covered before, but I need some help, Iยดm using this code in a door sensor with 2 aa battery, and reporting if battery changes, when the door opens or closes. My problem is that I always get diferent readings from close to open, so Iยดm always reporting battery level and using more power than needed. Thanks


  • Mod

    @andredts the voltage reference only has limited accuracy, therefore the reported battery voltage might vary slightly. Also the load on the battery can change, causing a variation in battery level reported. Not a lot you can do about that I'm afraid.
    I experimented with sending all decreases in battery level wrt the previous value, and only large increases (eg 10% or more to detect change of batteries). Works quite well.



  • @Yveaux Thanks, that was exactly the insight I was looking, for my door sensor with 2aa battery, your way worked great. For a scene controller with a CR2032 a had to not send also decreases greater then 10%, but hey, 10 steps is more enough.


  • Mod

    @andredts cr2032 is a totally different story. The voltage level fluctuates significantly when sending messages compared to AA powered sensors.
    The 10% is only an example value and used for an increasing voltage level (that normally should only happen when replacing batteries). For a decreasing voltage (regular battery usage) you can just report the level and get much higher resolution. Question is if it will really be useful for cr2032 though...


  • Hardware Contributor

    How about storing last 10 values and send an average every time?


  • Hardware Contributor

    @andredts said in New library to read Arduino VCC supply level without resistors for battery powered sensor nodes that do not use a voltage regulator but connect directly to the batteries ๐Ÿ˜‰:

    @Yveaux Thanks, that was exactly the insight I was looking, for my door sensor with 2aa battery, your way worked great. For a scene controller with a CR2032 a had to not send also decreases greater then 10%, but hey, 10 steps is more enough.

    For having consistent measurements with a CR2032 you should measure voltage as first action after waking up from sleep.
    I keep the value in a variable and process it after "action" message of the node.

    If possible, run at 1Mhz on internal oscillator so the power consumption of the atmega stays very low (around 1mA instead of 3 at 8MHz/3V).


  • Mod

    I'd like to share my little experience with the 3.2V LiFePO4 AA batteries ad they are a very good solution since a single battery can be used and be directly measured through VCC without requiring any voltage divider or booster



  • @Yveaux I know about that fluctuation, but for my use in a scene controller I would be happy just to know the battery is low. I have it running with a multi-button, were I have click, duble-click and click and hold, I only check battery at one click, because of its fluctuation, but if you use it more than 4 times e a short period that fluctuation is noted, and that is why a added to the 10% increase a 10% decrease gap on battery sent information. Thanks



  • @Nca78 said in New library to read Arduino VCC supply level without resistors for battery powered sensor nodes that do not use a voltage regulator but connect directly to the batteries ๐Ÿ˜‰:

    @andredts said in New library to read Arduino VCC supply level without resistors for battery powered sensor nodes that do not use a voltage regulator but connect directly to the batteries ๐Ÿ˜‰:

    @Yveaux Thanks, that was exactly the insight I was looking, for my door sensor with 2aa battery, your way worked great. For a scene controller with a CR2032 a had to not send also decreases greater then 10%, but hey, 10 steps is more enough.

    For having consistent measurements with a CR2032 you should measure voltage as first action after waking up from sleep.
    I keep the value in a variable and process it after "action" message of the node.

    If possible, run at 1Mhz on internal oscillator so the power consumption of the atmega stays very low (around 1mA instead of 3 at 8MHz/3V).

    Hi, I do read the battery first thing after wake up, my problem was when a had various click too close together. It`s good now that I only send battery values that a 10% higher or lower than my last stored value. I will take a look on the 1Mhz bootloader. Thanks


  • Mod

    @andredts you could make an average of the last 3-4 reads before sending the battery value


  • Mod

    is it normal that just swapping a pro mini I am getting a voltage reading difference of 0.12V from same node?


  • Mod

    @gohan the internal reference is specified to be 1.0 to 1.2 V (see "29.5 System and Reset Characteristics" in the datasheet)

    So the voltage will vary between different chips.


  • Mod

    Btw, what is the maximum voltage that you can read with this vcc library?



  • Hi guys, I plan to use a battery powered temperature sensor - 2xAAA batteries i.e. 3V plus a cheap thermistor with a series resistor. I think I shall use the internal 1.1V reference with a resistor divider like 1Meg and 470K to measure the battery level.
    But ... I think I can use two Arduino pins configured as outputs (one output would be HIGH and another would be LOW) to connect the resistor divider instead of connecting the divider directly to VCC and GND - this way the resistor divider would draw current only when the sensor is awake and thus saving power. It would be more simple than using an external transistor to enable the resistor divider.
    Same goes for the temperature measurement, use another pair of pins configured as outputs to connect the thermistor and the series resistor.
    I have tested this idea using the Nodemanager "setPowerPins" function, I can easily measure temperature this way and draw current only when the sensor is awake. After making the measurements all outputs are set LOW (no resistor divider can draw current) then I put sensor to sleep.
    What is your opinion? Is there any "weakness" in this idea?


  • Mod

    @iahim67 I'm missing what your request has to do with the vcc library



  • @gohan sorry, my bad, nothing to do with vcc library ... just realized that vcc lib allows me to measure vcc without resistor divider:-)


 

374
Online

8.1k
Users

8.9k
Topics

95.1k
Posts