2-Part ProMini Logger that runs >1 year on a Coin Cell

This ‘two-part’ logger fits nicely inside a 50mL Falcon tube. With a bit of practice, soldering the Pro Mini & RTC together takes ~30 minutes. The 4K EEprom on the RTC board will hold 4096 1-byte RTC temperature readings (~ 40 days worth @ 15 min. intervals) and that’s easily extended with $1 memory chips or modules.

The EDU build we released in 2020 provides remarkable flexibility for courses in environmental monitoring. However an instructor still needs to invest about five days ordering parts, testing components, and preparing kits for a 15-20 seat course being run remotely. (only 1/2 that is needed for in-person courses where the students pin & test the parts themselves). While that’s not unusual for university-level lab based subjects it is something of a stretch for high school teachers. And thanks to COVID chip shortages, modules that were only 99¢ at the beginning of this project could now set you back $5 each. So with all that in mind, we’ve continued development of a ‘lite’ version of our logger with the lowest possible prep time. That new baby is now ready for release with data download & control managed through the IDE’s serial monitor window.

With just three core components as our starting point, the only hardware option was to remove the SD card. Groundwork for this change was already in place with our use of an EEprom to buffer data so that high-drain SD saves only occurred once per day. Getting rid of power hungry cards also opened up the possibility of running the entire unit from the coin cell on the RTC module. But a power budget that small will necessarily add complexity to the base code, which must minimize run-time even though EEproms are notoriously slow devices. And most garden-variety memory chips have a lower limit of 2.7v – so a nominal 3v CR2032 can only be allowed to fall about 250mv under load before we run into trouble. That voltage drop increases over time because the internal resistance of a coin cell is only 10 ohms when new, but approaches 100 ohms by end of life.

We pressure tested the centrifuge tubes: 50mL tubes can be deployed to 10m depth, 30mL tubes can go to 20m. And the loggers run fine under mineral oil for deeper deployments.

In addition, it’s not unusual to see a 50mv delta at the battery terminals for every 5°C change in ambient so a standard lithium coin cell will not power the logger below 0°C. But if theres one thing I’ve learned on this project it’s that datasheets only tell you so much about system behavior in the real world – especially with stuff constructed from cheap modules carrying half a dozen unspecified bits. So let’s just build one and see how it goes…

Modifying the RTC module:

Clipping the VCC leg (the 2nd leg in from that corner) forces the DS3231 to run from the coin cell full time.
Disconnect the modules indicator LED by removing its limit resistor.
Remove the 200ohm charging resistor & bridge VCC to the backup power line at the black end of diode.

Cutting the VCC leg depowers most of the logic inside the DS3231. However the chip will still consume an average of 3µA through VBat to keep the oscillator, temperature compensation & comparator logic working. RTC current can spike as high as 650µA every 64 seconds when new temperature readings occur. Bridging VCC to Vbat also means a 3.3v UART will push some sub-milliamp reverse currents through an older cell. But I’ve yet to have a single problem (or even any detectable warming) after many days with loggers connected during development. Despite dire manufacturer warnings that reverse currents beyond 1µA will heat manganese-dioxide/lithium cells until they explode, the ones I’ve used so far survive the abuse without issue.

Three mods to the RTC module: Running from the Vbat also disables 32KHz output so I usually clip that header pin. Watch out for the ‘-M’ variant of the DS3231. We’ve had several batches of those over the years where the temperature register was off by 5°C or more. Try to use ‘-N’ or ‘-SN’ chips if you can get them.

I’ve no doubt the UART connected time is shortening the batteries lifespan slightly, in fact Panasonic specifies: “the total charging amount of the battery during it’s usage period must be kept within 3% of the nominal capacity of the battery”, so it’s a good idea to remove the battery if you are spending an extended time with the units connected to the serial line to keep the total reverse current time to a minimum. But given our tight operational margin I don’t think we can afford to lose two hundred millivolts over a Schottky protection diode. A typical solution would address this by ORing the two supplies with an ideal diode circuit but that’s not a option here as ideals usually waste some 10-20 µA. On a practical level it’s easier to just to pop in a fresh battery before every long deployment. Drift on these DS3231 RTCs is usually a loss of ~4-5 seconds per month, but could be up to twice that for -M variants of the chip.

Modify the Pro Mini board:

90° header tails on the left side are clipped to avoid accidental contact with the I2C jumpers later. Vcc & Gnd points left long. Load ‘Blink’ to test if the ProMini is working as soon as the header pins are on the board.
Carefully clip away the regulator from the 2-leg side. Also remove the power LED limit resistor.
Optional: Add the regulators orphaned 4.7µF input cap to the rail by bridging it to VCC.

An 8Mhz Pro Mini continues as the heart of our loggers because the 328p is still the easiest low-power option for projects that aren’t computationally demanding. These eBay Pro Mini’s usually sleep below 1µA with the BOD turned off but 17µA with BOD on. It’s worth noting there are clones out there with fake Atmel chips that won’t go below 150µA sleep no matter what you do. Cheaper boards usually ship with ceramic regulator caps (instead of tantalums) but that just makes them more resilient if you accidentally connect power the wrong way. At 8Mhz the ‘official’ lowest safe voltage for the 328p is 2.7v, so that’s where the default BOD is usually set. But I sleep with BOD off because I’ve noticed that if the BOD gets triggered by low battery voltage then the processor goes into a high 1mA drain condition and this makes AA’s leak all over the inside of our normal 3-part loggers.

Three removals & one addition prep this Pro Mini clone for assembly. The reset switch is removed to make room for a NTC thermistor circuit. The logger can then only be restarted with a serial connection, but that’s on purpose.

Join the two components:

But you always have the default 2.7v BOD on while the processor is operating so you probably want to stop logging when the rail starts falling below ~2785mv. Also keep in mind that there is range on that brownout threshold, from min. 2.5v to max. 2.9v. So one 328p may be more tolerant to running at low voltages than another.

Resistor legs wrapped in heat shrink extend the A4/A5 I2C bus. These two wires must cross over each other to align with connections on the RTC.
Add a layer of double-sided foam tape to prevent contact between the two boards. Extend the VCC & GND headers with resistor legs. Then remove the tape backing.
Carefully thread the four I2C bus jumpers through the RTC modules pass-through port. Press the two boards together onto the double sided tape.
Solder the connections to the RTC module. Now you can see why I trimmed the three header pins on that one side.

NOTE: Don’t trim the VCC & GND wires if you are going to add a rail buffering cap – the leftover ‘tails’ make perfect connection points for that capacitor later. (see below for details)
Clip the (non-functional) 32kHz pin and add solder to the SQW header pin on the RTC module. Solder a resistor leg to interrupt input D2 on the Pro Mini.
Add heat shrink & join D2 to the RTC SQW alarm header.
Then heat shrink the entire stack with ~4.5cm of 25mm (1inch) diameter tubing & cut that away from the battery holder.
The 2-module stack usually draws ~1µA in powerDown, but with part variability some go up to 2µA. Cheap modules often have leftover flux residue which can cause current leaks. It’s worth the time scrub these boards with isopropyl alcohol before assembly to reach the lowest possible power consumption. I found no significant difference in sleep current between setting unused pins to INPUT_PULLUP or to OUTPUT_LOW.

