- Chapter 0 – Introduction
- Chapter 1 – Arduino I2C
- Chapter 2 – Continuous EEPROM Addressing (digression)
- Chapter 3 – Update and Sleep Design
- Chapter 4 – Clock Design and Sleep Investigation
- Chapter 5 – Gallery
- Chapter 6 – Results
- Chapter 7 – Final Report
- Chapter 8 – Followup 1
In this episode, I’ll discuss how I got the DS3231M real time clock to set and report the time properly, and how I got the alarm working. After that, I’ll give some of the results I found while investigating sleep modes.
DS3231M Clock Design
Setting the clock and reading the time turned out to be pretty simple, just standard I2C register writes and reads, all explained in the datasheet. I decided I wanted a periodic alarm from the DS3231M to trigger an interrupt, which I could use to wake the microcontroller up from its slumbers. The DS3231M allows you to do just that, so I set it up to go off every minute, on the minute (as a test, once-per-hour could come later). According to the datasheet, the way the alarm works is this: every second, when the clock updates its current-time registers, it checks the values against the alarm registers (subject to the alarm mask, which determines whether to match only seconds, seconds and minutes, seconds and minutes and hours, etc. for periodic instead of one-time alarms) and if they match (and it is configured to do so), it drives the /INT,SQW pin low and sets the alarm triggered bit in the status word.
The interrupt pin is hooked up to the Boarduino’s digital I/O pin 2, which happens to also be interrupt 0. Furthermore, the Sleep library I selected (http://code.google.com/p/arms22/downloads/detail?name=Sleep003.zip) allows you to go into the deepest sleep (shutdown mode) and provide an interrupt (either 0 or 1) to use for waking up. The interrupts can only wakeup from shutdown when triggered on low, but since that’s what the /INT,SQW pin does anyway, it shouldn’t be a problem.
Piece of cake, right?
Well, I found that the alarm would go off after a minute, all right, but after it went off, it would continue triggering every second when it updated. It is not explained clearly in the datasheet, but it appears that the alarm will continue to drive the interrupt until the status alarm triggered bit is reset by the user. So, after I wake up from sleep, I reset the alarm triggered flags first. Then, I collect my temperature sample, write it to EEPROM, and then go back to blissful sleep, which now waits until the next time the seconds match (one minute) and the DS3231M triggers it all over again.
I was able to retrofit an old battery holder, and hook it up to the Boarduino I’m using to develop the software (still no luck programming the standalone ATmega328P with the Arduino bootloader, so I may have to stick with the Boarduino for the final project). The Boarduino ran just fine at 3V, instead of the usual 5V from the USB FTDI cable. I had it set to use external power (there’s a jumper to select), and just hooked +3V from the batteries to one of the +5V pins on the Boarduino (and hooked the GND from the batteries to one of the GND pins). It ran just fine with its 16MHz resonator, though I understand that 16MHz at anything less than 5V is out of spec.
Anyway, I checked the current draw when powered from the FTDI cable and from the batteries. In interactive mode, this was 20mA and 9mA, respectively. In embedded mode (going to sleep when inactive), this was about 3.3mA in both cases. When active in embedded mode (i.e., not asleep), the draw was always about the same as when in interactive mode, so from now on I’ll just refer to the “active” and “sleeping” current draws.
It seemed to me that 3.4mA was way to much current to draw while sleeping, and so I set out to find out what was taking so much of it. I tried cutting the power LED resistor lead, and found that it took about 1.4mA, so that got me down to about 2mA for sleep mode. Still not very good. What could be using it?
First, I checked the current draw from the EEPROM and the TC74, in hopes that maybe they were using the power, and I could kill the power to those devices while sleeping. I found that they only took about 4.7uA while sleeping, and about 1.8mA while active, so they must not be the culprits. Besides, I was already putting the TC74 into its “standby” mode, so I didn’t expect to find it here, anyway. However, it was the easiest to check, so I looked there first.
Then, I checked the DS3231M, which I had powered separately (thinking I might still want to try some battery backup for it). It took about 120uA while inactive (no I2C traffic) and about 590mA while active, which pretty much matches the datasheet. Still no good.
After reading around a bit, I found some mention that on the Arduino proper, the FTDI chip uses some power. I realized that I had left the FTDI cable attached (to see serial output), so I tried unplugging that. This forced me to use power just from the batteries, but bingo! In sleep mode, power consumption was down to about 180uA, about 120uA of which is probably from the DS3231.
A whole order of magnitude is nice to get (180uA instead of 2mA). I haven’t looked to hard for data about battery life at super low current draws, so it’s hard to have much in the way of analysis. The 5th contest dispatch (http://makermedia.createsend.com/T/ViewEmail/r/B0BCC1D7788629CC) refers to the battery datasheet, which has a chart that goes down to 10mA (showing about 200 hours of operation). I’m using about 2% of that, so as a completely rough guess based on suspect assumptions, I’d say 2000mAh of battery at 180uA ought to give me ~11000 hours, which comes to about 460 days, which is well over a year, much more than the growing season I was going for. So, unless I’m way off, it looks like this project will be able to serve its purpose without more battery life optimization.