Battery powered Arduino sensors

[quote=“derrij, post:20, topic:178451”]It is necessary to power up the radio all the time when waking from sleep. Or may be will be better to power up the radio if only temperature has changed .
Will it save some mA? Or radio needs some time for power up befor sending data?[/quote]

You don’t need to power up radio if you’re not going to send any data…

Brown out Detector (BOD) problems:

According to the spec the min Voltage at 8 MHz should be:
(( 2.7-1.8 )/2)+1.8 = 2.25 V

@ MDoc: when I lower my supply voltage to around 2.7 volts, the transmit light flashes rapidly just as you saw some type of oscillation) Once I raise the supply voltage, it stops and transmits normally.

I ended up having this problem as the batteries got tired. These two lines of code turn off the BOD during sleep to save power. When the sleep time is up, the BOD is turned back on again. This functionality is only available for some chips. Refer to the pages 39 and 44 of the ATmega manual:

“p44: BODS and BODSE only available for picoPower devices ATmega48PA/88PA/168PA/328P”

sleep.pwrDownMode(); // set sleep mode sleep.sleepDelay(SLEEP_TIME); // sleep for SLEEP_TIME

When the CPU is active, the BOD is on. This file sets the BOD threshold, when the CPU is flashed:

…\Arduino\hardware\arduino\boards.txt

In that file you will find:

Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328 ... pro328.bootloader.extended_fuses=0x05

This sets the BOD threshold to 2.7V (typical). As the power supply Volts goes below 2.7V the CPU resets itself continually ie oscillates, which then results in total destruction of the battery.

The brownout threshold is found in the “Extended fuses” - only the lower three bits are used and they are mutually exclusive and active low - pages 287, 312 of the ATmega manual:

[ul][li]0xFF or 0x07 Brown Out Detection disabled[/li]
[li]0xFE or 0x06 BODLEVEL0 1.8V (1.7-2.0)[/li]
[li]0xFD or 0x05 BODLEVEL1 2.7V (2.5-2.9) **** as used by the chip programmer[/li]
[li]0xFB or 0x03 BODLEVEL2 4.3V (4.1-4.5)[/li][/ul]

Not absolutely sure but I think that the unused bits always read high - however it doesn’t matter what you program them with. So you can use either of the hex values listed above or other mixtures - where the unused bits are either high or low. It’s only important to get the 3 lowest bits correct.

So to get the CPU to work down to 2.25 V (using an 8 MHz clock), then the fuse should be changed to:

0x07 to disable BOD
0x06 to change BOD threshold to 1.8V

As the the BOD is not much use on a battery powered device, it’s perhaps best to disable it completely using 0x07? Suggested addition to the boards.txt file (untested).

[code]##############################################################

pro328pBODoff.name=Arduino Pro or Pro Mini (3.3V, 8 MHz, BOD off) w/ ATmega328P

pro328pBODoff.upload.protocol=arduino
pro328pBODoff.upload.maximum_size=30720
pro328pBODoff.upload.speed=57600

pro328pBODoff.bootloader.low_fuses=0xFF
pro328pBODoff.bootloader.high_fuses=0xDA
pro328pBODoff.bootloader.extended_fuses=0x07
pro328pBODoff.bootloader.path=atmega
pro328pBODoff.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
pro328pBODoff.bootloader.unlock_bits=0x3F
pro328pBODoff.bootloader.lock_bits=0x0F

pro328pBODoff.build.mcu=atmega328p
pro328pBODoff.build.f_cpu=8000000L
pro328pBODoff.build.core=arduino
pro328pBODoff.build.variant=standard
[/code]

A few other ideas:
It probably makes sense to consider the actual CPU Voltage as the battery Voltage and use the technique as applied by @MDOC here to measure it:

http://code.mios.com/trac/mios_arduino-sensor/wiki/TipsAndTricks#Case3

If a battery step up convertor is used then the actual battery Voltage could just be returned as an interesting variable to plot. It’s the CPU Voltage that actually matters, no matter how it is supplied.

It is probably also advisable to send the Voltage just after having transmitted the sensor values. In that way, you get the Voltage after the battery has been hit hard by the transmit current. If you read it just after the sleep time, the battery has had time to recover.

A quick note on the code found here:

http://code.mios.com/trac/mios_arduino-sensor/wiki/TipsAndTricks#Case3

The constant 1126400L should be 1125300L.

1.110231000 = 1125300 correct
1.110241000 = 1126400 incorrect

Not that it makes much of a difference.

Also you can use ADCW to get the upper and lower registers in one.

[code]// Read the CPU supply Voltage
long readVcc()
{
long result;

// read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(5); // wait for Vref to settle after the mux change
ADCSRA |= _BV(ADSC); // convert
while (bit_is_set(ADCSRA,ADSC));

//result = ADCL;
//result |= ADCH<<8;
result = ADCW;

result = 1125300L / result; // AVcc in mV = 1.110231000 = 1125300

return result;
}[/code]