This two module combination usually sleeps around 1µA and most of that is the RTC’s (IBATT) timekeeping current as the 328p should only draw ~150nA in powerdown mode [with BOD off]. If we assume four readings per hour at 5mA for 10msec, the battery life calculator at Oregon Embedded estimates a 220mAh battery will last more than 10 years…which is ridiculous. We know from the datasheet that 575µA temperature conversions bring the RTC average up to 3µA – which isn’t showing up on this direct measurement. And there’s the battery self discharge of 1-3% per year. Perhaps most important there’s the complex relationship between pulsed loads and CR2032 internal resistance, which means we’ll be lucky to get half the rated capacity before hitting brown-out at 2.7v A more realistic estimate would start with the assumption that the battery only delivers about 110mAh with our logger consuming whatever we measure + 3µA (RTC datasheet) + 0.3µA (coincell self-discharge). We can round that up to 5µA continuous, with four 5mA*10millisecond sensor readings per hour, and we still get an estimated lifespan of about two years. So our most significant limitation is the amount of EEprom memory rather than battery power.

The Code: [posted on Github]

The most important difference between a coin cell powered logger and our AA powered units is that the battery has a high probability of being depleted to the point of a BOD restart loop. (which causes rapid flashing of the D13 LED) So we use a multi-step serial exchange in Setup() to prevent data already present in the EEprom from being accidentally overwritten.

Addendum 2023-10-25: Code revisions are *currently underway* to support the use of these loggers in enviro-sci course curriculum & some elements of the old logger code may disappear from Github for a while until our students have progressed further through the lab sequence. Those elements will then be restored to the base code on Github. This may cause discrepancies between the text in this post and the options in that code.

In Setup()

A UART connection is required at start-up so those menu-driven responses can occur through the serial monitor in the IDE. These have timeouts to avoid running the CPU during unintentional restarts. The menu sequence can be re-entered at any time simply by closing & re-opening the serial monitor window:

If you see random characters in the download window you have the baud rate set incorrectly. (We have recently increased this to 500,000 baud in the github code) Reset the baud and the menu should display properly HOWEVER you then need to close & re-open the window (this restarts the promini with serial window at the correct baud). If you try to Ctrl-A copy out the data when the the window still has garbled characters at the top then only the bad start characters that will copy out.

The first menu option asks if you want to download the contents of the logger memory to the serial monitor window. This can take 1-2 minutes with large EEproms at 500000 baud, which is the fastest rate an 8MHz ProMini can reliably sustain. Then copy/paste (Ctrl-A & Ctrl-V) everything from the IDE window into an Excel sheet and then, below the data tab, select Text to Columns to separate the data at commas. Or you can paste into a text editor and save as a .txt file for import to other programs. While that process is clunky because the IDE’s interface doesn’t export, everyone already has the required cable and data retrieval is driven by the logger itself. ( And yes, the exchange could be done with any other serial terminal app.)

After the start menu sequence the first sample time is written to the internal EEprom so the timestamp for sensor readings can be reconstructed during data retrieval later by adding offsets added to the first reading time. This technique saves a significant amount of our limited EEprom memory and all it takes is =(Unixtime/86400) + DATE(1970,1,1) to convert those Unix timestamps human readable in Excel. It is important that you download the old data before changing the sampling interval via the menu options because that interval (stored in eeprom) is used to reconstruct the timestamps during download. Valid intervals must divide evenly into 60 and be less than 60. Second-intervals can be used for rapid testing if you first enter (0) for the minutes during setup.

No sensor data is lost from the EEprom when you replace a dead coin cell and you can do the entire data retrieval process on UART alone with no battery in the logger. But RTC time reset should only be done after installing a new battery or the time will not be retained. If the time in the serial menu after a complete power loss reads 2165/165/165 165:165:85 instead of 2000/01/01 then there’s a good chance the RTC’s registers have been corrupted & the clock may need to be replaced. I’ve managed to do this to a few units by accidentally shorting the voltage to zero when the logger was running from a capacitor instead of a battery.

After setting the RTC time, the sampling interval, and other operating parameters, the logger requires the user to enter the ‘start’ command again. Only when that last ‘start’ confirmation is received are the EEprom(s) erased by pre-loading every location with ‘0’ values which also serve as End-Of-File markers during the next download. The red D13 led then blinks at 1second while the logger waits for the first sampling alarm to align with the current time before beginning the run.

Main LOOP()

To save power, slow functions like digitalWrite() and pinMode() can be replaced with much faster port commands. Careful attention is paid to pin states, peripheral shutdowns (power_all_disable(); saves ~0.3mA) and 15msec sleeps are used throughout for battery recovery. Waking the 328p from powerdown sleep takes 16,000 clock cycles (~2milliseconds @8MHz +60µS if BOD_OFF) and the ProMini draws ~250µA while waiting for the oscillator to stabilize. Care must be taken when using CLKPR to reduce system speed because the startup-time also gets multiplied by the divider.

( Note: For the following images a Current Ranger was used to convert µA to mV during a reading of the RTC’s temperature register at 1MHz. So 1mV on the oscilloscope means 1µA is being drawn from the Cr2032 )

Here CLKPR restores the CPU to 8MHz just before entering powerdown sleep, and then slows the processor to 1MHz after waking. The extra height of that first spike is due to the pullup resistor on SQW. Cutting the trace to that resistor and using an internal pull-up reduces wake current by 750µA.
Here the logger was left at 1MHz when it entered powerdown sleep(s). Waking now takes 16 milliseconds – wasting a significant amount of power through the 4k7 pullup on SQW when the RTC alarm is still asserted at the start of the event.

[ 2023-05-31 UPDATE: I came across several cheap eBay EEproms that would freeze the system when I lowered the system clock to 1MHz to save power during EEprom saves. So I have removed that technique from the code on GITHUB to make that codebase more generic. This problem did not affect the chips I bought from DigiKey]

CR2032 voltage is checked during the EEprom data save because an unloaded coin cell voltage does not change – even when the battery is nearly dead. This assures that the voltage droop is captured though the exact timing of that minimum varies from one memory chip to the next. Logger shutdown gets triggered when the EEprom write brings the rail voltage below the 2795mv systemShutdownVoltage, which happens when the internal resistance of the coincell rises at end of life.

Adding Sensors:

An RTC temperature only configuration for this logger records a 0.25°C temperature record from the DS3231, index-encoded to use only one byte per reading. This allows ~4000 readings to be stored in the 4k EEprom on the RTC module. This works out to a little more than 40 days at a 15 minute sampling interval, but you can set SampleIntervalMinutes to any even divisor of 60.

We made extensive use these RTC temp records in our cave drip loggers at the beginning of the project. The accuracy spec is pretty bad at ±3°C, but they were usually within ±1 @ 25°C. Note that the RTC only updates its temp. output registers once every 64 seconds, making it a fairly slow sensor.

