The first three tutorials in this series show how to build a promini based data logger that should sleep around 0.25mA, depending on the quiescent current of your sensors and your μSD card. That will usually get you to at least 6 months of operating life before a bank of three AA batteries in series falls below the 3.5v cutoff on your regulator, and most of our field units make to about 11 months on a good quality set of alkaline AA’s. With their flatter discharge curve, lithium AAs would probably have carried those logger past 12 months, but if you really want the logger to pass one year of operation you need to do a few other things that might be a bit of a stretch for beginners. So I am posting them here as “additional” things to tackle once you have built a few of the basic loggers and have them working Ok. Use the cheap parts till you get the hang of soldering and working out how you want your cables & housing to go together physically. I find that things usually go well the third time I make a new prototype.
Usually takes me about 20 minutes to assemble, or less with solderless headers. At any given time I probably have 6-8 of these breadboard loggers running on the bookshelf to test different hardware and code combinations. Be careful not to bump the SD card connections though, as its easy to kill the card with unexpected power interruptions.
Without question the most important thing you can do to extend the life of your data loggers is to build yourself a breadboard “testing platform”. This lets you determine the sleep current for each component on it’s own, making it easy to spot fake SD cards, or bad sensor breakout boards. And even good SD cards wear out with time , or are damaged by high temperatures. Checking that cards and boards go to into a low current modes properly (after the main mcu sleeps) is the best diagnostic I have found to determine if the components are Ok. Good SD cards sleep between 0.05-0.07 mA, and these tend to be older Sandisk 128mb cards. Typical cards pull between 0.07-0.09 mA while sleeping. Any more than than that and I simply do not use the card in my data loggers. The difference between a good sensor breakout board and a bad one can be even more extreme, and you should always look for breakout boards that have a native 3.3v input line to avoid regulator losses. I already mentioned pulling up three of the SPI lines, and the breadboard unit lets you easily test how other pin configurations affect the logger. Pin states are generally preserved during sleep, though any timer dependent functions (like PWM) will be shut down when the associated timer stops, unless you use ‘idle’ mode. Always avoid floating I/O pins.
All you have to do to retrofit any 3.3v mini-style board with a more efficient MCP1700 is connect the external regulators output directly to the 3.3v pin, which is the main power rail behind the default voltage regulator. This by-passes the onboard Vreg the same way that your UART board does when you are tethered to USB. When I do this modification I completely remove the original regulator from the Arduino board so there is no leakage current slipping through it while the logger is sleeping. Also be sure to move the high side of the resistor divider you have monitoring the battery voltage to the new regulators Vin line. Replacing the MIC5205 with a MCP170x will save you ~0.05 mA of sleep current, depending on your particular board. That doesn’t sound like much, but it all adds up over time, and you have 100 mA more current available to power your sensors.
When you test your components individually you notice that there can be significant differences from one pro-mini board to the next (especially with cheep eBay clones) and much of this comes down to the voltage regulator. Sparkfun Pro-mini’s use a Micrel MIC5205 150mA LDO Regulator, and there are more efficient options out there. I have had success with boards that use MCP1700 & MCP1703 regulators (datasheet) like the Rocket Scream Mini Ultra or the Moteino. Each board has a unique pin-out, so you will have to figure out where to put the jumpers for each particular board. You can also simply bypass the pro-mini’s on-board regulator and use an external voltage regulator (see the image posted at the bottom of that thread by fat16lib – don’t forget the 1 µF caps. MCP1700s @ < $0.50 ea here ).
Sleeping your processor & components at every possible opportunity is vital. If there is a power wasting delay statement left in your code anywhere, there ought be a really good reason for it (like waiting for your ADC reading to stabilize, etc)
You can flick the SCL and SDA pullup off the board easily with the tip of a soldering iron.
The next life extending technique is to add a larger I2C eeprom so that you can buffer more data before you write to the SD card. The functions I use to do this buffering is included with the I2C eeprom tester example I posted to gitHub. Eeprom power consumption limits to how far you can take this strategy, but switching from the 4K AT24C32 on that RTC breakout to a 32K AT24C256 provides a $1 way to extend your operating life by 5-10% depending on the amount of sensor data you are handling. The two eeproms are from the same Atmel family, and the wire.h I2C library limits you to 32 byte page writes, so all you have to do is change the bus address in your code and you are done! Same applies to the AT24C512 all the way up to the 2Mb AT24CM02 if you can find them. You can also lift & jumper the address pins (A0,A1) to enable up to four of these Atmel boards on the same bus. (and it would require some code tweaking, but you might also be able to swap some of the larger Microchip brand I2C eeproms into the cheap press fit DIP boards if you wanted bigger chips to play with. Or you could just roll your own breakout board for a whopping 1024Kb with the 24LC1025 and the 24AA1025 ) The logical end game if you go down the eeprom road is to abandon simple ASCII and start working with struct’s in C. Then you could store a years worth of data without any SD cards at all.
1. Remove the two pull-up resistors from the YL-90 breakout (if that’s the one you are using ) as the RTC board pull-ups are sufficient. Straighten the riser pins and trim them to about 1/2 length.
2. Cut 2” lengths of Black, Red, Yellow, and White wire. Solder them to GND, VCC, SDA, and SCL respectively. Shrink wrap the solder joints.
3. Clean the board with alcohol and let it dry. Apply conformal coating if desired and put a patch of double sided tape on the bottom.
4. The next step is to adhere the eeprom to your logger platform via the tape, so that you can cut the jumpers to length. If you left some excess wire protruding from the board when you added the bus interconnect for the sensor cap, it’s pretty easy to patch the four eeprom wires right onto the cascade port.
Sleeping & buffering are the low-hanging fruit, and after that you get into trickier techniques to improve the power budget. For example that new eeprom also lets you push the bus speed above the 100kHz default if your other I2C devices can handle it. I am still testing prototypes at 400kHz, even though that violates the Tlow spec on 8mHz AVR processors, so I am cautious about recommending that to everyone until I see those units deliver a year of good data. But the results have been promising so far...
Another useful modification is powering the RTC from a digital pin. For some reason I have not been able to dig out of the data sheet, the DS3231 pulls almost 0.1 mA when it is powered by the Vcc pin. Fortunately, you can force the IC into a miserly 3μA timekeeping mode if you draw that Vcc pin down, and if the Battery-Backed Square-Wave Enable register bit is set the RTC will still generate alarms when running off of the backup battery. But the soldering for this is a bit tricky:
1. After removing the power LED & charge circuit resistors from the RTC board, wedge a fine tweezer tip behind the power pin and apply an iron to the pad on the board. When the solder melts gently lever the pin away from the board.
2. Then tin the pin, and solder a jumper wire to the lifted power pin, being careful not to bridge any of the other connectors in the process. I usually secure the jumper wire to the board with a zip-tie so that no physical stress can be transferred to that tiny solder connection later.
At that point you can attach the jumper to a free digital pin on your Arduino, and use digital.write(pin#,HIGH/LOW) to power to the chip only when the logger is awake. My pin-powered builds have eight months under their belt now, and by spring 2016 I will know if the CR2032’s can provide enough power to drive the RTC in timkeeping mode for a full year. (2016 note: they all made it!) I am trying to track the coin cell status with another voltage divider on the breakout board, but since lithium cells keep their nominal voltage until they are completely dead unless you provide a load, that record might not give me any useful information. I will post updates on those experiments on my RTC page as they become available. (Note: Even with the default MIC5205 reg on the promini, pin-powering the RTC like this should get your logger down to ~0.17mA sleep current)
By testing components, changing regulators, buffering, and pin powering the RTC, I am now seeing power curves like this:
This unit had a TMP102 temperature sensor, an MS5803-02 pressure sensor, and an HTU21D RH sensor attached, and it still took four months to burn off the over-voltage on 3 AA Duracells. (with a 15 minute sample interval) The logger slept at 0.15 mA because all those sensors all have great low power sleep states.
Though I have reached my original one-year goal, I still keep an eye out for other ways to save power. Several people have explored using a MOSFET to de-power the SD cards but according to the fellow who actually wrote the SdFat library, there are some issues wrt multiple re-starts of the SD library . He also warns that you have to close all files and allow at least one second for the SD card to power down before pulling the plug, just in case you accidentally trigger some internal housekeeping event with the file close command. The folks over at OSBSS claim they can switch the low side without problems and Nick Gammon seems to be having success with his THL logger switching the high side, though those two examples leave me wondering which way to go. Some set all the SPI lines HIGH & INPUT before powering down to prevent parasitic leakage after the cut, though the guys at Solarduino imply only the slave select line is vulnerable to the problem, and suggest that line won’t leak if you switch the low side (?).
Another potential factor is low 3.3v I’m using to control the FET, discussed here at CMicrotek’s Low-power Design Blog:
“When using a P-channel FET to drive a load, a GPIO may not drive the gate high enough to completely turn off the FET so you may be leaking power through the FET. This can often go un-noticed since the amount of power is too low to activate the load. A P-channel FET of similar rated voltage and current as an N-channel FET will typically have 50-100% higher Rds(on) than the N-channel FET. With Rds(on) specs on modern FETs in the double-digit milliohm range even doubling the Rds(on) produces a fairly low value. However, that is simply wasted power that can easily be eliminated if low-side switching is an option for your application.”
Reading that makes me lean towards low side switching; though the 2n7000s in my parts bin probably can’t be fully turned on with only 3.3v on the base? (Note: there are beefier N-channels out there that will work with a 3.3v system if you are also de-powering high current sensors) Luke_I has proposed using SPI.end() to kill all SPI communications once all files are synced and closed but most people simply set the SPI control register SPCR=0; When you restore power after low side switching you have to reset SCLocK(D13), MOSI(D11) & CS back to OUTPUT (MISO stays at input) and set the SCLock line LOW to disable that pullup. Then you reinitialize the SDcard with sd.begin(chipSelect, SPI_FULL_SPEED); and reopen your files. Several sources have suggested that only SdFat allows this re-initialization , while SD.h does not.
One possibly important thing to note is that the sandisk datasheets states (pg 11)
“Power must be applied to the VDD pin before any I/O pin is set to logic HIGH. In
other words, CMD, CLK, and DAT0-3 must be at zero (0) volts when power is
applied to the VDD pin. “
But perhaps this only applies when accessing the cards in their native SDIO mode? But this does make me wonder if you are supposed to turn on the mcu’s internal SPI peripheral before, or after you restore power to the SD card (?) I think that datasheet suggest you should be doing it after, but they are switching the high side in that example case.
You can extend that strategy and cut power to the entire logger. As I mentioned in the RTC post, the most elegant way to do this would be using the RTC alarm (outputs low) to control a P-channel Mosfet on the high side of the main battery supply. When the INT/SQW alarm goes low, this turns the mosfet on and powers everything including the main mcu board which would then goes to work taking samples and storing data. Unfortunately some of my builds use interrupts from both the RTC and the sensors, and there is a good chance that with these frequent startup initializations the resulting delays could miss the phenomenon I was actually trying to capture; like tipping bucket or wind sensor reed switches.
Just thought I would post another shot of a retrofit with an MCP1700 voltage regulator:
Note: I used a 6 volt input MCP1700 here, but the MCP1703-3302E/TO accepts up to 16v
…with the addition of a 2 x 4.7 MΩ voltage divider to put 1/2 of the RAW input voltage on A0. Note that the onboard vreg has been removed (normally you would see it just under the cap in front: you can see some of the empty pads still there) and the two led limit resistors have also been pulled. Other than the mcu there is not much left but the crystal & some caps, and I now think of the board itself as simply a convenient breakout for the 328p. This retrofit with an MCP1700 looses the shutdown enable functionality of the default MIC5205 (marked KBxx or LBxx), and the noise suppression features, but I am hoping the caps are enough to deal with that. The 1700’s are more efficient at low power than the 5205’s which limp along at about 20% efficiency below at 0.1mA, and loggers typically spend 99.9% of their time sleeping. The XC6203E332PR is another low-ish standby power option if you need output currents in the 400mA range.
On late 2016 builds I started moving the replacement voltage regulator & battery divider away from the Arduino to the battery connector. Given that this is now separated from the caps on the main board, I’m using ceramic 105’s on the MCP1700 as per the spec. Three wires run from this deadbug back to the pro-mini: 3.3v, GND, and 1/2 battery voltage from that 2x10M divider, which gets read on an analog pin.
Keep track of the capacitors if you change the voltage regulator, as the ones on the outgoing side are still connected after you remove the original reg. Sparkfun promini’s have a pair of black 10µF C106 smd caps on either side of the MIC5205 (& an extra 0.1uF on the output side). Several of the clones I checked match that layout, but others had a pair of 0range & brown tantalum 475C SMD capacitors (4.7µF). The MCP1700’s call for a fairly small 1µF on either side. Since my loggers are powered by a relatively large battery with little chance of brown out and no input noise, I have not been too worried about adding a big cap on the input side (often people add up to 100uF..?). I could probably get by with the output side caps already on the Arduino board, but I have been adding the ceramic 104’s (0.1µF) anyway, as I’ve seen a few forum posts suggesting that you get better noise suppression by using multiple capacitor chemistry-types with different ESR on outputs. And I am still careful to add 0.1µF ceramic bypass capacitor from +V to GND on every sensor IC.
If you combine a pin powered RTC, with the MCP1700 retrofit, and you have a good SD card, it’s not unusual to see the logger platform sleeping below 0.1 mA, even for units built with cheap eBay clones. The pro-mini style board is only responsible for about a third of that after the retrofit.
It would be a good idea to re-read Nick Gammons post on Power saving techniques for microprocessors, as much of what I’ve done to optimize these loggers is covered in more detail there. For folks who want to take it farther, there’s good background info on low power design in Granssle’s article: Issues in Using Ultra-Low Power MCUs. And Hackaday’s post on TI processors shows how far the art in low power operation goes.
Kevin Darrah has been posting some brilliant you-tube tutorials on lowering the power consumption of an Arduino. This includes a kill power circuit, which has been on my to-do list for quite some time now. Definitely worth a look. The rub of course is that you then have power-up latencies for everything. That’s probably around 75-100 milliseconds for a typical Arduino, SD card initialization would probably be about the same (ie about 5 milliamp seconds) and a couple of sensor inits could easily double or triple that total. So you could burn up to 25 milliamp seconds for the restart. Even with a sleeping SD card drawing power, a logger built with the optimizations discussed here usually sleeps at 0.14 mA or less. So a regular startup is probably equivalent to ~3 minutes of sleep time, and it would take several more minutes of sleep time power to match a really bad 1 second startup if you had some pokey sensors. So it all depends on how much time you need to get everything operational. As best I can tell, I am still getting operating life that compares well to some of the power down approaches people are using.
Another tip for saving power is to always use high output LEDs, and to use the green as a status indicator color whenever possible. Why? If you look at the typical rating for a high output RGB you see Luminosity numbers like: 800R, 4000G & 900B mcd. That means that you can use a limit resistor that’s three times larger on the green channel for about the same light output. I often get away with 30K on the ground line, and an extra 20-30K on the green line of a common cathode LED, and I’m still able to see the indicators with pulses in the 10-15 ms range. With that much limiting resistance, the LEDs don’t impact the power budget at all. LEDs tend to stay lit for a relatively long time after they are turned off so switching the LED on/off with a 50/50 duty cycle at a rate faster than 1Khz will cut the power by half with an imperceptible reduction in brightness. While I would never leave an led on all the time for a datalogger application, if your application needs a power on indicator, consider a slow flash of the LED (for ½ second every 3 seconds) instead of having it on constantly.
With my hardware reaching reasonable sleep currents, I guess its finally time for me to look at reducing the run time power use by turning off unnecessary peripherals with the power reduction register. Heliosoph posted tests results from his capacitor powered project, with a reminder about grounding unused pins. There are some 3.3v numbers over at avrProgrammers and Nick Gammon weighs in with some sage advice on his forum. Each peripheral doesn’t use much on it’s own, but together they total up to ~1mA that is just being wasted. Here’s a few of the things I’m currently experimenting with:
- Disable the digital input buffers you aren’t using with DIDR0
- Never leave floating pins – always use a pullup or pulldown resistor.
- Disable unused module clocks using the PRR register
- Especially the ADC with ADCSRA &= ~_BV(ADEN);
- Shut off the analog comparator: ACSR |=_BV(ACD);
Here’s how those look in code:
//defines for DIDR0 setting
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
// create variables to restore the SPI & ADC register values after shutdown
// then be sure to store the default register values during setup:
keep_ADCSRA = ADCSRA; keep_SPCR=SPCR;
// 1) where the ADC pins are being used, disable the digital input buffers
//2) set unused analog pins to digital input & pullup to prevent floating
pinMode(A3, INPUT); digitalWrite(A3, HIGH);
//3) And pull up any unused digital pins:
// Disable internal peripherals that you are not using:
// Note to self: Don’t mess with timer 0!
power_timer1_disable(); // (0.12mA) controls PWM 9 & 10 , Servo library
power_timer2_disable(); // (0.12mA) controls PWM 3 & 11
power_adc_disable(); // disable the clock to the ADC module
ADCSRA = 0; // disable ADC by setting ADCSRA reg. to 0 (0.23mA)
ACSR = B10000000; // disable comparator by setting ACD bit7 of ACSR reg. to one.
power_spi_disable(); // disable the clock to the SPI module
SPCR = 0; //disable SPI by setting SPCR register to 0 (0.15mA)
power_usart0_disable(); //(0.08mA) but only if your are not sending any output to the serial monitor!
// power_twi_disable(); // (0.18mA) I don’t usually turn off I2C because I use the bus frequently
// Shutting down ADC & SPI requires you to wake them up again if you need them:
// Before any SD card data saving:
power_spi_enable(); SPCR=keep_SPCR; delay(1);
// Before ADC reading:
power_adc_enable(); ADCSRA = keep_ADCSRA; // & throw away the first reading or two…
Still to explore: Lower the CPU clock & then using a lower voltage power source.
Slowing down the processor doesn’t help much if you are trying to minimize processor up time, but if you get into a situation where you are forced to keep the Arduino awake, you could try to reduce the power consumption by slowing the main system clock. I’m not brave enough yet to make new board definitions & mess with the CLKPR system prescaler, since I have so many sensor communication events. Delay and millis I can deal with, but Timer0 PWM, ADC and probably a few other things have to be set in conjunction with CLKPR to keep them running at the right speed. Slower clocks let you reduce the whole system voltage, but I still need to 3.3v because of the sensors & SD card. Fuse setting still seems like the dark arts to me, and I’m not sure shutting down the BOD is a great idea for data loggers…
After you apply the optimizations described above the sleeping µSD card becomes the biggest power drain left in the system. So I should probably add a reminder here that there is a huge difference between SD cards that sleep well, and those that don’t. Sandisk cards smaller than 1Gb tend to have lower idling/sleeping current modes ~70µA, but it’s not unusual to see new large capacity cards drawing 200µA. (I’ve seen spec sheets floating around the web for special TwinMOS mircoSD cards, listing incredibly low sleep & write currents, but I have never managed to find any for sale.) Cards between 64-256mb usually give me the lowest sleep currents, but because those older cards have to be purchased from eBay, there is also a significant difference in their speed when I test them with H2testw, with some being slower than 2.0MBytes/s, and others saving at 5MBytes/s or better. I presume that is because used cards get slower due to the onboard wear leveling circuitry working to avoid the accumulated bad spots, and the SD latency spec is worse than all of those, allowing a card to take as long as 250ms per write event. The default SD library in Arduino usually writes data at about 4500-5000 bytes per second, and even if SdFat performs significantly better even the slowest SD cards are much faster than the Arduino. And my gut feeling is that the relatively slow I2C bus coms to the EEprom I’m currently using are sand-bagging the system so much that whole question of SD speed is moot until I start using SPI EEproms, or faster Fram.
The point is, always try several different cards with your logger, so you can reject ones that do not sleep well. With a good card you can get an optimized build below 0.1 mA between readings, but a bad sleeper will easily bump the logger back up into the 0.2 mA range, cutting your operating life in half. It’s also worth remembering that there is a world of difference between how often you see problems with consumer grade vs industrial grade SD cards.
With regards to runtime current: always format SD cards using SD Formatter, as OS level formatting utilities may adversely affect performance with the SdFat library. According to William Greiman (author of the SdFat library) “Performance of microSD cards is not easy to predict on Arduino. Arduino uses SPI to access the cards and the SD library has a single 512 byte cache. Modern SD cards are designed to be used on the high speed 4-bit SDIO bus with very large (16 KB or larger) multi-block writes and reads so they must emulate the single block access that Arduino libraries use. This can mean much internal data movement, erasing of flash, and rewriting of data.” Once again, older, smaller SDcards suffer less from this problem than larger size cards, and it’s probably a good idea to try to match your data saves to that 512 byte block size.
One extension of getting your loggers down to a low sleeping current is that it becomes possible to power your data logger with solar cells, especially with 500F super caps available for $3 each on eBay (& capacitor balancing boards at $1.50). A commonly seen conversion is 1Farad = 0.277mAh /V, so you can think of that 500F cap roughly equivalent to a 138mAh battery – somewhat similar to the capacity of a CR2032 coin cell. Ignoring the pulse discharges for sampling, I’m seeing sleep currents in the 0.1-0.2mA range, implying more than a week of operation with that kind of power. David Pilling has done some interesting experiments using cheap garden solar cells with super caps. So has Nick Gammon, and the guys over at Solarduino.net and heliosoph.mit.
The real question is how to get the logger to recover gracefully from a brown-out event if the sun goes away for an extended period of time, and then comes back and is able to charge the caps up again…
Well, I finally took the plunge and started cutting power to the SD cards: Switching off SD cards for Low Power Data Logging. I left that step for last because as I was being cautious about anything that might put my precious data at risk, but so far (and I am still testing the heck out of it) is seems to be working well.
It can take a reasonable amount of soldering & code Kung-fu to implement the power optimization methods described above, and if you haven’t quite reached that level the Adafruit TPL5110 Low Power Timer provides a alternative approach to power management for only $5. Cfastie has been putting this board through it’s paces over at PublicLab.org.