Electronic Time Capsule: Difference between revisions

From Alnwlsn - Projects Repository
Jump to navigation Jump to search
 
(42 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[File:Eagle.png|thumb]]
This is a board with a bme280 pressure, humidity and temperature sensor, a ds3232m realtime clock, and 4MB of flash memory. The clock wakes up an atmega328p, it takes readings and stores them, and then goes back to sleep. A low dropout, low quiescent current voltage regulator provides 3.3v power to the board from an external battery.  
This is a board with a bme280 pressure, humidity and temperature sensor, a ds3232m realtime clock, and 4MB of flash memory. The clock wakes up an atmega328p, it takes readings and stores them, and then goes back to sleep. A low dropout, low quiescent current voltage regulator provides 3.3v power to the board from an external battery.  


I built this to be buried inside a time capsule (though it has plenty of other uses), so it has to be able to survive freezing temperatures, and should last at least 5 years without maintenance. A quick calculation of current draw on my prototype says that it should be able to run for about 15 years (!) on AA batteries, and there is plenty of room in the flash memory for hourly measurements (15ish years worth).
I built this to be buried inside a time capsule (though it has plenty of other uses), so it has to be able to survive freezing temperatures, and should last at least 5 years without maintenance. A quick calculation of current draw on my prototype says that it should be able to run for about 15 years on AA batteries, and there is plenty of room in the flash memory for hourly measurements (15ish years worth).


==Operating Instructions==
Over 10 years, the board is calculated to use <pre>88000hr*((20mA+4)*(.5/3600)+.35mA*(57/3600)+.006mA) = 1309 mAh</pre>
 
==Unit Status==
===envilog2===
buried in 2018 time 5 year capsule (started/sealed WC 42,hourly), lithium batteries
===envilog1===
On deck in tupperware outside house, started Jan 2019 (hourly), lithium batteries
* Checked at July 2019 Winter Camp party, status ok.
* Checked Jan 26, 2020, status OK. Left inside for few days to dry after finding the tupperware cracked. Time was about 65 seconds behind EST.
* Checked May 20, 2020 - after a heavy rainstorm the past few weeks, I found the tupperware cracked and the unit submerged in about an inch of water. All batteries are dead, although I do not think water reacted quickly with the lithium as I see no melting of the plastic case. After a wash in acetone and brake cleaner, most of the corrosion was removed, and I was able to power up the unit and retrieve the data out the serial port. The water first shorted the trigger pin for the wakeup, before apparently draining the batteries and causing the unit to reboot several times. Interestingly, at these times the on-board humidity sensor recorded "100.00%"
* As of 2020-08-13, the unit is running on regular batteries indoors. The LEDs had stopped working after the board was submerged in water, but seems to have since dried out and started working again.
 
===envilog5===
At Jan trailer, started Jul 2019, hourly, lithium batteries
* checked 2020-08-05. All OK, clock was 28 seconds later than UTC
 
===envilog3===
buried in 2019 time 5 year capsule (started/sealed WC 43,hourly), alkaline batteries
 
==Files==
* [[File:Envilog-pcb-files.zip]] - The eagle and gerber files needed to make the boards
* [[File:Envilog-arduino-code.zip]] - The arduino program that runs on the board. Additional board hardware and libraries listed below are needed also.
 
==Parts List==
* BME280 board measuring temperature, humidity and pressure.
* DS3231M measuring time, and temperature
* Optional voltage divider to measure battery voltage
* MCP1703AT-3302E/MB - 3.3V voltage low dropout linear regulator
* ATMEGA328P-AU
* Winbond 25q32fvsig
 
==Interface Description==
[[File:Envilog-boardoutline.png|thumb|The board layout]]
The board contains 4 dip switches, which pretty much work independently, and one button.
The board contains 4 dip switches, which pretty much work independently, and one button.
The switches should be labeled 1-4, with 1 being closest to the center of the board. The off position of the switch has the handle toward the 3 indicator LEDs, and the on position is towards the button.  
The switches should be labeled 1-4, with 1 being closest to the center of the board. The off position of the switch has the handle toward the 3 indicator LEDs, and the on position is towards the button.  
Line 12: Line 45:
* Switch 3 (on) - Dumps the flash. Over serial, the board will output a tab-formatted table of the measurements that have been recorded. The dump will continue until either the entire chip has been read (including blank areas), or Switch 3 has been turned off. To start a dump, turn switch 3 on and then either wait for the RTC to wake up the system, or wake it up yourself with a single press of the button.
* Switch 3 (on) - Dumps the flash. Over serial, the board will output a tab-formatted table of the measurements that have been recorded. The dump will continue until either the entire chip has been read (including blank areas), or Switch 3 has been turned off. To start a dump, turn switch 3 on and then either wait for the RTC to wake up the system, or wake it up yourself with a single press of the button.