That little AT24c32 doesn’t last very long with sensors that generate 2 or 4 byte integers. The solution is to combine them with larger 32k (AT24c256), or 64k (AT24c512) chips so the sensors arrive with the extra storage space they require. These EEprom modules can usually be found on eBay for ~$1 each and (after you change the bus address & bytesofstorage defs) they work with the same page-write & addressing code as the 4k EEprom.

The headers on this common BMP280 module align with the 32k headers in a ‘back-to-back’ configuration. The tails on the YL-90 breakout extend far enough to connect the two boards. Note this sensor module has no regulator which is better for low power operation.
Pin alignment between the YL-90 and this BH1750 module is slightly more complicated as you must keep the light sensor facing out. BMP280 sensors usually run about two years, but the BME280 variant (includes RH) has a shorter lifespan and should be replaced yearly.
After removing the EEprom’s redundant pullups, clip away the plastic spacers around the header pins. Then wiggle the BH1750 over the headers on the 32k module. Solder the points where the pins pass through the 1750 board. I2C pullups on the sensor boards can left in place.
I2C pin arrangement on the RTC doesn’t match the BH1750 module. Make the required cross-overs with a 4 wire F-F Dupont. (which comes with those red 32k boards) or soldering those connections is more robust.

NOTE: Support for both of the sensors shown above is included in the code on Github to serve as examples to guide other I2C sensor additions. Sensors are enabled by uncommenting the relevant defines at the start of the program and the base code also supports the ICU based NTC/LDR combination shown below.

I2C generally expects the pullups to be about 1ma which on a 3v system would require 3300 ohms. This means you can leave the 10k pullups on the sensor boards to bring total pullup (4k7 on the RTC & 50k on the ProMini = ~4k3) closer to the 3.3k ideal. The open-drain implementation of I2C means that capacitance on the bus will slow down the rising edges of your clock and data lines, which might require you to run the bus more slowly. The more sensors you add, and the longer the wires, the worse the parasitic capacitance gets. So if you need long I2C wires drop the total bus pullup to 2k2.

The 662k LDO regulator on most eBay sensors wastes 3-4µA: For long deployments this can be removed & then bridging the in->out pads should bring your sleep back to ~1µA.

You must use low power sensors with a supply range from 3.6v down to our 2.7v EEprom/BOD cutoff. A good sensor to pair with this logger should sleep around 1µA and take readings below 1mA. Sometimes you can pin-power sensors that lack low current sleep modes although if you do that be sure to check for unexpected current leaks in other places such as bus pullup resistors and the I2C bus may go into an illegal state (the idle condition is with both lines high) requiring a full reset of all sensors after power is restored. Choose libraries which allow non-blocking reads so you can sleep the ProMini while the sensor is gathering data and check that those libraries do not contain any delay() statements. In that regard my favorite sensor combination for this logger is an NTC thermistor & CDS cell which adds nothing to the sleep current. We explained how to read resistive sensors with Arduino’s Input Capture Unit in some detail back in 2019; so here I will simply show the hardware connections. Add these passives to the Pro Mini BEFORE joining it to the RTC module, taking care not to hold the iron so long that you cook the components:

D6=10kΩ 1% reference resistor , D7=10k NTC, D8=300Ω, D9=LDR (5528). Note that the LDR could be replaced with any other type of resistive sensor. A typical 10kNTC reaches ~65kΩ near -10°C and a 10kLDR usually peaks near 55kΩ at night.
You MUST put the lines you are not reading into input mode to isolate them from the circuit when you read a specific sensor. It’s easy to kill the LDR with too much heat – in that case it becomes infinite resistance.
A 104 ceramic to GND completes the ICU timing circuit. With 0.1uF as the charge reservoir, each resistor reading takes ~1-2msec in sleep mode IDLE. With these sensors I jumper D2->SQW with a longer piece of flexible wire to avoid covering the D13 LED.

Don’t expect the NTC you have in your hands to match exactly the values provided by its manufacturer. Fortunately there are several online calculators to choose from when determining your NTC thermistor constants. For calibration data, I use a food dehydrator to heat the loggers to around 45-50°C, then then it cool to room temp. for the midpoint, and then put them in the refrigerator overnight for a cold point at ~5°C. I add this NTC/LDR combination to all loggers (even if they will eventually drive I2C sensors) because a good test-run for newly built units is to read these sensors at an ultra short five second interval until the EEprom is full. After passing that test you can be sure the core of the logger is ok before adding new sensors.

Other useful modifications to the basic 2-module logger include:

A 220µF 10-25v Tantalum buffer cap can be added where the rail wires pass through the RTC module. Anything from 200 to 470µF will do the job of reducing older battery droop. After matching polarity, flip it over to bring the SMD solder pads to the top surface for easier soldering. Rail buffering caps assist the coincell, extending runtime by ~30%
The code on GitHub has a #define which enables A0=GND, A1=Green, A2=Blue. Lighting the LED(s) by setting A1/A2 pins to INPUT_PULLUP keeps the current below 50µA with the internal pullup resistors. The red led on D13 is left in place to show when you are trapped in a BOD-restart loop. LED’s also make good frequency specific light sensors..
With a few strategic bends, single I2C sensors can be soldered directly to the pins.

EEprom & sensor additions push measured sleep currents to 2µA (so ~6µA actual w RTC’s 3.0µA) but that still gives a >1 year estimates on 110mAh. With all due respect to Ganssle et al, the debate about whether buffering caps should be used to extend operating time is something of a McGuffin because leakage currents are less important when you only have enough storage space for one year of operation. Even a whopper 6.3v 1000µF tantalum only increases sleep current by about 1µA. That’s 1µA*24h*365days or about ~ 8.76 mAh/year in trade for keeping the system above our 2.7v cutoff with barely a ripple. That means we don’t need to lower the BOD with fuses & custom bootloaders that break code portability. Pushing the limits of fuse optimization can get a little flaky on these cheap boards, so it’s good to have those ‘Get out of jail free‘ defaults available at reboot. When you only service your loggers once a year, any tweaks that require you to remember ‘special procedures’ in the field are things you’ll probably regret. (And many of those cheap eeproms on eBay also have a 2.7v lower limit) Using the 328p internal oscillator to save power is also a non-starter because it’s 10% error borks your UART to the point you can’t upload code.

With a practiced hand you can do a memory expansion right on the RTC module without changing the sleep current: Here I’ve replaced the default 4k AT24c32 with a 64k AT24c512. 64k is the sweet spot for single sensors generating a 2-byte integer value as you can store ~340 days of data with a 15minute interval. The RTC modules default configuration pulls address pins high (=0x57) with a 4k7 resistor block, while the red YL-90 modules pull the address pins low (=0x50). So you retain the option of adding another eeprom on the I2C header pins after this upgrade. It is also possible to solder new chips onto those little red EEprom breakouts. Note: 128k AT24c1024 chips are slightly larger than the 32&64k so you have to bend the legs straight down which makes that soldering tricky. So I usually find it easier to just ‘stack’ two smaller 64k chips.
Here’s an example of stacking the EEproms. The rtc module pulls all address pins high (setting the lower default 4k eeprom in this picture to 0x57) but if you leave any address pins on the 64k chips ‘unconnected’ they get internally pulled to ground. (setting the bus address to 0x51 for the upper chip in this picture) AT24C512’s cost about 50¢ on eBay. The Write Protect pin can also be left unconnected. Each chip you add increases overall sleep current by ~1µA.

