I’ve been working on a prototype for an updated jam jar node, after the success of the ukhasnet hackweekend in 2015 and felt that actually jam jars are a good enclosure for floating nodes. The jam jar node that we launched (AI3) ran on batteries which would have only lasted a few days so ideally we want to put together a node that is able to charge its batteries. As noted in previous posts I have been looking at using supercapacitors however in this case going with a LiPo battery is probably best as it will allow the node to work overnight.
It would be therefore be helpful to have a method of monitoring the battery voltage both to allow easy experimentation but also allow the node to have some smart energy management (e.g if battery is low don’t transmit as often). Usually you would use a ADC with a resistor divider to read the battery voltage however the LPC812 (unlike the ATmega328) doesn’t have a full ADC. Luckily there are other ways of using the internal hardware in the LPC812 to act like an ADC and helpfully other people have already investigated this!
Method 1: Measure input VCC using comparator and resistor ladder
(Check out Jeelabs for more details)
This approach uses an internal resistor ladder and the internal comparator (decides whether the input is higher or lower then a reference). We setup the resistor ladder (31 steps) with Vcc and then compare the 0.9V internal reference with this. Starting at the bottom we work our way up until we find the step that equals 0.9V, and from there can calculate the input voltage. This is best shown with an example:
- We input an unknown voltage to VCC
- Setup the resistor ladder (each step is 1/31 of unknown voltage)
- Starting from step 1 we work out whether it equal or greater than the known reference voltage of 0.9V
- In this example we find that step 9 fits this
- Therefore 0.9V/9 = 0.1V per step and therefore 0.1V * 31 = 3.1V
I’ve been using this setup on my supercap nodes as they run without an external regulator to take advantage of the range of input voltages that the supercap can provide. However for the LiPo based node I need to use a voltage regulator for the GPS and so would need to have the LPC812 skip the voltage regulator. To try this out I cut the trace for voltage to the LPC812 and diverted it via a diode (to drop the voltage down a bit). While it did work I found that it was incredibly inaccurate as the difference that could occur with the battery (3.3V up to 4.2V) is only 3 steps difference.
Method 2: Measure Vcc using comparator and resistor ladder on ACMP_2
(Check out Nano-Age for more details)
Instead of measuring the input Vcc we can instead measure the battery voltage by passing it through a resistor divider and then into ACMP_I2 which is a fixed pin on PIO0_1 which on the LPC812 is pin 12. Unfortunately I’m already using this pin for SPI to the radio so had to cut the trace and due to the brilliance of the switch matrix I just had to move SPI0_SCK to PIO0_6 (10) and run a separate wire.
Using the code from the nano-age blog we can use the function read_adc2() which uses the same concepts as Method 1 comparing the voltage to the resistor ladder. After trying a few different input voltage I was able to work out a adjustment factors to turn the reported value into a rough mV.
The main issue with this setup is the poor resolution, each step on my current setup equals 136mV and due to the range of the battery (3.3V – 4.2V) we are only going to get 7 steps (though more likely 6) but its better then Method 1.
Method 3: Delta-sigma modulation
(Check out Jeelabs for more information)
This is probably the best method as it creates a pretty good ADC rather than being stuck with using the internal resistor ladder. The approach is to use the comparator and an additional digital output to create a loop, varying the voltage to find where it matches and therefore calculate the input voltage. The code is a bit more complicated but is described really well on Jeelabs and will be great to get it working.
Currently I’m using Method 2 to measure battery voltage on AI4 but will eventually would like to switch to using Method 3 as it should give a lot better resolution. The code is currently setup using #defines for either #ADC (using Method 2) or #ACMPVCC (using Method 1) as it allows me to use the same codebase on different nodes.