* Switch 4 (on) - Blinks a green light every time the 328 powers up. Turn off to save power
* Switch 4 (on) - Blinks a green light every time the 328 powers up. Turn off to save power.


The LED functions are, in general:
The LED functions are, in general:
Line 18: Line 51:
* Red - Working - Turns on when user input is acknowledged  
* Red - Working - Turns on when user input is acknowledged  
* Yellow - Waiting for user input
* Yellow - Waiting for user input
==Software Libraries used==
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
==Build / Operating Instructions==
* 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.


==Example Output==
==Example Output==
This is what it looks like when running / dumping measurements in the serial terminal.
This is what it looks like when running / dumping measurements in the serial terminal. To create a dump, move switch 3 to on position and press button once. Data is dumped out the TXD pin at 115200 baud.
<pre>TIME CAPSULE LONG DURATION ENVIROMENTAL LOGGER - Alan J. WIlson 2018
<pre>TIME CAPSULE LONG DURATION ENVIROMENTAL LOGGER - Alan J. WIlson 2018
Current time: 00/01/01 00:51:57
Current time: 18/09/05 23:29:49
Flash capacity: 4194304 bytes, 131072 frames
Flash capacity: 4194304 bytes, 131072 frames
Frame size: 32
Frame size: 32
Next ram index: 13159
Next ram index: 457


Current time: 00/01/01 00:52:02
Current time: 18/09/05 23:29:49
Cycle: 0
Cycle: 0
Index: 13159
Index: 457
Battery ADC: 0
Battery ADC: 0
DS3231 Temperature (C): 25.25
DS3231 Temperature (C): 22.75
BME280 Temperature (C): 25.29
BME280 Temperature (C): 22.70
BME280 Pressure  (Pa): 99076.30
BME280 Pressure  (Pa): 99898.25
BME280 Humidity    (%): 69.27
BME280 Humidity    (%): 51.34
Write OK
Write OK


FLASH MEMORY DATA DUMP FOLLOWS
FLASH MEMORY DATA DUMP FOLLOWS
Index Cycle Year Month Day Hour Minute Second DS3231 Temperature (C) Temperature (C) Pressure (Pa) Humidity (%) Battery (10-bit ADC)
Index Cycle Year Month Day Hour Minute Second DS3231 Temperature (C) Temperature (C) Pressure (Pa) Humidity (%) Battery (10-bit ADC)
0 0 18 8 26 18 13 12 28.00 25.93 98721.45 56.25 0
0 0 18 9 5 14 44 45 22.50 22.22 99527.77 45.77 0
1 1 18 8 26 18 14 10 27.25 26.69 98700.82 51.92 0
1 1 18 9 5 14 44 45 22.50 22.19 99525.35 46.32 0
2 2 18 8 26 18 15 10 26.25 26.62 98697.11 51.89 0
2 2 18 9 5 14 44 58 22.75 22.21 99520.82 46.35 0
3 3 18 8 26 18 16 10 26.00 26.08 98680.39 51.73 0
3 3 18 9 5 14 45 10 22.75 22.19 99530.60 46.18 0
4 4 18 8 26 18 17 10 25.50 25.72 98682.92 52.41 0
4 4 18 9 5 14 46 10 22.50 22.23 99526.82 46.55 0
5 5 18 8 26 18 18 10 25.25 25.43 98677.75 52.36 0
5 5 18 9 5 14 47 10 22.25 22.29 99525.55 46.44 0
6 6 18 8 26 18 19 10 25.00 25.13 98676.18 52.90 0 </pre>
6 6 18 9 5 14 48 10 22.25 22.02 99528.21 47.05 0
7 7 18 9 5 14 49 10 22.00 21.90 99535.94 47.95 0
8 8 18 9 5 14 50 10 22.00 21.79 99527.93 48.24 0
9 9 18 9 5 14 51 10 22.00 21.75 99536.94 48.41 0
10 10 18 9 5 14 52 10 22.00 21.74 99537.06 48.59 0
11 11 18 9 5 14 53 10 22.00 21.74 99530.03 48.66 0</pre>
 
==Serial Console (12/08/2018)==
In the original version of the software, I use the single button to do most of the setup. This can be very difficult, because the board and button are tiny, and pressing it is required many times, especially for setting the time. Since I implement a simple serial console tool into many of my other projects, I figured it would be a good idea to have one here too, since it is probably fairly likely that you will have the device hooked up to a computer when setting it up anyways.
 