Then use both eeproms by changing defines at the start of the code:
define opdEEpromI2Caddr 0x57
define opdEEbytesOfStorage 4096
define sensorEEpromI2Caddr 0x51
define sensorEEbytesOfStorage 65536

Leakage scales linearly with capacitance so use the Falstad simulator to see what size you actually need. Capacitors rated 10x higher than the applied voltage reduce leakage current by a factor of 50. So your rail buffering caps should be rated between 10 to 30v if you can find them. While they are a bit bulky, electrolytics also work fine. The 220µF/25v 227E caps I tested only add ~5nA to the loggers sleep current and these can be obtained on eBay for <50¢ each. High voltage ratings get you closer to the low leakage values you’d see with Polypropylene, Polystyrene or Teflon film and moves you farther away from de-rating problems.

Note that as the buffering cap gets larger, you need to add more ‘recovery time’ before the rail voltage is restored after each load. A large rail capacitor also protects the unit from impacts which might briefly disconnect the spring contact under the coin cell. This is a such common problem in our other loggers that we use a drop of hot glue to lock the RTC coin-cell in place before deployment.

Discussion:

CLKPR brings the ProMini down to 1MHz and a current of ~1.3 mA however the energy cost per logging event actually increases when the system clock gets divided. But with our slim operating margin the growing internal resistance of the coin cell means we have to stay above 2.775v even if it means using less efficient code. Running from the internal oscillator might help but is avoided because our ICU timing method needs the thermal stability of an external oscillator and, the internal oscillator makes UART coms flakey. FRAM has much lower saving currents than standard EEproms but those expensive chips sleep around 30µA so they aren’t a viable option for low-power systems. (…unless you pin-power them so you can cut their power during sleep.)

In the next three images, a Current Ranger converts every 1µA drawn by the logger to 1mV for display on the scope. The last two spikes are transfers of buffer-array data into the 4K EEprom on the RTC module while the CPU takes ADC readings of the rail voltage. Note that our code staggers EEprom save events so they don’t occur in the same pass like this, but I forced them together for this testing to illustrate the effect of repeated pulse-loads:

A triple event with a temperature sensor reading followed the transfer of two array buffers to EEprom. Battery current with no rail buffering cap. [Vertical scale: 500µA /division, Horizontal: 25ms/div]
Here a 220µF tantalum capacitor was used to reduce the peak battery currents from 2.5mA to 1.5mA for that same event.
Here a 1000µF tantalum [108J] capacitor reduces the peak battery current to 1mA. The 30msec sleep recovery times used here are not quite long enough for the larger capacitor.
Voltage across a coin cell that’s been running for two months with NO buffering capacitor. The trace shows the 2.5mA loads causing a 60mv drop; implying the cell has ~24 ohms internal resistance. [Vertical Scale: 20mv/div, Horizontal: 25ms/div]

The basic RTC-only sensor configuration reached a very brief battery current peak of ~2.7mA with no buffering cap, 1.5mA with 220µF and less than 1mA with 1000µF. The amount of voltage drop these currents create depend on the coin cells internal resistance but a typical unbuffered unit usually sees 15-30mV drops when the battery is new and this grows to ~200mV on old coin cells pulled from loggers that have been in service since 2018. The actual drop also depends on time, with subsequent current spikes having more effect than the first as the internal reserve gets depleted. The following images display the voltage droop on a very old coin cell pulled from a logger that’s been in service since 2016 (@3µA average RTC backup)

This very old coin cell experiences a larger 250mv droop with no capacitor buffer. Note how the initial short spike at wakeup does not last long enough to cause the expected drop. [Vertical: 50mv/div, Horizontal: 25ms/div]
Adding a 220µF/25v tantalum capacitor cuts that in half but triples the recovery time. CR2032‘s usually plateau at 3.0v for most of their operating life, so the drop starts from there.
[Vertical: 50mv/div, Horizontal: now 50ms/div]
A 1000µF/6.3v tantalum added to that same machine limits droop to only 60mv. Recharging the capacitor after the save now approaches 200 milliseconds. [Vertical : 50mv/div, Horizontal: 50ms/div]

After many tests like those above, our optimal solution is to run the processor at 8MHz most of the time while breaking up the execution time with multiple 15 millisecond POWER_DOWN sleeps before the CR2032 voltage has time to fall very far. (This is especially necessary if you start doing a lot of long integer calculations) This has the added benefit that successive sensor readings start from similar initial voltages. The processor is brought down to 1MHz only during the EEprom save event where the block can not be divided (and that only happens when the data buffering arrays are full….)

Current drawn in short bursts of 8MHz operation during sensor readings. The final EEprom save peaks at ~2.75mA draw with CLKPR 1MHz CPU & Sleep_ADC readings.
[CH2: H.scale: 25msec/div, V.scale 500µA/div via Current Ranger]
Voltage droop on that same ‘old’ CR2032 used above reached a maximum of 175mv with NO buffering capacitor across the rail. This battery has about 64 ohms of internal resistance.
[CH2: V.scale 25mv/div, H.scale 25ms]
Adding a 220µF tantalum capacitor to the rail holds that old battery to only 50mv droop. The 25v tantalum cap adds only 0.1µA leakage to the overall sleep current.
[CH2: V.scale 25mv/div, H.scale 25ms]
This ‘solder-free’ AT24c256 DIP-8 carrier module is bulky compared to the red YL-90 boards, but it lets you easily upgrade to 64k AT24C512 & configure multiple I2C address. Here I’ve removed the redundant power led & pullup resistors.

Even with fierce memory limitations we only use the 328’s internal 1k for a couple of index variables that get written while still tethered to the UART for power. EEprom.put starts blocking the CPU from the second 3.3msec / byte, and internal EEprom writing adds an additional 8mA to the ProMini’s normal 5mA operating current. This exceeds the recommended pulse current for a garden variety CR2032. And multi-byte page writes aren’t possible so data saved into the 328p costs far more power than storage in an external EEprom. However it is worth noting that reading from the internal EEprom takes the same four ticks as an external with no current penalty, while PROGMEM takes three and RAM takes two clock cycles. So it doesn’t really matter to your runtime power budget where you put constants or even large lookup tables.

Most DIP8 EEproms are pin compatible with that carrier. 128k EEproms are usually divided into 64k blocks with sequential I2C addresses so the location variables don’t exceed uint16_t max of 65535. Heliosoph posted a way to combine multiple 64k EEproms into a single linear address range but with ‘combination’ sensors like the BME280 sometimes it’s easier to just send each sensor’s output to a different bank using the two bus addresses. Our code demonstrates how to do this with the OPD & sensor arrays.

