Since the Cave Pearl is a data logger, it spends most of the time sleeping to conserve power. So you could say that the most important sensor on the unit is the Real Time Clock, who’s alarm signal wakes the sleeping processor and begins the cascade of sensor readings. I built the first few beta units with the DS3231 Chronodot from Macetech (about $18 each), but I kept on stumbling across cheap RTC modules on eBay, Amazon, etc. and I eventually bought a couple to try them out. While I waited for them to ship on the proverbial slow boat, I did some digging, because these modules were (almost) selling for less than the chip itself if I bought them directly from trusted sources like Digikey, Mouser, etc.
So perhaps they are counterfeit chips, which are simply pin & code compatible? I also found rumors about “ghost” shifts, where legitimate manufacturer plants/equipment are used off the clock to produce extra parts. Or legitimate production runs which test out defective (if 10% of a run’s chips are bad, they often scrap the entire run) but someone intercepts the chips before they can be destroyed, and they resurface on the grey market. But even with all these possibilities in mind, I still have to make the Pearls as inexpensive as possible if they are going to be deployed in large numbers, and having an I2C eeprom on the board for the same money, made the temptation too great to resist.
(and you get temp to 0.25°, although only to ±3°C accuracy)
When the RTC’s arrived they had an LIR2032 rechargeable battery underneath the board, and a LED power indicator above. I had a feeling that neither of these were going to be friendly to my power budget so I went hunting for the schematics to see what I could do to improve the situation. I quickly found an Instructables post which described how to remove the battery charging circuit from a very similar DS1307 module, and then I found the datasheets and schematic for my DS3231 board over at at a site in Europe. Most of the parts were pretty straight forward:
But thanks to the tutorial by msuzuki777, I immediately zeroed in on a few parts that could be removed easily:
The power indicator (1) was pretty pointless, so that was the first thing to go. I already had pullups on the I2C lines, so they were not needed here, but they were in a combined 4 resistor block, which meant that to get rid of the pullups on SCL and SDA, I also had to remove the pullup on the alarm line. This had me a little concerned, as that alarm line is vital to the whole design. Without that resistor on SQW, I am relying on the weak internal processor pullups keep the alarm line high with:
digitalWrite(INTERRUPT_PIN, HIGH); //pull up the interrupt pin
Fortunately the pin stays high in all sleep modes and so far everything has been working with this setup (so fingers are crossed….again… 😉 )
Then I looked at the 200Ω resistor & diode (3) that are supposed to provide a trickle charge to the rechargeable battery. The LiR2032 that these modules ship with is 3.6v, and while capacity varies depending on where you buy them, most provide 35ma to 45ma capacity. Looking at the power draw from the DS3231, a fully charged battery would keep the unit backed up for at least 200 days (in a perfect world, with no self discharge, etc) But, it requires a 4.2v charging voltage for maximum charge, so vcc would have to be above 4.3-ish volts. I don’t anticipate my 3x AA power supply staying in that territory for the duration of a long deployment (especially if I end up powering the units from cheap AA’s) so there really was no compelling reason to keep the charging system in place. Once I de-soldered the resistor, I popped in a CR2032 (3v 240mAh) as a replacement which should backup the clock for several years of operation.
Libraries for that RTC?
I am using the Date, Time and Alarm functions in the library from Mr Alvin’s github,
which is based largely on Jean-Claude Wippler’s (aka JeeLab) excellent RTC library.
And it’s worth noting the clear alarm interrupt issue over in the Arduino playground.
Then we come to the AT24C32N (2.7 to 5.5v) memory chip that is also on this breakout board. Another of those 4 resistor bricks is lifting pins 1,2 and 3 to Vcc, so according to the eeprom datasheet this unit is being set to 0×57 on the I2C bus. There are pads there to ground out these lines if you need to reassign the address to something else. Although I have already determined that eeprom is not the power savior I hoped it might be (all that eeprom reading & writing uses about 1/3 the power of simply writing the data to the SD card in the first place) it’s presence lets me be really lazy on the coding and just pop any numbers or characters that I want into a PSTRING’d buffer which then gets sent to a standard eeprom page writing routine. This flexibility allows me to swap sensors with dramatically different output, while retaining essentially the same code to handle the eeprom loading and the transfer of data back out to the SD card. If you want more information about that you can head over my earlier post on buffering sensor data to an I2C eeprom for the gory details.
To top it all off, the cascade ports on the far side of the module let me “just barely” fit the rtc, the I2C hub (with corners sanded off), and main TinyDuino stack onto the platform in the middle of my housing. I am lifting the voltage regulated I2C bus traces from the TinyDuino light sensor board, so I am also hunting around for an off the shelf vreg & level shifter combination to replace that hack (because that bit of soldering is a pita). But overall, I am very happy with this build, as all the central data logging functions have come together into a nice securely mounted package, that should withstand significant knocking about during the deployment dives. Of course there is plenty of field work testing still to be done, so time will tell (sorry, couldn’t resist…) if these cheap RTC’s will cause more trouble than they are worth.
It just occurred to me that sooner or later Tinycircuits will be releasing an RTC board, and that will give me a chance to directly compare these cheap boards to a “trusted” clock signal provided that their chip does not want the same bus address. Or if their clock wants the same I2C bus address as this eBay RTC, I could use a DS3234 on the SPI bus. I will post an update when I can run that test to spot clock drift, alarm errors, etc. Several sites have mentioned that real DS3231’s drift about 2 seconds per month, while the cheaper ds1307’s drift 7-10 seconds per day. If you have the right equipment, you can make the chip even more accurate by adjusting the aging offset register.
I just realized something else odd about my setup here. The I2c bus is held at 3.3 volts by the regulator on the tiny light sensor shield, but I am pulling up the SQW via the tinyduino cpu, which is following the voltage on the battery pack because the tiny CPU is unregulated. So the pull-up voltage on the alarm line is out of sync with the voltage seen by the rest of the DS3231 chip….hmmmm.
(2014-10-28 : data sheet says its Ok to pull the line all the way up to 5v, even on Vbatt)
I created a very inexpensive 3-component data logger with this RTC, a Pro Mini mcu board, and a cheap sd card adapter. And you can see a post about the latest version of that logger concept here which has added a power shutdown feature. In those Pro Mini based loggers I do not remove the I2C pullup resistor bank as shown earlier in this post (2 in the photo above), as the removal is only needed if you already have pullups in place, as I did when using the hacked Tinyduino light sensor board to drive the RTC. I have built many loggers now, and some of them have come close to 400,000 alarms & eeprom write cycles, so these cheap RTCs are proving to be pretty durable.
I have noticed that when I power this module from Vcc at 3.3v, it draws around 89 µA. But according to the datasheet,the RTC should only draw ~2 µA on average when powered from Vbat. (1µA baseline plus about 500µA for 100ms every 64 seconds when the crystal is doing temperature compensation) Nick Gammon found an elegant way to power a DS1307 by connecting Vcc to one of the Arduino pins , driven high in output mode when the system is active. (look about half way down the page) When the Arduino pin is low, the clock reverts to battery power, and goes into the low current timekeeping mode. But according to the datasheet, Bit 6 (Battery-Backed Square-Wave Enable) of control register 0Eh, can be set to 1 to force the wake-up alarms to occur when running the RTC from the back up battery alone. [note: This bit is disabled (logic 0) when power is first applied] So you can still use the RTC to wake the Arduino, even if you have de-powered it by bringing the pin low. I have tested this and it seems to work fine on my RTC modules, reducing the sleep current by about 70 µA. (or ~ 600 mAh per year = almost 1/4 of a AA) Tests are underway now to see if this is stable as a direct jumper to the pin without using a current limiter, which might give me a problem with inrush current unless I also add a resistor as N.G. did.
And since my loggers are going in caves where the temperature does not change very quickly, I am bumping the temp conversion time from 64 to 512 seconds as per Application note 3644, in theory reducing the battery drain to < 1 µA. It’s a little unclear from that datasheet if this only really works on the DS3234 (?) but if it does this puts the battery discharge on par with electrolyte evaporation if Maxim’s coin cell lifespan estimates are to be believed.
And finally, doing this means that you are relying on the Cr2032 to power the clock for a substantial amount of time, so you need to make sure you are not using fake coin cell batteries. Name brand packaging is no guarantee of good batteries either! In learning this little lesson I discovered that you can not simply read a CR2032 coin cell with your volt meter to determine if it is healthy, as the no-load voltage stays above 3v even when the cells are nearly dead. As per the Energiser datasheet, I read the cell with a 400 Ω resistor pulse load (for 2 seconds). If that gives me >3v I call the cell good. If you are stuck out in the field without a meter, check if the battery bounces well.
I do wonder if its worth putting a 100uF multilayer ceramic capacitor on the coin cell to buffer the impact of the alarm events. But I don’t know how much I would then loose to capacitor leakage. Abracon seems to think its a good idea in their application note, claiming 11 µA leakage for a 100µF MLCC. But that is more than 3x the current draw of the DS3231 in timekeeping mode.
NOTE: If you try powering the entire breakout board from a digital pin, you are essentially turning the onboard SDA & SCL resistors into pulldown resistors and these fight against the Atmels internal pullup resistors on the 328 that get enabled by default in the two wire library. For details on how to fix that problem, check out this post on the Arduino playground: DS3231 drawing 200+µA through SDA/SCL Also note that I had to go all the way to (x86)\Arduino\hardware\arduino\avr\libraries\wire\utility to find the twi library on my machine, but if you power your DS3231 by lifting the pin from the board like I do, the library edit does not change the sleep current.
This 32k AT24C256 is pin for pin compatible with the 4K AT24C32 on this RTC module. For only $1, it’s really tempting me to do one more little modification to the RTC breakout, although on reflection I think it might be quite handy to have two easily accessed eeproms in the system, using the smaller one for persistent storage of calibration & configuration info, and the other much larger one for sensor data. Keeping the 4K eeprom will limit the I2C bus speed to 100 kHz, while the larger AT24256 opens up the possibility of raising the I2C bus speed to 400 kHz.
Testing confirms that the AT24C256 is a drop in replacement. The code I was already using to write data to the eeprom on the RTC breakout worked fine provided I changed the I2c address to 0x50 (while the 4k eeprom on the rtc breakout is 0x57 because its address lines are pulled up). In my case, the larger eeprom allows me to buffer 512 of my two-page write cycles before having to transfer the data out to the SD card. And after some testing, I have confirmed that both eeproms go into standby mode at 1 µA when they are not being accessed. The only challenge is that this many buffered readings represents several days worth of data…so I will need to come up with some kind of procedure for shutting down the loggers without losing information. One solution would be to add a function that flushes the entire eeprom to the SD card during setup. That way simply hitting the reset button would make sure that any residual data in the buffer gets saved before I disconnect the batteries.
In some of my older loggers that were put together ages ago, there is not enough space to easily do this jumpering right onto the RTC breakout, so I came up with some “in-line” eeprom upgrades that I could just drop in without changing any other wiring on the build.
I have recently run into another RTC related issue, which is how to set the RTC’s more accurately. Now that I have multiple data loggers on the go, the led pips show me that the loggers are as much as 4 seconds* different from each other, and that gets even more pronounced when I use different computers to upload sketches. Retrolefty has proposed one method for “syncing by hand” at the playground. I will post some results when I find out if the Whac-A-Mole method reduces my inter-unit time offsets.
One solution would be a sketch that uses an Ethernet shield and connects to an internet time server. Then you could get the offsets down to average round-trip time (using the nearest NTP server) plus the serial communication. But I do not have an Ethernet shield, so that is a non-starter. Some use a GPS for an accurate time signature, or a dedicated time signal receiver. But my PC is already synced, so buying hardware just to reproduce information that is already available seems like overkill. A more logical approach would be to have two programs, one running in the PC environment then second running inside Arduino. Then both programs could communicate (PC -> sends time stamp via serial line -> Arduino reads value from serial line & sets clock to match). I have not found a set like this yet.
In addition, I would like to have all my loggers running UTC, but that’s easily address by just setting my machine to UTC before setting the clock. UTC avoids all the problems with ‘local’ daylight savings time, etc.
* It looks like I might have been causing that problem by opening the serial window to to check that the clock was updated properly. Makes me wonder why the RTC set sketch was written with serial output in the first place?
This is good to know, although of course one source/batch doesn’t confirm them all when you are dealing with cheep eBay knock-offs. For a different approach to testing, jremington over at the playground notes: “By comparing the rising edge of the RTC 1Hz square wave output to that of the 1 Hz PPS output of a GPS unit with a good satellite lock, you can determine within a few hours how much the RTC is drifting. ”
(no need to use a PIC, though…)
I have been noodling around with new sensor combinations for my next set of builds, and I thought I would post a quick overnight comparison of the DS3231 temperature register ( rated at ±3°C ) to data from the Adafruit MCP9808 ( ± 0.25°C ).
Degree Celsius vs Time: (5 min samples)
You can see that the DS3231 has a much lower bit depth, but I was pleasantly surprised by how closely they tracked each other. If the datasheet claims are to be believed, the 9808 should be dead-on in this temperature range. This gives me more faith in the data from that humble RTC, which currently records ambient temperature in my drip sensors.
Addendum Update: Although I did not catch it when I posted this graph, I was converting the LSB portion of the temperature register with:
TEMP_degC = ((((short)MSB << 8) | (short)LSB) >> 6) / 4.0;
from Coding Badly at the Arduino forum. There should have been no “bumps” on that graph smaller than 0.25°C. But what I was actually getting a mix of xx.00, xx.25, xx.244 and xx.238 in my data. No half degrees, and no temps that read xx.75 You can see those temps are missing, as “steps” in that graph.
So I tried this code to fix that with this code from the Arduino forum:
Wire.write(0x11); //location of Temp register MSB, LSB at 0x12
bytebuffer1 = Wire.read(); // Here’s the MSB which is an int
bytebuffer2 = Wire.read(); bytebuffer2 = bytebuffer2 >> 6;
// the upper 2 bits of the LSB represent quarter degrees 00=.00 01=.25 10=.50 11=.75
TEMP_degC = float(bytebuffer1);
TEMP_degC = TEMP_degC + 0.00;
case 1 :
TEMP_degC = TEMP_degC + 0.25;
TEMP_degC = TEMP_degC + 0.50;
TEMP_degC = TEMP_degC + 0.75;
// see http://forum.arduino.cc/index.php?topic=262986.15 for temps below zero with no floats
But I got the same result with that code too which is very puzzling to me?? Where are the .238 fractional temperatures coming from? Why do I never see xx.5 or xx.75 temperatures?
Addendum Update Update:
So it turns out that both examples of code above work fine, but the way I was converting the fractional part of the decimal (so I could print them as integers: printing real #’s takes too much ram) was incorrect. All my other temperature sensors provide at least three digits of information after the decimal place so I had been using fracTemp=(TEMP_degC – wholeTemp) * 1000; to extract the fractional data. But this did not work for the RTC fractional data. Changing it to fracTemp=(TEMP_degC*100) – (wholeTemp*100); converts the decimal part of the RTC temperature into integer values normally. Thanks to Stack Exchange for showing me that you need determine exactly how many decimal points you want to turn into the integer before you do a conversion like this, or the calculation yields weird results. In my case the error changed xx.05 into xx.0244, and xx.75 into xx.238. Fortunately that error was correctable, so here is what that graph should have looked like:
Recent fieldwork gave me a chance to check clock drift on six loggers using these RTC boards. All of these RTCs were set at the end of August and over the course of about 4 months, all of them lost between 30-40 seconds. That puts these cheap units over the minute per year territory that I see claimed for “real” DS3231 breakouts like the Chronodot, but not by enough to make me worry too much as this was a pretty crude test. These modules are still way better than any DS1307 alternatives.
I have been putting together some smaller underwater sensors using two inch pvc pipe, and the tight curved profile of the housing forced me to flip the RTC over. As soon as I did this, I realized that I should have been mounting the RTC this way all along, as it makes it easy to replace the coin cell without undoing the nuts on the standoff bolts. And if I am going to be pin-powering the RTC, I will probably need to change those coin cells regularly. It also lets me use shorter 12mm standoffs and still tuck everything under the RTC.
Steve Hicks over at envirodiy.org has posted on how to convert the DS3231’s epoch time (ie: #number of seconds since January 1, 2000) into unix time and here they convert unix time into Excel standard dates with [=CELL/(60*60*24)+”1/1/1970″ note: you have to have the RTC set to UTC for this to work]. Using epoch time lets you store or compare times as a single 32-bit number (another conversion method here) rather that dealing with 6 numbers and details like the number of days in each month and leap years. A very handy tip. You can view a datalogger script example using long epoch = now.unixtime(); over on Github.
P.S. The RTC library I’m currently using gives me unix time with:
DateTime now = RTC.now();
Serial.print(“Seconds since midnight 1/1/1970 = “);
But if yours does not, it is fairly easy to calculate an epoch time integer from the standard YY MM DD MM SS format, if you have your clocks set to UTC.
I have decided to pin power all of my next generation of loggers, including the long chains of DS18b20 temperature sensors I have been working on. But I still don’t know exactly how much impact generating the interrupts will have on the coin cell over time, so I have added a voltage divider connected to the backup coin cell on RTC board, with the center drawn off to an analog input pin on the Arduino. I am hoping these 4.7 MΩ resistors will add only 0.35µA draw to the ground line and perhaps double that when the ADC input capacitor is being charged for a reading. The readings wobble a bit without a capacitor to stabilize them, but I was afraid that leakage on a MLCC would be larger than the RTC’s sleep current so I left it out. I read the pin three times with a 1ms delay, throwing away the first reading and averaging the next two, and that gets me a reading pretty close to what I see on an external volt meter. But CR2032‘s are lithium batteries, so I might need to put some kind of load on the coin cell to actually read it’s capacity. I was thinking I could do this by forcing a temperature conversion while the pin power is removed. (setting bit5 of reg 0Eh which draws 575 µA for 125-200 ms) This approach would waste some energy and create time delays, so I will do my first few test runs without the “load” to see if I can interpret the reading from that voltage divider without it.
There is another question about pin powering these RTC’s that is niggling at the back of my mind: What happens when I have Battery-Backed Square-Wave Enable set, so the RTC generates alarms when it is powered only by the backup battery, and I disconnect power to the main Arduino before the next alarm? Presumably the alarm still gets generated, but nothing can respond and reset it. My hope is that the open-drain SQW pin, which should only sink current, does not somehow create a circuit through the Arduino that bleeds away power in this situation. Especially now that I have the voltage divider in place…?
I just returned from another fieldwork trip, and I had the chance to do proper RTC drift checks on twelve data loggers that were deployed in Dec. 2014. After three months of operation they all had offsets between -24 to -30 seconds, and the remarkable consistency across these units made me suspect that I was looking at something other than random errors. I reset the clocks with the little netbook I had on hand, and re-checked the clocks. Sure enough every one of them was reading the current time -24 seconds. I checked the time on the six new new loggers that I had prepared before the trip and every one of them was exactly nine seconds slow (my computer back home is much faster than the netbook I take into the field). When I reset those new loggers with the netbook every one of them became 24 seconds slow. So it looks like the time lag caused by the compile & upload of the RTC set sketch was responsible for the majority of the offsets I reported back in December, and that these DS3234SN RTC’s actually have a drift somewhere between 0-5 seconds over a three month deployment. This is well within the manufacturers spec. And now that I know the compile time is the limiting factor, at least I can be certain that the units all have the same negative time offset before each deployment.
NOTE: With further testing I have found that if you simply hit the verify button before you hit the upload button, the resulting RTC time offset is reduced to 1/2 (or more for slower systems). On my home based system this reduced lag caused by the compile & upload from ~20 seconds to about 9 seconds. I expect to see even more of a difference on my really slow netbook. In theory you can improve things even more by removing the verify option as you upload. The RTC time setting sketch is the only place where I would risk errors to get to a faster upload time, since I immediately have to replace the RTC “setting” sketch with a “read time only” sketch to confirm it worked anyway.
Update 2016-10-14: I’ve been referring here to the setTime sketch that used to be provided with MrAlvin’s library. This sets the RTC to the compile time with the command
RTC.adjust(DateTime(__DATE__, __TIME__)); His new version has a method of setting the time using the serial monitor, which removes the compile time lag time problem. I’ve gotten used to using setTime & getTime , so I still keep a copy of those older utilities on my GitHub. Paul Stoffregens DS1307 library uses the same compile time method to set the DS3231, but you have to install his Time library as well.
Just digging into the recent data set, and noticed that one of the drip sensors we left out on the surface (to act as a rain gauge) got baked as the local climate went into the dry season:
This is the record from the RTC, and I am surprised the batteries did not pop with the loggers internal temp hitting 60°C. The good news is that even after subjecting the RTC to this ordeal, the drift for this unit was the same as the units that were left down in the caves. This logger went back out for another stint in the tropical sun, as I am a firm believer in testing my builds to their limits.
That last deployment saw several loggers run successfully with pin powered RTC’s so I though I should post the little code snippet I use to do that. I have the de-powering embedded inside the function that puts my loggers to sleep
In setup: (note brackets missing around includes!)
#include RTClib.h // https://github.com/MrAlvin/RTClib
#define RTCPOWER_PIN 7 // this is the pin I have jumpered to the RTC’s vcc leg
So after the setting the next alarm time in the main program loop
//The variables ALRM1_SET bits and ALRM2_SET are 0b1000 and 0b111 respectively.
I use this function to de-power the RTC and the data logger
#ifdef RTCPOWER_PIN //if using pin power on RTC, now depower it:
pinMode (RTCPOWER_PIN, INPUT);
// driving pin LOW FORCES to the RTC to draw power from the coin cell during sleep
noInterrupts (); // make sure we don’t get interrupted before we sleep
interrupts (); // interrupts allowed now, next instruction WILL be executed
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
detachInterrupt(0); //HERE AFTER WAKING UP
digitalWrite(RTCPOWER_PIN, HIGH); // about to generate I2C traffic
pinMode (RTCPOWER_PIN, OUTPUT); // so provide power to the RTC
and clocktrigger is the ISR that updates a variable checked in the main loop
clockInterrupt = true;
So there you have it. After 3 months of reliable operation, and no coin cells killed off in the process, I am calling this good code. BTW this is how I currently connect the RTC boards to the Arduino:
After finding Rob Tillarts multispeed I2C bus scanner, I was happy to notice that all my I2C devices showed up on the higher speed scans. So I have started pushing the bus to faster 400 khz speeds with TBWR=2 on the 8Mhz boards, and TBWR=12 on the 16Mhz boards right after Wire.begin(); The DS3231 is rated for it. The larger AT24C256 eeprom that I have been adding to my loggers is also rated to that speed, but even the smaller AT24c32 on the RTC board seems to work ok at the higher I2C bus speeds, though it is only rated to 100kHz. Since I had been using the I2C communication delays as part of my led pips, I could immediately see shortened operating time (my pips became too short to see) . I have some doubts about whether a humble 8Mhz Arduino can run the I2C bus that fast. Without a scope, or some way to determine the capacitance on the lines, there’s no way to know if I’m actually reaching 400khz with the 4.7kΩ pullups on that RTC breakout. But with quite a few run tests going well thus far, I think add the TBWR settings to my standard code build to shorten mcu up time.
I have done a few more tests using a 2x 4.7MΩ divider to monitor the coin cell. The divider definitely works but as expected it also bleeds 0.32µA from the coin cell when the Arduino is powered & sleeping. If I remove power from the whole Arduino, the current drain from the battery through the divider rises to almost double that at 0.56µA. Pin Powering the RTC during uptime and letting it go into timekeeping mode (3 µA) while the Arduino sleeps (with the coincell divider in place) appears to be causing a 5-7mV drop per day on the CR2032 coin cell. With the 2300 mV minimum for the DS3232’s vBatt, that probably means the coin cells will only provide about 4-5 months of pin powering before the little cells need to be replaced. This is a somewhat irritating as I thought I would get more time than that from the 240 mAh coin cells. I am suspecting there are other drains occurring somewhere.
One trick I can try is to set the coincell reading analog pin to INPUT_PULLUP with a pinmode setting while the Arduino sleeps. This would raise the middle of the voltage divider to 3.3v – above the coincell. This will also send 0.7µA from the analog pin through the grounded leg of the divider. When I tried this I found that it also pushes about 0.03µA back towards the coin cell’s positive battery terminal where I have the divider connected. I don’t know if that power is flowing into the lithium coin cell (which is probably bad for CR2032’s – but perhaps it would be ok with an LIR2032?) or into the RTC somehow (?) So this strategy would shut down the divider power leakage from the coin cell and hand it off to the much larger main batteries. This is much lower than the 89µA that the RTC draws if you power it via the Vcc line, but it seems a bit dodgey to flip flop between analog and digital modes on that pin all the time.
I will have to do more tests before I trust that this is not hurting the RTC or the Arduino. Having the lithium coin cells catch fire when their voltage got low would not make my day either. And if I was going to have a small constant drain from one of the pins I might as well just replace the coin cell backup battery with a capacitor – which could be kept charged by the pin that I am currently using to check the backup battery voltage. That way I’d never have to worry about changing the RTC batteries once I got the system rolling…hmmmm…I wonder what the capacitor leakage current would be?
P.S. In my tests to date, the faster 400khz I2c bus settings settings still seem to be working OK.
Looks like my earlier concern about the new divider creating and excessive drain the RTC backup battery were unfounded. Several of my bench test loggers saw an initial drop off but all of them seem to have leveled out around a nominal 3.05 v.
Most of the new batch have this 2 x 4.7 MΩ divider in place and I am now confident that it will be Ok to deploy those units, which likely will not be retrieved till the end of the year. Btw there is a fantastic page over at ganssle.com testing the behavior of CR2032 batteries at low currents. Granssle’s article on Issues in Using Ultra-Low Power MCUs is worth reading. Hackaday’s post on TI processors shows how far the art in low power operation goes. Ignoring self discharge, a CR2032 should be able to last about 4 years if the average draw stays below 5 µA, and the divider is adding ~ 0.7 µA to the RTC’s base load.
Just a quick update on that coin cell reading. I continued that test (on a logger with 20 DS18B20 temp sensors) and the coin cell voltage rose after the break then fell again to about 3040mv:
So at least I am not seeing a catastrophic fail when trying to read the coin cell, but I am still left with the question of whether this reading actually means anything, given that the loading on these lithium cells is a mere 3μA when the RTC is in timekeeping mode. So I still might be shortening the lifespan of my loggers below my 1 year target with the pin powering technique if the coin cells can’t go the distance. At 150-200 mAh /cell, there should be no problem…but I have made the mistake of counting those chickens before. And I still might need that 1µF cap across the lower resistor, which in theory will cost me ~1nA in leakage.
Note: Data from the batch of loggers deployed in Aug 2015 displays a similar pattern to my bench test results:
All the loggers using 2×4.7MΩ dividers to track the coin cell leveled out somewhere between 3020 & 3040 mV, and I attribute the differences there to ADC & resistor offsets. So I will adopt this as a standard part of my new builds.
I prep these RTC’s in runs of 10 to 20 pieces, as this makes the best use of the isopropyl alcohol in the ultrasonic bath. While I was de-soldering resistors on the latest batch (to disable that useless charging circuit) I realized that the first part of the UNO based Datalogger Tutorial (that I put together to help some teacher friends of mine bring Arduinos into the classroom) gives you great platform for testing a bunch of these RTC’s quickly. You can just pop them onto the breadboard in quick succession before you invest any time cleaning them up. You don’t even need to put the battery in! And the code that I posted to Github for that logger is about the simplest example you are likely to find of how to use this RTC breakout to wake a sleeping Arduino.
Just stumbled across a post at Arduino Stackexchange on combining day-month-year data into strings, and using that as a date-stamp file name. This could be handy for “threshold/event” based loggers, as opposed to the more typical take a sample every X minutes approach. I think this method is limited by fat16 to generating a max of 512 entries in the root directory.
Data from a cave deployment of one of our multi-sensor units:
so I am impressed again with the temp accuracy of those humble RTCs. This is also a really great illustration of what gain when you add more bits to your ADC.
Over at raspberry-pi-geek.com they did some benchmarks with four I2C RTC’s: the DS1307, the PCF8563, the DS3231, and the MCP79400. Their graphs show the DS3231 as the overall winner, suggesting that this is is a result of the temperature compensation. It will be interesting to see if they do the tests over again with temp variation to see how this affects the RTCs accuracy.
Just stumbled across a playground forum thread where user Tominakasi tried replacing the backup battery with a capacitor. He reached 24 hours of operation with a 0.22F capacitor, but I would need significantly more time than that in a logger application. If I play with some datasheet numbers over at Maxim’s Super Capacitor Calculator, it looks like it might be feasible with a one farad cap. But folk’s over at Sparkfun, seem to think that leakage current would be a serious problem. Since I am already tracking the coin cell voltage with a resistor divider on the top of these boards, I think I will pickup a 5v 1F super cap and try an experiment to find out how long it actually takes for it fall to the RTC’s 2.3v minimum. It would not take much to connect one end of that cap to a separate digital pin and then top it up when necessary because the Arduino will keep a pin driven high even while sleeping. Probably not worth doing for a regular logger, but if I was building something completely potted in epoxy… hmmmm…
There must be a million great clock projects out there, but I stumbled across a couple recently that looked like they would be fun to build. The idea embedded in the Laser Cut Clock by [Buckeyeguy89] really has legs, and I think it could go on to some very interesting higher levels of complexity. And I am sure that I am not alone in drooling over the Ferrofluid Clock by Zelf Koelma, to the point of wondering how I could drive batch of small electromagnets with an Arduino…
Another coin cell curve (mV) from a longer deployment:
This was from a 2×4.7 MΩ set, so I am more confident that we will go a year even with the added drain from the divider. I have since switched over to using 10 meg Ω resistors, but there is some question of whether the ADC sample & hold caps can will get enough current to read that properly. I’ve been dating the coin cells with a marker to help keep a tab on their lifespan.
Just had to post a link to the Arduino Sport Watch Instructable by Alexis Ospitia which combines this DS3231 board with a pro-mini and one of the ubiquitous Nokia 5110 LCDs.
There are a host of changes coming as the ATmega 328p becomes the 328pb. But relevant to this thread, the full-swing oscillator driver circuitry is being removed. While this won’t affect a low&slow application like data loggers, it might spur a few more people to look into the 32K output from these boards. If that’s your thing, there are some interesting frequency measurement guidelines over at sitime.com
Just had to add a shout out here to Luke Millers Tide Clock as a great use for the DS3231 breakout, and a great addition to his Open Wave Height logger project. There are only a handful of us focusing on underwater logging, and his work on the MS5803 was a great contribution.
I’ve been trying out some $2 coin cell testers from eBay, and so far they seem to be working ok. There’s a big logger service trip coming up, and this will come in handy.
Just found out about a time-related function in Excel that is really useful to know about if you are trying to isolate subsets from your time series data:
…use a helper column and then filter on the results of the helper column. Assuming your date/time record starts at A2, and column B is available, then enter the time interval you wish to filter on in cell B1 (e.g 10 or 30 etc). Then enter the following formula in cell B2 and copy it down the rest of the column:
This will provide a TRUE/FALSE value if the time conforms to the interval value contained in cell B1. Then filter all the records based on the TRUE values in column B.
I tend to run my bench tests pretty fast to give new builds a real workout, but then I end up with far more data than I need for calibration / normalization. This little trick works a charm to bring that back to more typical 15 minute sample intervals.
And while we are on the topic of time in Excel, it’s worth mentioning that the program sometimes refuses to convert time stamps from commercial loggers into its native number format. In that case you end up having to extract and convert each piece of text data with a =DATE(year, month, day) and =TIME(hours, minutes, seconds). As an example, converting some weather station times tamps that looked like this 01.01.2009 02:00 ended up needing this beast:
=DATE(MID(B2,7,4),MID(B2,4,2), LEFT(B2,2)) + TIME(MID(B2,12,2), RIGHT(B2,2),0)
I was showing a friend how to set the time this RTC recently, when we made the surprising discovery that you can not easily set the system clock on an Apple to UTC. You can select London, England, however England uses daylight savings time and as a result uses GMT (UTC+0) during the winter and British Summer Time (UTC+1) during the summer. (aka selecting London as the city to base my timezone does not provide UTC year round, only in the winter). A bit of hunting revealed that there are other cities in the GMT timezone that do not use daylight savings time such as Ouagadougou, Burkina Faso, and there are other fixes out there if you are willing to go under the hood. But its just hard to believe that Apple made it so hard to set a computer to the global time standard…weird.
With long startup latencies & initialization issues in the SDfat library, I haven’t pursued approaches that remove power from my loggers between samples. But I’ve been reading about what might be the most elegant approach to that method for data logging applications: Using the RTC alarm (which outputs low) to control a P-channel Mosfet (AO3401). Geir Andersen discusses this over at LetsMakeRobots, and I think it’s the method that he used on the Deadbug shield. The idea is that when the RTC alarm line goes low, the mosfet turns on, powering the processor that goes to work taking samples, storing data. Then power is shut down by resetting the RTC interrupt flag. Even more interesting were hints that this approach was used with an ESP8266 to build a mains dimmer switch. Food for though, as I can see how stabilizing the Mosfet control line could be tricky…
I tweak the code on most of my loggers between deployments so often only the more unusual sensor combinations get run for long periods of time without a clock reset . The last round of fieldwork had me updating several of those old dogs, most of whom had been running for more than a year, and this let me do some RTC drift checks. There were two end members for the set; with one unit losing 1.1 seconds per month, and another gaining 1.4 seconds per month. Most of the other loggers drifted forward by ~ 1/2 second per month. So my two worst-case units have drift rates about twice as large as the 0.026 seconds per day they saw at SwitchDoc Labs, but most of the units are in good agreement with their benchmarks. All of these loggers were in a very stable thermal environment (ie. a cave) at around 24°C. Depowering the RTC does not seem to increase the drift, (in fact David Pilling found that timekeeping on these boards actually improves when you disable the lithium coin cell charging circuit) and the coin cells look like they will last well past two years with this level of drain, but it’s still uncertain exactly when they will quit due to flat lithium discharge curve.
And while we have plenty of high-precision sensors for temperature data, the RTC registers continue provide a convenient ‘inside the housing’ record:
(The log shown above is from a very dynamic site with several entrances to provide airflow, but most of the other temp. records hover near the bit toggling point all year. )
While there is a lot of lag in the RTC temperature reading due to the thermal mass of the housing, these logs still provide a good sanity check when my other sensors are starting to fail.
Hackaday released a post on the quartz crystal resonators which provide the heartbeat for RTC modules. Adafruit has produced a DS3231 module, if you want something more compact than these cheap eBay units, without the EEprom.