The serial console I made accepts commands one line at a time, but there is a timeout so that the system does not get stuck waiting forever for a character that never comes. This makes it excellent for programs that send data one line at a time, like the Arduino IDE, but it will not work that well for standard dumb terminal unless you can type very quickly.
 
The console accepts commands in the form of a single letter, followed by a floating point number, and finally the newline character. For example:
<pre>y18.00\n</pre>
The letter gets passed along as the command, and the number gets passed along as the parameter. It doesn't have to stay floating point either, it will just get converted into an integer or whatever you need.
 
To use the serial console, set your terminal to 9600 baud and reset the board. Then enter '''e'''. I found that the baudrate of the board's normal 115200 is too high to reliably accept serial input, but works fine for outputing data at high speed during normal operation of the board.  
 
The following table documents all the commands and their functions:
{| class="wikitable"
|-
! Command !! Parameter !! Description !! Example
|-
| e || any || Enters the Serial control mode ||
|-
| t || 1 - start listing<br>0 - stop listing || Lists continuously the current time. This is helpful when setting it exactly to another source. || t1 - lists time
|-
| a || 1 - start listing<br>0 - stop listing || Lists continuously the flash data. This is much slower than using the switch #3 because it is only at 9600 baud. || a1
|-
| r || any || Displays the DS3232M RTC registers ||
|-
| y || 2 digit year || Sets the year of the RTC || y18 - sets to year 2018
|-
| m || 2 digit month || Sets the month of the RTC || m12 - sets to month December
|-
| d || 2 digit day || Sets the day of month of the RTC || d8 - sets to day 8
|-
| H || 2 digit hour || Sets the hour of the RTC || H32 - sets to hour 1PM
|-
| M || 2 digit minute || Sets the minute of the RTC || M32 - sets to minute 32
|-
| S || 2 digit second || Sets the seconds of the RTC || S0 - sets to second 0
|-
| F || value 12345 || Erases the flash memory || F12345
|}
 
==Octave Plotter==
If the output table is changed from tab formatting to CSV (you can do this with Notepad++ or some other text editor), you can use this script in GNU Octave (an open source MatLab alternative) to make a handy plot of the data.
 
<pre>
clear;
clc;
clf;
 
raw = load("j.csv");
 
%frame format:
%[ time, ds3231T, temp, pressure, humidity ]
 
i = 0;
while(i<length(raw(:,1)))
  i++;
  frame(i,:)=[datenum([2000+raw(i,3),raw(i,4),raw(i,5),raw(i,6),raw(i,7),raw(i,8)]),raw(i,9),raw(i,10),raw(i,11),raw(i,12)];
end
 
figure(1)
ha(1)=subplot(3,1,1);
hold on;
title(strcat("Enviroment data: ",datestr(frame(1,1)," mmm 'yy ")," to",datestr(frame(i,1)," mmm 'yy ")));
plot(frame(:,1),frame(:,2)*(9/5)+32);
plot(frame(:,1),frame(:,3)*(9/5)+32);
datetick("x", "mmm/yy");
grid on;
xlabel("Time");
ylabel("Temperature (F)");
 
ha(2)=subplot(3,1,2);
plot(frame(:,1),frame(:,4));
datetick("x", "mmm/yy");
grid on;
xlabel("Time");
ylabel("Pressure (Pa)");
 
ha(3)=subplot(3,1,3);
plot(frame(:,1),frame(:,5));
datetick("x", "mmm/yy");
grid on;
xlabel("Time");
ylabel("Humidity (%)");
 
linkaxes(ha, "x");
</pre>
 
==Details (hackaday.io)==
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.
 
===The Microcontroller===
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.
 
===The Clock===
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.
 
===The Memory===
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.
 
===Power===
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.
 
===Operator interface===
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.

Latest revision as of 08:00, 13 August 2020

Eagle.png

This is a board with a bme280 pressure, humidity and temperature sensor, a ds3232m realtime clock, and 4MB of flash memory. The clock wakes up an atmega328p, it takes readings and stores them, and then goes back to sleep. A low dropout, low quiescent current voltage regulator provides 3.3v power to the board from an external battery.

I built this to be buried inside a time capsule (though it has plenty of other uses), so it has to be able to survive freezing temperatures, and should last at least 5 years without maintenance. A quick calculation of current draw on my prototype says that it should be able to run for about 15 years on AA batteries, and there is plenty of room in the flash memory for hourly measurements (15ish years worth).

