Table of Contents
In this post, we will build a temperature logger. This can than be deployed to monitor the temperature of a room or the environment. We will read the temperature every 15 minutes and store it in SD card.
This post builds upon three topics discussed earlier:
Make sure to check out these posts. You will get a better understanding about the different modules used in this project.
Block Diagram and Approach:
Our approach to this project is very simple. Let me describe the steps:
- Read the time from the RTC. If the minutes is a multiple of 15, go to step 2. Else, do nothing
- Read the temperature from the temperature sensor
- Store the time and the temperature in the SD card
Essentially, what we are doing is that we will store the temperature once every 15 minutes, i.e., every time the minutes read 00, 15, 30 or 45.
Temperature Logger Circuit Connections:
Temperature Logger Code:
#include <SPI.h> #include <SD.h> #include "Wire.h" #define DS3231_I2C_ADDRESS 0x68 File dataFile; byte stored=0; void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial); // wait for serial port to connect. Needed for native USB port only Serial.print("Initializing SD card..."); if (!SD.begin(10)) { Serial.println("initialization failed!"); while (1); } Serial.println("initialization done."); // open the file. note that only one file can be open at a time, // so you have to close this one before opening another. Wire.begin(); } // Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return( (val/10*16) + (val%10) ); } // Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return( (val/16*10) + (val%16) ); } void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) { // sets time and date data to DS3231 Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set next input to start at the seconds register Wire.write(decToBcd(second)); // set seconds Wire.write(decToBcd(minute)); // set minutes Wire.write(decToBcd(hour)); // set hours Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday) Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31) Wire.write(decToBcd(month)); // set month Wire.write(decToBcd(year)); // set year (0 to 99) Wire.endTransmission(); } void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes of data from DS3231 starting from register 00h *second = bcdToDec(Wire.read() & 0x7f); *minute = bcdToDec(Wire.read()); *hour = bcdToDec(Wire.read() & 0x3f); *dayOfWeek = bcdToDec(Wire.read()); *dayOfMonth = bcdToDec(Wire.read()); *month = bcdToDec(Wire.read()); *year = bcdToDec(Wire.read()); } void loop() { byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // retrieve data from DS3231 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // Store temperature only once every 15 minutes if(minute%15==0 && stored==0) { Serial.print("Writing to data.txt..."); dataFile = SD.open("data.txt", FILE_WRITE); if (dataFile) { dataFile.print(hour, DEC); // convert the byte variable to a decimal number when displayed dataFile.print(":"); if (minute<10) { dataFile.print("0"); } dataFile.print(minute, DEC); dataFile.print(":"); if (second<10) { dataFile.print("0"); } dataFile.print(second, DEC); dataFile.print(" "); dataFile.print(dayOfMonth, DEC); dataFile.print("/"); dataFile.print(month, DEC); dataFile.print("/"); dataFile.print(year, DEC); dataFile.print(" - "); dataFile.println(readTemperature()); Serial.println(readTemperature()); dataFile.close(); Serial.println("done."); stored=1; } else { // if the file didn't open, print an error: Serial.println("error opening data.txt"); } } else if(minute%15 != 0) { stored=0; } else{} delay(50000); // every 50 second } //Function to read the temperature float readTemperature() { float ADCValue; float tempVoltage = 0; float temp = 0; ADCValue = analogRead(A0); tempVoltage = (float)((5.0/1023)*ADCValue)*1000.0; //sensor output in milli volts temp = (float)tempVoltage/10.0; //temperature in Celcius return temp; }
Output:
After letting the code run for a few hours, you will get a file in the SD card with data that looks like this.
Improvements:
One of the drawbacks we have in this system is that the code is always running. Even though we are not doing anything for almost 15 minutes. Once every 15 minutes we log the temperature and then go back to doing nothing.
A major improvement that can be done is to make the Arduino go to sleep after it has recorded the temperature. That way, the power consumption will be significantly reduced. Once every 15 minutes, read and store the temperature and go back to sleep.
Hi, I’m Vivek, a Senior Embedded Innovation Specialist. I have been working on Embedded Systems and IoT for the past 11 years. I love to share my knowledge and train those who are interested. Nerdyelectronics.com was started out of this interest. You can read my full profile in this link.