A simple optimization we haven’t done with the code posted on GitHub is to increase the I2C buffer. All AT-series EEproms are capable of 32-byte page-writes but the default wire library limits you to only 30 bytes per exchange because you lose two for the register location. So we used 16-byte buffer arrays in the starter code but you could increase those array/transfers to 32 bytes by increasing the wire library buffers to 34 bytes:

In wire.h (@ \Arduino\hardware\arduino\avr\libraries\Wire\src)
#define BUFFER_LENGTH 34
AND in twi.h (@ \Arduino\hardware\arduino\avr\libraries\Wire\src\utility)
#define TWI_BUFFER_LENGTH 34

With larger EEproms you could raise those buffers to 66 bytes for 64 data-byte transfers. That buffer gets replicated in five places so the wire library would then require an extra 138 bytes of ram over the 32-byte default. 128k EEproms often refresh entire 128-byte blocks no matter how many bytes are sent, so increasing the buffer reduces wear considerably for those chips, while 64k & below may perform partial page-writes more gracefully. It’s also worth mentioning that there are alternate I2C libraries out there (like the one from DSS) that don’t suffer from the default library’s limitations.

An average sleep current of ~5µA*86400 sec/d burns ~432 milliAmpseconds/day. With a page-write that draws 4mA*6msec, the usual 12x buffer-array transfers of data to EEprom per day will consume about 288mAs. Cutting that in half by doubling the size of the array is going to save you ~144mAs per day, so it will take four days to save enough power for one more day of operation. That return is better with older 10 millisecond/write EEproms, and reducing the number of pulse-load events may extend battery life in ways other than the power being saved. I always do the 34-byte I2C buffer & 32-byte data array increases for long deployment loggers because the cheap EEproms on eBay are always older revs, so they take twice as long for both read & write operations compared to newer AT series chips from DigiKey.

No matter what optimizations you make, battery life in the real world can also be shortened by temperature cycling, corrosion from moisture ingress, being chewed on by an angry dog, etc. And you still want the occasional high drain event to knock the passivation layer off the battery.

Here wires extend connections for the thermistor & LED to locations on the surface of the housing. Alternate power is brought in from a small solar panel – but I will post more on that little experiment later 🙂

An important topic for a later post is data compression. Squashing low-rez sensor readings into only one byte (like we do with the RTC temperature & battery voltage) is easy; especially if you can subtract a fixed offset from the data first. But doing that trick with high resolution thermistor or lux readings is more of a challenge. Do you use ‘Frame of Reference’ deltas, or XOR’d mini-floats? We can’t afford much of an energy tradeoff for heavy calculations on our little 328p so I’m still looking for an elegant solution.

Hopefully this new member of the Cave Pearl family goes some way toward answering people asking why we haven’t moved to a custom PCB: Using off-the-shelf parts is critical to helping other instructors base their courses on our work, and when you can build a logger in about 15 minutes, from the cheapest parts on eBay – that still runs for a year on the coin cell… why bother? We do water sampling dives all the time with those 50mL centrifuge tubes and I’ve yet to see the Nunc’s from Thermo leak at depths far beyond IP68. And again, you are only talking about $1 each for those tubes.

We’ve also been having fun embedding these ‘ProMini-llennium Falcons’ into rain gauges and other equipment that predates the digital era. There’s a ton of old field kit like that collecting dust in the corner these days that’s still functional, but lacks any logging capability.

Addendum

30ml self-standing Caplugs from Evergreen Labware are another good housing option because they have a brace in the cap that just fits four 22gauge silicone jacket wires. Holes drilled through the lower stand enable zip-ties to secure the logger. The outer groove in the lid provides more surface area for JB-weld epoxy, giving you an inexpensive way to encapsulate external sensors. 1oz / 25ml is enough to cover about five of these sensor caps. Then clear JB weld can be used as a top-coat to protect optical sensors.

Drill the central channel to pass the I2C wires through the cap. Roughen the upper surfaces with sandpaper to give it some tooth for the epoxy.
Conformal coat the board before the epoxy. Work the epoxy over the sensor board carefully with a toothpick and wipe away the excess with a cotton swab.

If you deploying in an area exposed to direct sun you can prevent the logger from getting too hot by adding a layer of PTFE thread tape around the tube:

PTFE tape is also an excellent light diffuser to keep the logger cool or when reading the LDR
Heat shrink holds tape in place

Adding a small amount of silicone grease to the rim of the tube before closing improves the seal with the lid considerably. We’ve done pressure tests to 45psi so these tubes can be deployed to at least 20m depth. Avoid old stock as the caps get brittle & crack long before the clear tubes age. Use small 0.5-1 gram desiccant packs with this housing.

Addendum: 2022-07-01

Since we covered adding sensors, here’s a couple of burn-down curves for the two configurations described above. Both were saving 4 bytes of data per record every 30 minutes giving a runtime storage capacity of about 150 days. Battery was logged each time the 16-byte buffer-arrays were written to eeprom. Both loggers have a measured sleep current of ~1.5µA and they will be downloaded periodically. Although the curve spikes up after each download, these are runs on the same coin cell battery:

Cr2032 voltage after 11 months @30min sampling interval: BMP280 sensor reading Temp. & Pr. stored in 32k eeprom with NO 220µF rail buffering capacitor. This test run is complete. At oversampling x16 the BMP uses considerably more power than the BH1750.
Coin cell after more than 12 months @30min sampling interval: BH1750 sensor & 32k ‘red board’ EEprom (Sony brand battery: again, with no rail buffer cap). Both of these records show only the lowest battery reading in a given day. This logger is still operating…

I’m running these tests without help from a rail buffering cap, to see the ‘worst case’ lifespan. A pulse loaded Cr2032 has an internal resistance of ~20Ω for about 100 mAh of its operational life, so our 5mA eeprom writing event should only drop the rail 100mv with no rail buffer cap. But once the cell IR approaches 40Ω we will see drops reaching 200mv for those events. The CR2032’s shown above have plateaued near their nominal 3.0v, so we should see the rail droop to ~2800mv when the batteries age. Again, with the 220 µF rail capacitor those drops are reduced to less than 1/2 that size and with 1000µF they are virtually eliminated.

Note that the download process briefly restores the voltage because the 3.3v UART adapter drives a small reverse current through the cell. I think this removes some of the passivation layer, but the effect is short lived. I have reloaded these two loggers with a new code build that tracks both high (immediately after wake) & low (during EEwrite) battery levels to see if the delta in the logs matches the 50mv drops I usually see with a scope.

According to Maxell’s 1Meg-ohm (3.3µA continuous) discharge test, coin cells should stay at their 3v plateau until they deliver about 140mAh [~500,000 mAs] So buffering caps aren’t really needed until batteries pass that point. In testing, 200uF rail caps extended runtime by about 35%. Of course, if you reach a year without the rail buffer, then you’ve probably filled the EEprom. So that capacitor may only be necessary with high-drain sensors or in low temperature deployments where the battery will struggle with larger IR drops. According to Nordic Semi: “A short pulse of peak current, say 7mA (typical of a Bluetooth Low Energy radio) for 2 milliseconds followed by an idle period of 25ms is well within the limit of a CR2032 battery to get the best possible use of its capacity.” Our EEprom save events are typically around 6-8 mA for 5ms which causes <50mv drop with a 200µF. Even with very old batteries the typical EEsave event doesn’t usually drop the rail more than 150mv, however the recovery time grows from less than 25msec to more than 150msec, so logging events look more like ‘blocks’ on the oscilloscope trace rather than a series of short spikes.