Over 10 years, the board is calculated to use

88000hr*((20mA+4)*(.5/3600)+.35mA*(57/3600)+.006mA) = 1309 mAh

Unit Status

envilog2

buried in 2018 time 5 year capsule (started/sealed WC 42,hourly), lithium batteries

envilog1

On deck in tupperware outside house, started Jan 2019 (hourly), lithium batteries

  • Checked at July 2019 Winter Camp party, status ok.
  • Checked Jan 26, 2020, status OK. Left inside for few days to dry after finding the tupperware cracked. Time was about 65 seconds behind EST.
  • Checked May 20, 2020 - after a heavy rainstorm the past few weeks, I found the tupperware cracked and the unit submerged in about an inch of water. All batteries are dead, although I do not think water reacted quickly with the lithium as I see no melting of the plastic case. After a wash in acetone and brake cleaner, most of the corrosion was removed, and I was able to power up the unit and retrieve the data out the serial port. The water first shorted the trigger pin for the wakeup, before apparently draining the batteries and causing the unit to reboot several times. Interestingly, at these times the on-board humidity sensor recorded "100.00%"
  • As of 2020-08-13, the unit is running on regular batteries indoors. The LEDs had stopped working after the board was submerged in water, but seems to have since dried out and started working again.

envilog5

At Jan trailer, started Jul 2019, hourly, lithium batteries

  • checked 2020-08-05. All OK, clock was 28 seconds later than UTC

envilog3

buried in 2019 time 5 year capsule (started/sealed WC 43,hourly), alkaline batteries

Files

Parts List

  • BME280 board measuring temperature, humidity and pressure.
  • DS3231M measuring time, and temperature
  • Optional voltage divider to measure battery voltage
  • MCP1703AT-3302E/MB - 3.3V voltage low dropout linear regulator
  • ATMEGA328P-AU
  • Winbond 25q32fvsig

Interface Description

The board layout

The board contains 4 dip switches, which pretty much work independently, and one button. The switches should be labeled 1-4, with 1 being closest to the center of the board. The off position of the switch has the handle toward the 3 indicator LEDs, and the on position is towards the button.

The functions of the switches are:

  • Switch 1 (on) - Enters the clock setting procedure. The clock is set using only the single button, pressed a number of times to set the date and time. You can only set the clock when the board is first connected to power or reset.
  • Switch 2 (on) - Erases the flash chip. The flash must be empty to write new data from the beginning. An extra button press is needed to confirm you really want to do this. If the clock set switch is also on, then you will set the clock first, then erase the flash. You can only erase the flash when the board is first connected to power or reset. This helps avoid doing it accidentally.
  • Switch 3 (on) - Dumps the flash. Over serial, the board will output a tab-formatted table of the measurements that have been recorded. The dump will continue until either the entire chip has been read (including blank areas), or Switch 3 has been turned off. To start a dump, turn switch 3 on and then either wait for the RTC to wake up the system, or wake it up yourself with a single press of the button.
  • Switch 4 (on) - Blinks a green light every time the 328 powers up. Turn off to save power.

The LED functions are, in general:

  • Green - Status - Blinks when something happens / has happened
  • Red - Working - Turns on when user input is acknowledged
  • Yellow - Waiting for user input

Software Libraries used

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

Build / Operating Instructions

  • 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.

Example Output

This is what it looks like when running / dumping measurements in the serial terminal. To create a dump, move switch 3 to on position and press button once. Data is dumped out the TXD pin at 115200 baud.

TIME CAPSULE LONG DURATION ENVIROMENTAL LOGGER - Alan J. WIlson 2018
Current time: 18/09/05 23:29:49
Flash capacity: 4194304 bytes, 131072 frames
Frame size: 32
Next ram index: 457

Current time: 18/09/05 23:29:49
Cycle: 0
Index: 457
Battery ADC: 0
DS3231 Temperature (C): 22.75
BME280 Temperature (C): 22.70
BME280 Pressure   (Pa): 99898.25
BME280 Humidity    (%): 51.34
Write OK

