This project takes inspiration from many of the other similar low-power loggers on this site, but especially from the Cave Pearl project which I discovered about halfway through prototyping on this one. Instead of using several cheap modules, the heart of the data logger is distilled into just a few critical components.
The following software was used in the program for this device:
- Arduino MiniCore hardware package. The board is programmed like a normal arduino board with the arduino bootloader, but this package makes it easier to get a bare 328 chip working with many of the power-heavy features disabled.
- avr/power, avr/sleep, Wire, SPI arduino libraries, included with the arduino IDE.
- https://github.com/Marzogh/SPIMemory - for using the external flash memory chip that stores the measurements
- The SparkFun BME280 library - For configuring the BME280 sensor
To make the project itself:
- Make the board and assemble the components onto it. Everything is surface mount except the sensor board, which is an Aliexpress special.
- Flash the 328 on the board with the Arduino MiniCore bootloader. Make sure that the BOD is disabled, and the 8 mhz clock speed is selected. I tried 1 mhz as well, but found that the flash chip did not work well at this speed. The 328 can be programmed with ICSP, just like flashing a normal Arduino. The reset line, VCC and ground pins are brought out on the outside 5 pin header. The remaining SPI pins needed for ICP can be connected to either some test points on the board, or by clipping onto the legs of the flash chip.
- The board can now be programmed with a usb-serial adapter like any other arduino board. The tx and rx pins on the board connect to the rx and tx pins on the usb-serial device. The reset pin on the board connects through a 0.1uf cap to the DTR pin on the usb-serial, because I didn't include one on the board. Upload the main program.
- Push switches 1 (clock set) , 2 (flash erase) and 4 (status) on, and connect the board to a serial monitor and power (between 4 and 15 volts).
- Use the single button to set the clock following the serial terminal instructions. For example, to set the first parameter, the year, to 2018, press the button repeatedly until 18 is shown, then wait 2 seconds to continue.
- Erase the flash by pressing the button once when prompted.
- Return all dip switches to off position. Switch 4 can be left on, which will blink the green led whenever the 328 is powered up, but can be turned off to save power.
- After data is collected, turn switch 3 on and press the button. The data will be output over serial in the form of a table.
This project has been ongoing for a few months now, but I, like many people, don't document projects as well / as often as I should. This project represents a lot of firsts for me, such as the first time working with low power, first time ever soldering SMD components, and only the second project where I have designed a PCB. Most of my projects consist of either breadboards, prototyping boards, or some bizarre freeform/deadbug. I am not an electrical engineer or programmer, just a self taught hobbyist, which does sometimes mean that I have no idea if I am doing something "the right way." I want to keep my designs simple, using components that are well known, and programming no more complex than Arduino. With that in mind, the following ramblings explain my thoughts in building this project.
Since this was designed to be buried in a time capsule, the first order of business is how to get power. I had never worked with any low power sleep modes on microcontrollers, but I have plenty of devices that last for years with just batteries. Plenty of projects here on HAD that use a coin cell, but i'd be hard pressed to get 5 years out of one of those. Sounds like a good solution is normal AA batteries. I will use enough so that even when the battery is near dead, the voltage will still be high enough to power the device. It also gives me a bit of extra room to not worry so much about squeezing every last drop of juice out the batteries.
It's an ATmega328, nothing special. I thought about using an ATtiny, but since both have the same sleep power requirements, I kept the 328 for some extra pins and more ram, in case I wanted to expand the system a little or do some kind of heavier processing. Yes, this is essentially the same thing as building your own Arduino, but it's simple and it works.
The important thing is to be able to get the 328 into and out of sleep mode. Having never experimented with this mode before, Nick Gammon's tutorial taught me most of what I needed to know. I want this board to run for a long time, so everything must go, like the ADCs, and brownout detection. This brings the sleep current down to an impressive 0.1 uA. I'll re-enable any periperials I need upon waking up.
To wake up the chip, I'll use one of the interrupt pins.
I'm using a real-time clock chip to wake up the 328. It's much more accurate than an internal watchdog timer, and lets me add a timestamp to my measurements. I've used the DS3232 rtc before in the form of some inexpensive modules, so I decided to use them for this project as well. This chip contains a real time clock with temperature compensation. The clock accuracy is supposed to be quite good, on the order of a few PPM.
The DS3231 can be powered exclusively through the Vbatt pin instead of the normal Vcc pin. This saves some power according to the datasheet, but also increases the temperature compensation time to once a minute rather than every few seconds. For my purposes, this is fine.
For interfacing to the 328, 3 pins are used. Two are the i2c pins, and the third is the INT pin. The DS3231 has an alarm function, which can trigger this pin to go LOW when tripped. Connected to an interrupt pin on the 328, it is used to wake up the microcontroller from deep sleep. The 328 then resets the alarm, and reads out a timestamp over i2c. Alarm functions are not inplemented in most of the Arduino libraries I have found, so I wrote a simple one to make working directly with the RTC easier (but it only uses one of the two alarms).
My initial testing with RTC and microcontroller seemed promising, with the circuit waking up and blinking an LED once per minute as I had set it to do. However, when placing the setup in the freezer, the clock was more than a minute off after only a few hours. This is probably because the DS3231s I got from eBay were counterfeit. They work fine for room temperature operation (I have a counterfeit one in a nixie clock I made and it keeps accurate time) but my board needs to survive in freezing temperatures. A few genuine DS3232M from Maxim solved the problem, and my boards now keep accurate time even in the freezer. The M version is a smaller package, and is very slightly less accurate but is supposed to be more durable, using a MEMS oscillator instead of a crystal. The 3232 part number includes some extra battery backed general purpose memory, which I thought might be useful but is still not used yet in my design. The new chip takes the same commands as the old one, so no code changes were needed.
Initially, I tried using a 128kb 24lc1025 EEprom as the main storage space, but quickly found it would run out of space in less than the 5 year design life, so I would need to do something else.
While working on this project, I came across the Pearl cave project, where the same idea is used to make environmental sensors for monitoring caves. Their solution was to use an SD card, but it was found that different SD cards used different amounts of power, and that the cards did not like being turned on and off. Rather than an SD card, I thought about using a flash memory chip, maybe in the same way SPIFFS is used in my esp8266 projects. It would also be soldered to the board, with no spring connectors that could corrode or come loose. I settled on the Winbond 25q32fvsig, a 4mbyte flash chip. This would have plenty of room for years of measurements, and also has a sleep mode which takes the power down to a sub-microamp level. I used Marzogh's SPIMemory library for this, which takes care of most of the work in interfacing with the flash. When working with these chips, I found I could not write my 17 byte long measurement frame sequentially like I could with the EEPROM. Increasing the frame size to 32 bytes aligned them with the flash pages and I was able to read and write without errors, as well as fit a few extra measurements in. Now I can store 128k samples, instead of just 128k bytes. At one sampling per hour, this is almost 15 years of storage.
On the board in my picture, you can spot my mistake in the board design. I accidentally connected the reset and write protect pins to GND instead of VCC. This means that the chip is in a constant reset state, and cannot be read or written. With a Dremel, I carefully cut the traces. The reset pin is right next to the VCC pin, so a little excess solder is enough to bridge them. A jumper of thin wire across the top of the chip brings the write protect pin positive as well. This error is fixed in the released version provided in Files.
Initially, all I wanted to measure was temperature. However, that's not a lot of payout for 5 years work. Since the time capsule supposed to be a sealed PVC tube, I thought that it would be interesting to see what the internal pressure was like. The BME280 can do both temperature and pressure, and also humidity. It also has a low power sleep mode, and communicates over i2c. Since I've never soldered a part that small, I cheated and used a premade breakout board module, which fits on to the i2c header behind the main header. The header allows for more expansion also, in addition to or if another i2c sensor is to be used.
With the selection of a 3.3v memory chip and sensor, I was limited to running the board at 3.3v instead of the 5v I had originally planned. I didn't think that two AA batteries or a coin cell could last long enough and still be enough voltage to power the board after it lost some charge. Since I care more about reliability with no maintenance, and ton't have too much of a size constraint on the size of the batteries. I thought it would be better to run the components at some stable voltage that did not drop with the batteries (though I recognize that this will increase idle current draw). I could have run the 328 at 4.5v with 3 AAs, but I would still need an additional 3.3v supply and some kind of logic level conversion. The pearl cave project had the same problem, and solved it by using a simple linear regulator. However, the regular has to be a low quiesent current type, which drew little current on it's own, unlike an lm1117 found on most of the cheap Arduino boards. It took me a while to find a version that had an input voltage greater than 5.5v (in case I decided to use more than 3 cells), and still had good performance. Both the Mcp1703 and HT7773 are good candidates, and come in a sot89 package with the same pinout. I happened to have some of the through hole HT regulators on hand, and used them while I waited for some eBay mcp1703s to arrive. Unfortunately, the eBay mcp1703s turned out to be counterfeit also, and did not meet the claimed quiescent current listed in the datasheet. The current was instead around 70 microamps, more than 10x what I had planned. Again, some genuine samples from Microchip fixed the problem. Interestingly, the HT chips which are produced by a Chinese company and were bought overseas from an unknown seller performed perfectly.
Only seven IO pins on the 328 were being used thus far. Two for i2c, one for the clock wake up pin, and 4 for the SPI flash memory. I added an eighth, a voltage divider of high value resistors on an ADC pin to measure the battery voltage, which has not been fitted yet. But that still leaves lots of other pins open on the 328. I connected four of them to a small 4 position dip switch that I had on hand, three more to colored LEDs, and a button switch to the other interrupt pin. In this way, the board can still be verified working after disconnecting from the programmer. Otherwise, I can't tell if the board is working fine or a brick. The button enables waking up the 328 without waiting for the clock alarm to trip, which could take an hour on the slow setting. The dip switches allow for selecting different models, like setting the clock accurately to the second, or erasing the flash to start over, or dumping the flash contents over serial.
I decided to include a serial interface header on one side, so it will be easier to get the data off of the board when the time comes. I'll use the Arduino bootloader so I can program the chip over serial, since I have many more usb serial adapters than AVR programmers, and the cheap AVR programmers I do have only work 5% of the time anyways. VCC, GND, Tx, Rx, and the 328 /RST pins are brought out on the 5 pin header.