And here we compare our typical logging events to the current draw during the RTC’s internal temperature conversion (with a 220µF/25v cap buffering the rail). On all three the horizontal division is 50 milliseconds, and vertical is 200µA via translation with a current ranger:

Typical sampling event peaks at 450µA with a 220µF rail buffer cap. The logger sleeps for 15msec battery recovery after every sensor reading or I2C exchange.
Every 64 seconds a DS3231 temperature conversion draws about 250-300µA for 170ms. There is no way to influence the timing of the RTC conversions.
Occasionally the RTC temp conversion happens in the middle of a logging event adding to the peak current.

The datasheet spec for the DS3231 temp conversion is 125-200ms at up to 600µA, but the units I tested drew half that at 3.3v. The rail cap can’t protect the coin cell from these long duration events so RTC temp conversions overlapping the EEprom save will likely be the trigger for most low voltage shutdowns. The best we can do to avoid these collisions is to check the DS3231 Status Register (0Fh) BSY bit2 and delay the save till the register clears. But even with that check, sooner or later, a temp conversion will start in the middle of an EEprom save.

Another thing to watch out for is that with sleep currents in the 1-2µA range, it takes a minute to run down the little 4.7µF cap on the ProMini board. If you have a 220µF buffering the rail the logger can sleep for more than 10 minutes with no battery. So if you are trying to reset the RTC you may need to briefly short Vcc to GND (at the UART headers) after removing the coin cell. Note that on several of the RTC modules the alarms continue to be asserted even after you disable them in the control register and this draws 6-700uA continuously through the pullup on the module. The only way to be absolutely sure the RTC alarm(s) will not fire after a shut-down is to turn off the RTC’s main oscillator. It’s also worth noting that the datasheet says: “If low power consumption during reset is important, it is recommended to use an external pull-up or pull-down.” If your code hangs, the processor will draw 5mA continuously until the battery drains and the logger goes into a BOD restart loop with the D13 red led flashing quickly. The logger will stay in that BOD loop from 4-12 hours until the battery falls below 2.7v without recovering. This has happened many times in development with no damage to the logger or to any data in the EEprom.

In all cases, your first suspect when you see weird behavior out of the logger is that the coin cell needs to be replaced. It’s worth noting that name brand CR2032s (Panasonic, MuRata, Duracell, Energizer, etc.) can last significantly longer than no-name ‘bulk’ coin cells from eBay/Amazon. They also plateau at 3.05v, while cheaper cells tend to level out at 2.95v. Most of the units I’ve tested trigger their BOD just below 2.775 volts. And 10 to 20 millivolts before the BOD triggers the internal voltage ref goes a bit squirrely, reporting higher voltages than actual if you are using the 1.1vref trick to read the rail. The spring contact in the RTC module can be pretty bad and that can give you random quits from large voltage drops so I usually slide a piece of heat-shrink behind it to strengthen contact with the flat surface of the coin cell. Normal operation will see 40-50mv drops during EEprom saves up to 3msec with 200µF rail buffers ( with a 1000µF rail cap those events are under 20mv) If those events look unusually large or recovery starts stretching to 100’s of milliseconds on the scope you probably have bad battery contact. In all cases, a long duration load can deplete the rail buffering cap – a 200µF reaches the same v-drop as a ‘naked’ battery after ~3msec, and 1000µF after ~10msec.

Addendum: 2023-04-23

We finally released the full build tutorial on YouTube – including how to upgrade the default 4k EEprom with two stacked 64k chips:

…and for those who already have soldering skills, we posted a RAPID 4 Minute review at 8x playback

Make at least two machines at a time. I usually build in batches of six, and of those, one usually ends up with either a faulty RTC module or a ProMini with one of those fake 328p chips that wont sleep below 150µA. Test each ProMini with ‘blink’ before assembly because you occasionally get one that shipped without a bootloader. Having more than one logger makes it easy to identify when you’ve got a hardware problem rather than an error in your code. Even then, no unit is worth more than an hour of troubleshooting when you can build another one from scratch in about 30 minutes – your time is worth far more than these components. That said, taking time to clean all the parts before & after assembly is always worth your time, because with sleep currents below 5µA any leakage paths between PCB traces from flux residue, fingerprint smudges, etc. become important.

Also Note: 99¢ eBay sensor modules are cheap for a reason and it’s not unusual for us to see 25% of them rejected for strange behavior or infant mortality during week long burn-in tests. Relative accuracy spec for the BMP280 is supposed to be ±0.12 millibar, but when I run a batch of them side-by-side I usually see ±4 millibar between the records. So huddle test each batch to normalize them and be sure to look at each graph individually so you don’t include any bad data in your normalization which could throw off ALL of the corrections. Cheap BME280s sometimes refuse to operate with it’s individual RT/T/Pr sensors set at different oversampling levels, and at the highest x16 setting that sensor may use more power than your budget can sustain over a long deployment. Another thing to be aware of is that real-world installation means exposure to condensing conditions. For sensors with a metal cover (like the BMP280) internal condensation will happen at the dew point – often killing the sensor.

This $10 si7051 temp sensor module has ±0.1°C accuracy and sleeps in the nano amp range. You are more likely to find sensor modules with low power requirements on Tindie, than you are on eBay/Amazon. Be careful about boards with regulators, as their quiescent draw can be much larger than the sensors sleep current.

And all the other quid-pro-quos about dodgy eBay vendors still apply: Split your part orders over multiple suppliers with different quantities, ordered on different days, so you can isolate the source of a bad shipment. Don’t be surprised if that batch of boards somehow turns into a random delivery of baby shoes to your doorstep. Amazon is often cheaper than eBay and AliExpress is 1/4 the price of both.

Addendum: 2023-06-05

16x accelerated tests averaged about 1250 hours run time.

Ran a series of Cr2032 battery tests with these little loggers and was pleasantly surprised to find that even with the default BOD limiting us to the upper plateau of those lithium cells; we can still expect about two years of run time from most name brand batteries (with a 200uF rail cap). And with a series of different resistors on the digital pins, this logger might be the cheapest way to simulate complex duty cycles for other devices. Also keep in mind that all the units in the battery test had BOD’s below 2.8v – about 1 in 50 of these Promini’s will have a high BOD at the maximum 2.9v value in the datasheet. It’s worth doing a quick burn test with the Hdao cells to spot these high cutoff units to exclude them from deployment.

Addendum: 2023-10-25