FLASH MEMORY DATA DUMP FOLLOWS
Index	Cycle	Year	Month	Day	Hour	Minute	Second	DS3231 Temperature (C)	Temperature (C)	Pressure (Pa)	Humidity (%)	Battery (10-bit ADC)
0	0	18	9	5	14	44	45	22.50	22.22	99527.77	45.77	0	
1	1	18	9	5	14	44	45	22.50	22.19	99525.35	46.32	0	
2	2	18	9	5	14	44	58	22.75	22.21	99520.82	46.35	0	
3	3	18	9	5	14	45	10	22.75	22.19	99530.60	46.18	0	
4	4	18	9	5	14	46	10	22.50	22.23	99526.82	46.55	0	
5	5	18	9	5	14	47	10	22.25	22.29	99525.55	46.44	0	
6	6	18	9	5	14	48	10	22.25	22.02	99528.21	47.05	0	
7	7	18	9	5	14	49	10	22.00	21.90	99535.94	47.95	0	
8	8	18	9	5	14	50	10	22.00	21.79	99527.93	48.24	0	
9	9	18	9	5	14	51	10	22.00	21.75	99536.94	48.41	0	
10	10	18	9	5	14	52	10	22.00	21.74	99537.06	48.59	0	
11	11	18	9	5	14	53	10	22.00	21.74	99530.03	48.66	0

Serial Console (12/08/2018)

In the original version of the software, I use the single button to do most of the setup. This can be very difficult, because the board and button are tiny, and pressing it is required many times, especially for setting the time. Since I implement a simple serial console tool into many of my other projects, I figured it would be a good idea to have one here too, since it is probably fairly likely that you will have the device hooked up to a computer when setting it up anyways.

The serial console I made accepts commands one line at a time, but there is a timeout so that the system does not get stuck waiting forever for a character that never comes. This makes it excellent for programs that send data one line at a time, like the Arduino IDE, but it will not work that well for standard dumb terminal unless you can type very quickly.

The console accepts commands in the form of a single letter, followed by a floating point number, and finally the newline character. For example:

y18.00\n

The letter gets passed along as the command, and the number gets passed along as the parameter. It doesn't have to stay floating point either, it will just get converted into an integer or whatever you need.

To use the serial console, set your terminal to 9600 baud and reset the board. Then enter e. I found that the baudrate of the board's normal 115200 is too high to reliably accept serial input, but works fine for outputing data at high speed during normal operation of the board.

The following table documents all the commands and their functions:

Command Parameter Description Example
e any Enters the Serial control mode
t 1 - start listing
0 - stop listing
Lists continuously the current time. This is helpful when setting it exactly to another source. t1 - lists time
a 1 - start listing
0 - stop listing
Lists continuously the flash data. This is much slower than using the switch #3 because it is only at 9600 baud. a1
r any Displays the DS3232M RTC registers
y 2 digit year Sets the year of the RTC y18 - sets to year 2018
m 2 digit month Sets the month of the RTC m12 - sets to month December
d 2 digit day Sets the day of month of the RTC d8 - sets to day 8
H 2 digit hour Sets the hour of the RTC H32 - sets to hour 1PM
M 2 digit minute Sets the minute of the RTC M32 - sets to minute 32
S 2 digit second Sets the seconds of the RTC S0 - sets to second 0
F value 12345 Erases the flash memory F12345

Octave Plotter

If the output table is changed from tab formatting to CSV (you can do this with Notepad++ or some other text editor), you can use this script in GNU Octave (an open source MatLab alternative) to make a handy plot of the data.

clear;
clc;
clf;

raw = load("j.csv");

%frame format:
%[ time, ds3231T, temp, pressure, humidity ]

i = 0;
while(i<length(raw(:,1)))
  i++;
  frame(i,:)=[datenum([2000+raw(i,3),raw(i,4),raw(i,5),raw(i,6),raw(i,7),raw(i,8)]),raw(i,9),raw(i,10),raw(i,11),raw(i,12)];
end

figure(1)
ha(1)=subplot(3,1,1);
hold on;
title(strcat("Enviroment data: ",datestr(frame(1,1)," mmm 'yy ")," to",datestr(frame(i,1)," mmm 'yy ")));
plot(frame(:,1),frame(:,2)*(9/5)+32);
plot(frame(:,1),frame(:,3)*(9/5)+32);
datetick("x", "mmm/yy");
grid on;
xlabel("Time");
ylabel("Temperature (F)");

ha(2)=subplot(3,1,2);
plot(frame(:,1),frame(:,4));
datetick("x", "mmm/yy");
grid on;
xlabel("Time");
ylabel("Pressure (Pa)");

ha(3)=subplot(3,1,3);
plot(frame(:,1),frame(:,5));
datetick("x", "mmm/yy");
grid on;
xlabel("Time");
ylabel("Humidity (%)");

linkaxes(ha, "x");

Details (hackaday.io)

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.

The Microcontroller

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.

The Clock

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.

The Memory

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.

Power

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.

Operator interface

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.