2013 1 arduino_datalogger
DESCRIPTION
This is my slide show for the 2013.1 Desert Code Camp Code should be posted to Github soonTRANSCRIPT
DESERT CODE CAMP 2013.1Datalogging on an Arduino
Presented by Don DoerresEmbedded Pro [email protected]
TODAY’S TAKEAWAYS
The Arduino is a good starting point for a data logger, a device used to obtain and store data over a long period of time
The Arduino with a few add-ins is capable of Storing data with time tags Displaying data in real time Doing these tasks without tying up a
bigger computer
IDEA WAS TO LOG WEATHER
I started with a barometer (BMP085) and a humidity sensor (DHT11)
Both of these also provide temperature information
Power came from a desktop computer through USB cable to Arduino, Arduino to breadboard
FIRST BREADBOARD
SERIOUS WEATHER…
WEATHER WATCHING…
Observing an approaching dust storm, I realized that I didn’t want to leave the computer or sensors outside
Barometric pressure turned out to be adequate for storm tracking
Indoors, humidity did not change much So, I decided to record barometric
pressure and temperature
ORIGINALLY USED PC
Used Tera Term (Terminal Emulator) to log data
Tera Term added time stamp from PC clock
Once prototype was working, wanted to move time keeping function and data logging to Arduino and not tie up PC
ARDUINO TIMING SIX MINUTES, WRITING TO SERIAL PORT
Tera Term Screen
Tera Term Log File—Adds Time Stamp
ORIGINAL PLAN: CHRONODOT & SD BREAKOUT
Chronodot is a highly accurate clock with battery backup
SD Breakout allows simple connection to SD card
However, the combination would simply not fit on an Arduino breakout shield, let alone any sensors
DOT AND SD ON ARDUINO BREADBOARD
This picture shows the Dot and the SD card breakout
This works as a breadboard, but is too big for a shield
Dot
SD breakout
ADAFRUIT INTRODUCED A DATA LOGGER SHIELD
About the time I realized that my logger would not fit on a prototype shield, Adafruit introduced their new logger shield
This had a slightly lower accuracy clock than the Dot, but it had everything else in surface mount parts
All I had to do was add the pressure sensor and a connection to a 16X2 LCD display
ADAFRUIT LOGGER SHIELD
Adafruit logger shield Surface mount parts left prototype area quite
large enough for sensors Add an I2C 16X2 LCD display
SD HolderDS1307 RTC
Battery Holder
SENSOR SELECTION
This is the BMP085 pressure sensor This is a sensitive barometer/altimeter
and temperature sensor It runs on 5V It has an I2C interface
I2C BUS
This is a very simple serial Inter-Integrated Circuit connection bus, hence I2C
The interface consists of Clock, Data, and ground
Multiple devices can be hooked to the same bus as long as they have different addresses
The devices I used, pressure sensor (address 0x77) and display (address 0), do have different addresses
BMP085 CONNECTION TO ARDUINO
16X2 LCD DISPLAY WITH I2C BACKPACK This is a back view showing the four
wire connections—same connections as BMP085
DAT to A4CLK to A5
5V To 5V
GND To GND
OTHER CONNECTIONS
The SD breakout and the Clock are already wired up on the shield
The pressure sensor I soldered to the I2C connection pads on the shield
The LCD display I simply plugged in to the shield
The BMP and the LCD display have different I2C addresses, so there is no conflict
TYPICAL DISPLAY
Date (Year not shown), local time Temperature in F, Pressure in mmHG Display updates every 5 seconds Data is stored to SD card every 6
minutes
WHAT GOES ON THE SD CARD
The log is Comma Separated Values (CSV) of Time, Temperature, Pressure
Time is stored as a ‘C’ time stamp (more about this in two slides)
Temperature is degrees F Pressure is in millimeters of Mercury
(mmHg)
SAMPLE OF LOG FILE1363516494,79.0,691.01363516868,79.0,691.01363517243,79.0,691.01363517617,79.1,691.11363517991,79.1,691.11363518365,79.1,691.11363518740,79.1,691.11363519114,79.2,691.21363519488,79.2,691.21363519862,79.2,691.21363520237,79.2,691.21363520611,79.1,691.11363520985,79.2,691.21363521359,79.1,691.11363521734,79.1,691.11363522108,79.2,691.21363522482,79.2,691.21363522857,79.2,691.21363523231,79.2,691.21363523605,79.2,691.21363523979,79.2,691.21363524354,79.2,691.21363524728,79.1,691.11363525102,79.1,691.11363525476,79.1,691.1
THE CTIME STAMP
The C language uses as a time stamp the number of seconds since January 1, 1970
A 32 bit signed integer allows counting seconds until January 19, 2038 at 03:14:07 GMT
…by then, we will likely switch to 64 bit integers
And, yes, the value is a signed integer so that comparisons can be readily made
DISPLAYING IN EXCEL OR OTHER SPREADSHEET
It is simple to convert ctime to Excel time
The macro is, using ‘A2’ as a sample cell:
Display format is controlled with Excel
formattingCTIME Increase Delta Day Date Time Deg F mmHg
1363504243 0 0 Sun Mar 17, 2013 07:10:43 74.2 691.21363506389 2146 2146 Sun Mar 17, 2013 07:46:29 75.4 691.41363506764 2521 375 Sun Mar 17, 2013 07:52:44 76.7 691.71363507138 2895 374 Sun Mar 17, 2013 07:58:58 77.5 691.51363507512 3269 374 Sun Mar 17, 2013 08:05:12 77.4 691.41363507886 3643 374 Sun Mar 17, 2013 08:11:26 77.3 691.31363508261 4018 375 Sun Mar 17, 2013 08:17:41 77.3 691.3
=DATE(1970,1,1)+(A2)/86400
LIBRARIES
UNITS
The units of the BMP085 pressure sensor are Degrees C and pressure in Pascals
Conversions are in order
tempy = bmp.readTemperature();tempy = (tempy * 9.0 / 5.0) + 32.0;
press = bmp.readPressure();fpress = (float)press* 0.007500616827042;
TIMESET.INO, 1 OF 2
// timeSet.ino
#include <Wire.h>#include <RTClib.h>#include <LiquidCrystal.h>
LiquidCrystal lcd(0);RTC_DS1307 RTC;DateTime now;
void setup(){Serial.begin(57600);Wire.begin();RTC.begin();RTC.adjust(DateTime(__DATE__, __TIME__)); lcd.begin(16, 2);lcd.setBacklight(HIGH); //HIGH is ON, LOW is OFF}
TIMESET.INO, 2 OF 2
void loop(){ now = RTC.now(); lcd.setCursor(0, 0); lcd.print(now.year(), DEC); lcd.print('/'); if(now.month() < 10) lcd.print("0"); lcd.print(now.month(), DEC); lcd.print('/'); if(now.day() < 10) lcd.print("0"); lcd.print(now.day(), DEC); lcd.setCursor(0, 1); if(now.hour() < 10) lcd.print("0"); lcd.print(now.hour(), DEC); lcd.print(':'); if(now.minute() < 10) lcd.print("0"); lcd.print(now.minute(), DEC); lcd.print(':'); if(now.second() < 10) lcd.print("0"); lcd.print(now.second(), DEC); delay(2000);}
AUGUST 11, 2012 STORM IN PHOENIX About 10 hours of plot
0 100 200 300 400 500 600717.80
718.00
718.20
718.40
718.60
718.80
719.00
719.20
719.40
719.60
BMP_mmHg
0 200 400 600 800 1000 1200 1400 1600 1800688
690
692
694
696
698
700
702
704
706
39 HOTEL FLOORS AT LAS VEGAS FOUR SEASONS
Stepped up the logging rate to once per second
Three round trips
FUTURE WORK
Add time setting over serial while running
Seems to be a small temperature rise of about 2 degrees F with the display running
Add fancier display, perhaps a 1 hour plot of data on a dot matrix display
DCC_DATALOGGER_3.INO 1 OF 9// DCC_DataLogger.ino#include <Wire.h>#include <RTClib.h>#include <Adafruit_BMP085.h>#include <LiquidCrystal.h>#include <SD.h>
// On display, connect via i2c, default address #0 (A0-A2 not jumpered)LiquidCrystal lcd(0);
RTC_DS1307 RTC;Adafruit_BMP085 bmp;const int chipSelect = 10;
File dataFile;
unsigned long int press; // press is a longfloat tempy; // temperature is a floatfloat fpress;int loopSec = 0;int loopMin = 0;int num;// make a string for assembling the data to log:String dataString = "";
DateTime now;
DCC_DATALOGGER_3.INO 2 OF 9void setup(){Serial.begin(57600);Wire.begin();RTC.begin();bmp.begin();
// set up the LCD's number of rows and columns:lcd.begin(16, 2);lcd.setBacklight(HIGH); //HIGH is ON, LOW is OFF
if (! RTC.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled RTC.adjust(DateTime(__DATE__, __TIME__)); }Serial.print("Initializing SD card..."); // make sure that the default chip select pin is set to // output, even if you don't use it:pinMode(SS, OUTPUT);
DCC_DATALOGGER_3.INO 3 OF 9// see if the card is present and can be initialized:if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); // don't do anything more: while (1) ; }Serial.println("card initialized.");
// Open up the file we're going to log to! // This is an APPEND opendataFile = SD.open("datalog.txt", FILE_WRITE);if (! dataFile) { Serial.println("error opening datalog.txt"); // Wait forever since we can't write data while (1) ; }}
DCC_DATALOGGER_3.INO 4 OF 9void loop(){static int i;
if ( (loopSec % 5) == 0) { //Serial.println(__DATE__, __TIME__); tempy = bmp.readTemperature(); tempy = (tempy * 9.0 / 5.0) + 32.0; press = bmp.readPressure(); fpress = (float)press* 0.007500616827042;
now = RTC.now();
Serial.print(now.year(), DEC); Serial.print('/'); if(now.month() < 10) Serial.print("0"); Serial.print(now.month(), DEC); Serial.print('/'); if(now.day() < 10) Serial.print("0"); Serial.print(now.day(), DEC); Serial.print(' ');
DCC_DATALOGGER_3.INO 5 OF 9if(now.hour() < 10) Serial.print("0"); Serial.print(now.hour(), DEC); Serial.print(':'); if(now.minute() < 10) Serial.print("0"); Serial.print(now.minute(), DEC); Serial.print(':'); if(now.second() < 10) Serial.print("0"); Serial.print(now.second(), DEC); Serial.println();
Serial.print("C time is = "); Serial.println(now.unixtime());
lcd.setCursor(0, 0); // lcd.print(now.year(), DEC); // lcd.print('/'); if(now.month() < 10) lcd.print("0"); lcd.print(now.month(), DEC); lcd.print('/'); if(now.day() < 10) lcd.print("0"); lcd.print(now.day(), DEC); lcd.print(" ");
DCC_DATALOGGER_3.INO 6 OF 9 if(now.hour() < 10) lcd.print("0"); lcd.print(now.hour(), DEC); lcd.print(':'); if(now.minute() < 10) lcd.print("0"); lcd.print(now.minute(), DEC); lcd.print(':'); if(now.second() < 10) lcd.print("0"); lcd.print(now.second(), DEC);
lcd.setCursor(0, 1); lcd.print(tempy,1); lcd.print("F");
lcd.print(" "); lcd.print(fpress,1); lcd.print("mmHg");
Serial.print(tempy,1); Serial.print(" Deg F, "); Serial.print(fpress,1); Serial.println(" mmHg\n"); }
DCC_DATALOGGER_3.INO 7 OF 9delay(1000);loopSec+=1;
if(loopSec == 360) // 6 minutes { static bool lcdStatus = true; // LCD light on or off loopSec = 0;
lcd.clear(); lcd.setCursor(0, 0); lcd.print("Writing SD...");
dataString = String(now.unixtime()); dataString += ","; num = tempy; dataString += String(num); dataString += "."; tempy-=num; tempy+=0.05; tempy*=10.0; num=tempy; dataString+=String(num); dataString += ","; num = fpress; dataString += String(num);
DCC_DATALOGGER_3.INO 8 OF 9dataString += "."; fpress-=num; fpress+=0.05; fpress*=10.0; num = tempy; dataString +=String(num);
dataFile.println(dataString);
// The following line will 'save' the file to the SD card after every // line of data - this will use more power and slow down how much data // you can read but it's safer! // If you want to speed up the system, remove the call to flush() and it // will save the file only every 512 bytes - every time a sector on the // SD card is filled with data. dataFile.flush(); delay(1000); lcd.clear();
// To check out if display LED was causing warming, // cycle it off/on every six minutes // #define LEDONOFF #ifdef LEDONOFF lcdStatus = !lcdStatus;
DCC_DATALOGGER_3.INO 9 OF 9if(lcdStatus) { lcd.setBacklight(HIGH); //HIGH is ON, LOW is OFF } else { lcd.setBacklight(LOW); //HIGH is ON, LOW is OFF } #endif }}
DOWNLOADS 1
Grateful to Lady Ada!!!! Adafruit SD library:https://github.com/adafruit/SD Adafruit RTC library:https://github.com/adafruit/RTClib Adafruit logging shield tutorial:http://learn.adafruit.com/adafruit-data-logger-shield
DOWNLOADS 2
LCD i2c backpack tutorial http://learn.adafruit.com/i2c-spi-lcd-bac
kpack Liquid Crystal control library https://github.com/adafruit/LiquidCryst
al
QUESTIONS?
Find more slides from Don atwww.slideshare.net/dondoerres