Macintosh users have been running into a very specific problem with this logger: their USB-c to USB-a adapter cables are smart devices with chips inside that will auto shut-down if you unplug them from the computer while they are connected to a battery powered logger. The VCC & GND header pins on the logger feed enough power/voltage back through the wires to make the chip in the dongle go into some kind of error state – after which it does not re-establish connection to the Mac properly until it is completely de-powered. So you must unplug your loggers at the UART module to logger connection and NOT by simply pulling the whole string of still-attached devices out of the USBc port.

Addendum: 2023-12-01

Released the classroom version of this 2-module logger, with substantial code improvements to make it easier to add new sensors. This new build has two breadboards supported on 3D printed rails so that sensor connections can easily be changed from one lab activity to the next. The default code reads temperature via the RTC, and NTC thermistor, Light via an LDR and the Bh1750, and Pressure via a Bmp280.

Addendum: 2024-04-20

We have a separate post describing how to calibrate the NTC thermistors on these two module loggers using a DIY warm water bath made from insulated lunch boxes:

References:

Heliosoph: Arduino powered by a capacitor
Nick Gammon: Power Saving techniques for microprocessors
Jack Ganssle: Hardware & Firmware Issues Using Ultra-Low Power MCUs
Using a $1 DS3231 Real-time Clock Module with Arduino
Waterproofing your Electronics Project
An Arduino-Based Platform for Monitoring Harsh Environments
Oregon Embedded Battery Life Calculator
WormFood’s AVR Baud Rate Calculator
ATmega328P Datasheet

20 thoughts on “2-Part ProMini Logger that runs >1 year on a Coin Cell

  1. Brian Davis

    OK… wow. Um, you keep making me re-think, which is GREAT! Thank you!

    I admit one step I’ve not taken is stripping out the ProMini regulator and running unregulated (I’ve not even swapped to an external regulator just because I’m not sure which to do or how, and I haven’t needed it… YET). So that’s something I need to go back over everything and look at. I’ve also not taken the steps of disabling Vcc to the RTC because the soldering looked tricky… but here, with your trick of soldering a jumper from just over the diode in the battery charger circuit has me curious again for a different reason. That’s essentially connecting the RTC battery supply to the ProMini Vcc… but could you run this the other way? Remove the coin cell from the RTC (and frankly then desolder the coin cell holder off the board; it’s the biggest component and gets in the way), but do the same solder connection you do here to bring the ProMini’s Vcc rail over to the RTC, but coming in through the battery connection to keep the RTC running in low-power mode? Then my RTC and ProMini are all running off the main battery pack. Would that work? My goal here is to easily extend life by keeping the RTC in low-power mode and removing the coin cell battery holder entirely (I have enough room for batteries, but not that coin cell ironically. Also the wiring job between the RTC board and the ProMini is genius… and I wonder how much time you spend turning components around in your head. Same with the variety of sensor board / EEPROM board “co-wiring” solutions.

    I take a different strategy than you do for “different records”; instead of writing them “forward from the front and backwards from the rear” as you do, I just freely mix them with a single byte (or if I was trying to save this much memory a single bit) in the front labeling which type of record it is to decompress, but that’s just a small difference. Since I’m still using the SD card I just pack all my data records as 30 byte records so I’m doing EEPORM page writes, and battery life rather than memory is my limiting factor, but I really love this. Also, your point about editing the wire.h library to expand the buffer just two bytes, so you can write the entire 32 bytes of a page, is something I really should have done earlier, and didn’t think about… I just hate editing library files like that because it tends to really break things for others going forward, but I might have to do it.

    On data compression I need to think more… while I don’t need it to conserve total memory (SD cards are MASSIVE), I have been looking at it for compacting what I can fit in a single 30 byte record. Pressure sensors tend to be memory hogs (a single raw pressure or temperature reading takes up 4 bytes, and I’ve generally had two, so that measurement, uncompressed, chews up half the data record). Generally storing the simple differential is good enough but it’s another think I need to think about.

    Dang, I just wrote my own blog post. Sorry 🙂

    1. edmallon Post author

      In our typical AA powered loggers, the usual RTC mod cuts the Vcc leg, and then cuts the connection from the positive coin cell terminal to the Vbat line and replaces it with a 1n1418.

      Then the systems rail provides Vbat power whenever it’s higher than the coin cell-(minus the diode drop) which is most of the time with Lithium AA’s. That diode-OR setup works fine to power the RTC from the main system battery and I have not noticed any weird drift effects, etc. from the switching.
      [edit: Now that I think about it…I should probably replace the diode on the RTC module with a lower vF Shottky to more preferentially supply from the larger lithium AA system batteries]

      On this new ‘mini’ build I’ve also thought about replacing the coin cell battery holder with a 2x AAA holder & lithium cells, as that would easily tape down on that flat surface that’s left after removing the coin cell holder. But I’m working on another little trick there for posting soonish.

      I’ve been trying to figure out a way to use Varints that works for larger thermal deltas that also doesn’t obfuscate the code to the point where it’s completely unreadable by students. But that method is really optimized for small numbers and even with the 104 caps the thermal deltas between readings of the NTC gives you four sig figs. I think I’ve an idea for a solution packing those readings into 16-byte arrays, but just adding more memory is so easy I’d really only be developing that for my own amusement.

      Barometric pressure is easier to compress after you convert it to millibar. Then you can just subtract a fixed offset of the lowest expected reading at your latitude (about 980 where I live) and this leaves you with a normal range of about 30millibar. 2*(255) = 510 so if you can live with a resolution of only 0.2 millibar, then you can encode the rest of the pressure reading in one byte. This is essentially the same way we’ve encoded the battery readings to one byte only in that case I increased the spread with a 4x multiplier. But water level is more challenging due to the greater range. Perhaps you could generate periodic index/offsets and store those in the internal EEprom since you have loads of power on normal batteries?

      And WRT wiring…yes, I probably spend far too much time on these little puzzles.

  2. Manu

    Hello, you can save on eeprom write times by using FRAM instead of flash/eeprom. There are modules on Adafruit : https://www.adafruit.com/product/1895
    Basically, you can write byte by byte without penalty. The write time is shorter than the i2c transaction. Is simplifies a lot the code.

    1. edmallon Post author

      Last time I checked FRAM had sleep currents far too high for low power systems and those EEproms are so incredibly cheap: https://www.ebay.com/sch/i.html?_from=R40&_nkw=at24c512+50pcs&_sacat=0&LH_TitleDesc=0&_sop=15

      We also use the EEprom writing load to stress the batteries, and that’s actually lead to another interesting observation: with older coin cells that have been sitting around for a while, we’re seeing cell voltages rise significantly after they have been running for a week or two with those 2-3mA pulse loads. I don’t have a ref handy but I recall reading somewhere that if you never bring a coin cell above single digit μA loads then a kind of passivation layer builds up inside which reduces the total amount of power you can get from them.

      And there are lots of other power optimizations that could be done using more energy efficient CPUs & low power RTCs. But the point of this design was to make use of the parts already on a couple of cheap eBay modules so that non-engineering students could assemble it in one afternoon lab. I think we’ve achieved that nicely with this new build.

      1. Manu

        I solved the problem of sleep current by powering my fram with a digital output of the microcontroller (PIC24) making its sleep current probably in the nanoamp range (I didn’t have a microcurrent or a good microampmeter at the time, so I guessed it is that based on the time it worked). You also have to be careful not back powering the device from the i2c pins by disabling the i2c module in the uc. But it is effectively cheaper to use eeproms.

        1. Stuart

          The Fujitsu FRAM in the Adafruit module doesn’t seem to have a sleep mode, just a standby mode, whereas Infineon/Cypress modules like FM24V10 have a 5uA sleep mode with operation down to 2v, which would be better than the 2.7v EEPROMS. The cost of the FRAM may outweigh the benefits though!

  3. andrew

    an easier way to disable the LEDs is to burn them out – I use a 4 x AA NiMH battery pack – touch the leads (5 volts) across the LED, a brief flash & a millisecond later the LED is no more – saves on desoldering

    1. edmallon Post author

      That’s one way to do it, but I think asking our students to try that method would be a recipe for even more dead Pro Mini boards in the lab…and they don’t really need help in that regard. 🙂

    1. edmallon Post author

      The ‘basic’ two part build reads the RTC record if you uncomment ‘RTC_ONLY’ in the initial program defines. For other sensors you have to connect & enable them at the start of the code and we included BMP280 support to show people the kind of changes you need to make to add other I2C sensors.

      Yes the accuracy spec for the RTC temp is pretty rough, but when you actually test a large group of ‘-N’ and ‘-SN’ chips you find that most are only 0.25-0.5C away from actual. And that fixed offset is easy to correct over the range of temps seen by most student projects. BM sensor temps usually need exactly the same kind of correction because of self heating. The NTC requires a full calibration procedure against a reference sensor to derive the Steinhart–Hart constants – but then that’s another useful lab for the students work through.

      1. andrew

        I’m logging a mixed bunch of sensors at present – BME280, MCP9808, SCD30, various thermistors. The I2C ones all require periodic adjustments to the correction offsets over the months/ years for maximizing accuracy. So I spent a long time with NTC thermistors but they are even more troublesome when you are aiming/ desiring better than +/-0.2% accuracy ;-(

        1. edmallon Post author

          Yes. Things like ‘aging’ drift were far from my mind at the beginning of this project, but now, with up to a hundred loggers deployed at a given site, the data itself is telling us it’s an issue we can’t ignore. Our ratio-metric ICU method for reading thermistors is much better in that regard than traditional voltage dividers, but there are still several critical points. Sometimes there’s a known physical benchmark we can use for de-trending, but mostly we use a second calibration when the unit is retired (assuming it’s still operational…and didn’t get blown away by a Hurricane…) But that requires the drift to be both linear and unidirectional, when most of the stuff I’ve read says neither of those assumptions are true. I’ve also been playing with the idea of using the DS3231 temperature record for ‘on the fly’ drift corrections of the NTC data. That’s not perfect either, but at least it’s more characterized than cheap thermistors.

          The problem is that if you assemble a build from high quality components with really good tolerances & drift specs – you’ve probably spent too much money on them to do the kind of exploratory tattle-tale deployments that make the research more fun. In our experience, deploying 10x as many cheap sensors is more likely to give you interesting data than best-guess deployments with a small number of expensive toys – even if the cheap sensor data needs more post processing. And our ‘obviously home-made’ loggers tend to be ignored in places where nicer looking commercial equipment would quickly grow legs and walk away on its own. . .

          [Addendum: One thing that’s probably worth passing on is that the ageing effects we do see seem to be much more pronounced within the first year of a loggers lifespan. After that the whole system seems to ‘settle’ into much more constant (and slower) drift rates. So we usually run our loggers on a shelf somewhere from the moment they are made – even if they are intended for a deployment more than six months away. It’s probably not even worth calibrating them till they’ve had at least a two week short interval burn-in run]

          1. andrew

            So glad I’ve come across your blog. What an absolute mine of info. I’ve only read a small fraction of it so far, but hopeful it may give some tips for my own logging adventures.

  4. Crides

    How did you get the 328p down to 150nA when power down? The datasheet specifies the power down current is like 40uA

    1. edmallon Post author

      I think the 44uA in the datasheet is with both WDT (watch dog timer) & BOD (brown out detection) enabled. Rocket Scream’s Low Power library has an option to turn off the BOD in software and that’s required for sleeping down at 1uA. When you use this method the BOD is automatically re-enabled when the processor wakes so you still have protection from memory corruption. Occasionally you will get into the trap where the battery recovers but the start-up process draws enough current to pull the battery back down below the BOD cutoff, causing a restart-shutdown loop until the battery depletes. Fortunately with coin cells that limbo state doesn’t usually last long.

  5. Oliver

    You can write the data directly to the atmega328p flash using a modified bootloader. You don’t need a RTC either: if you de-solder the high speed crystal (with a 25$ hot air station), you can replace it with a 32khz crystal! You can then run your own RTC using asynchronous timer2 and powersave sleep mode (leaving timer2 on while sleeping). It sleeps at less than 1uA while keeping accurate track of time. You can then run on your CR2032 for much longer, cause you use less current and you don’t have the 2.7V limit.

    1. edmallon Post author

      Our whole aim with this 2-Part build was to avoid complications like bootloader mods so that the logger is easier for beginner level students to understand & work with. And with a raw crystal I’d be worried about thermal effects over the kind of time periods that loggers usually get deployed – correcting these drift errors are really what modern RTC’s do and there are several that mange it in the nA range. But you won’t find those really good RTC’s on cheep eBay modules.

  6. Pingback: Powering an Arduino Pro Mini logger for one year on a coin cell « Adafruit Industries – Makers, hackers, artists, designers and engineers!

  7. anthony mulherin

    Wondering if it is possible to modify this to see a change in state from a float switch or ultrasonic sensor, interested in building a data logger that could be positioned in tidal creek to log on off times of a switch rising to a set level and then comparing to tide chart heights to determine access times by boat to shallow areas
    I would like to build this as a low-cost data logger build tough to handle saltwater conditions,

    1. edmallon Post author

      This is easily done with the same circuit we use on our tipping bucket rain gauges which puts about 5msec of debounce into the event. ( See: Building an Arduino Weather station https://thecavepearlproject.org/2015/06/15/developing-an-arduino-based-weather-station/ ).
      The trick is getting two interrups to ‘interweave’ properly and I do that with a sub-loop at the end of the main loop, which only responds to the interrupt from the reed switch. Take a look at our old drip sensor code on github to see how we do that:
      https://github.com/EKMallon/The_Cave_Pearl_Project_OLD_codebuilds/blob/master/_20141002_DripSensors_WithPowerControl/_20141002_DripSensors_WithPowerControl.ino
      This uses interrups on D2 from the RTC, and D3 from the accelerometer to wake the system with sleepNwait4AccInterrupt. The ISR’s set flags, and only when the D2 RTC alarm flag is set does the processor break out of the while(clockInterrupt == false){ loop at the end of the main loop.

Comments are closed.