I am making a temperature logger using 6 ds18b20 onewire sensors (using the DallasTemperature library), an Arduino R2, and an adafruit SD data logging shield with an adafruit 2 line color display. I am using the RTC on the data logging shield (Thanks Adafruit_Admin for helping me solve my soldering problem).
I am trying to get the time and each probe reading onto a single line in the CSV file for each time the sensors are queried.
The RTC works, and I can display the sensor data on the LCD, but I am having trouble saving the data to the SD card.
The code is borrowed from multiple sources including the adafruit data logging shield tutorial: sorry for not including all sources in the code. I am not using the same sensors as the Adafruit data logging shield - I will have the arduino hooked up to 6 ds18b20 sensors in parasite mode all attached to the same wires. While I am building the code I have 2 ds18b20 sensors on a breadboard to show the code is working: Protoboard1Dot and Protoboard2Dot, the other sensors are not connected. Note: some of the comments describe functions I want to, but have not yet, built into the sketch.
Code: Select all
//SETUP
//Echo to Serial port initially used for debugging during initial programming, turn off when no longer needed
//Start the RTC
//Declare pins for LCD, SD shield, red yellow and green LED
//Declare deviceaddress for each ds18b20 probe (each is unique)
//Set resolution on sensors
//Confirm sensors are not giving erroneous readings *echo to serial
//Initialize SD card and confirm it is functioning *echo to serial
//Create new file with suffix ## (start at 0, increment up until no such file exists on card) *echo to serial
//Print header information to SD card in CSV format for spreadsheet use *echo to serial
//Set SD Logging interval
//Set data writing interval (every read vs every 10th read)
// http://arduinotronics.blogspot.com/2010/12/two-ds18b20-temp-sensors-on-lcd-display.html
// This Arduino sketch reads DS18B20 "1-Wire" digital
// temperature sensors.
// Tutorial:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-tutorial.html
// https://learn.adafruit.com/adafruit-data-logger-shield/using-the-real-time-clock
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <OneWire.h> // DS18B20 temp sensors use this protocol
#include <DallasTemperature.h> // tranlates DS18b20 readings into temperatures
#include <LiquidCrystal.h> // for the LCD
#include <Wire.h> // for I2C device communciation in this case RTC
#include "RTClib.h" // for RTC
#include <SD.h> // SD card library
#include <SPI.h> // Serial Periheral Interface library
// LCD Connections: AdaFruit LCD tutorial
// rs display data or command (LCD pin 4) to Arduino pin 12 - reassign to Ard pin 14 due to SD card
// rw write or read (LCD pin 5) to ground
// en enable tells LSCD ready for writing (LCD pin 6) to Arduino pin 10 - reassign to Ard pin 2 due to SD card
// LCD data pins d4, d5, d6, d7 to Arduino pins 9, 10, 11, 12 - reassign to Ard pins 4, 7, 8, 9
// LCD color pins need to go to a pwm Ard pin
// LCD pin 16 red to Ard pin 3 (pwm)
// LCD pin 17 green to Ard pin 5 (pwn)
// LCD pin 18 blue to Ard pin 6 (pwm)
//Adafruit SD datalogger
// communications between arduino uno and SD uses SPI, which uses digital pins 11 (MISO), 12(MOSI), 13 (SCK)
// SPI requires SS (slave select) to enable and disable specific devices
// digitalPin pin 10 is default
// always set this pin to OUTPUT or SPI interface will be put into slave mode and library will not work
// any pin can be SS for device - specify in the call to SD.begin()
LiquidCrystal lcd (14, 2, 4, 7, 8, 9); // (rs,en,db4,db5,db6,db7)
int backLight = 16; // pin 16 will control the backlight (red)
// Data wire is plugged into pin 3 on the Arduino - reassigned to 3
#define ONE_WIRE_BUS 3
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html
// PROBE 1 - ONE PINK DOT 0x28, 0x39, 0x77, 0xF6, 0x05, 0x00, 0x00, 0x14
// PROBE 2 - TWO PINK DOTS 0x28, 0x80, 0x81, 0xF7, 0x05, 0x00, 0x00, 0x30
// PROBE 3 - ONE GREEN DOT 0x28, 0x09, 0x4B, 0xF7, 0x05, 0x00, 0x00, 0xD3
// PROBE 4 - TWO GREEN DOTS 0x28, 0xAC, 0x68, 0xF7, 0x05, 0x00, 0x00, 0xD2
// PROBE 5 - ONE PURPLE DOT 0x28, 0x4E, 0x73, 0xF7, 0x05, 0x00, 0x00, 0x99
// PROBE 6 - TWO PURPLE DOTS 0x28, 0x0B, 0x07, 0xF7, 0x05, 0x00, 0x00, 0x75
// PROBE 7 - ONE BLUE DOT ON PROTO BOARD - 0x28, 0x1B, 0x58, 0xF7, 0x05, 0x00, 0x00, 0xD4
// PROBE 8 - TWO BLUE DOTS ON PROTO BOARD - 0x28, 0xA3, 0x3A, 0xF6, 0x05, 0x00, 0x00, 0x6F
// The brass plate on the Obsession defines Front of mirror box, which is
// furthest from the ground when the UTA is tipped toward the ground
// Mirror fans are boundary layer fans located on back of Mirror Box
DeviceAddress OutsideTemp = { 0x28, 0x4E, 0x73, 0xF7, 0x05, 0x00, 0x00, 0x99 };
DeviceAddress Mirror1Oclock = { 0x28, 0x39, 0x77, 0xF6, 0x05, 0x00, 0x00, 0x14 };
DeviceAddress Mirror7Oclock = { 0x28, 0x09, 0x4B, 0xF7, 0x05, 0x00, 0x00, 0xD3 };
DeviceAddress BehindMirrorFanLeft = { 0x28, 0xAC, 0x68, 0xF7, 0x05, 0x00, 0x00, 0xD2 };
DeviceAddress MirrorBoxBack = { 0x28, 0x0B, 0x07, 0xF7, 0x05, 0x00, 0x00, 0x75 };
DeviceAddress MirrorBoxFront = { 0x28, 0x39, 0x77, 0xF6, 0x05, 0x00, 0x00, 0x14 };
DeviceAddress Protoboard1Dot = { 0x28, 0x1B, 0x58, 0xF7, 0x05, 0x00, 0x00, 0xD4 };
DeviceAddress Protoboard2Dot = { 0x28, 0xA3, 0x3A, 0xF6, 0x05, 0x00, 0x00, 0x6F };
DeviceAddress insideThermometer = { 0x28, 0x1B, 0x58, 0xF7, 0x05, 0x00, 0x00, 0xD4 };
DeviceAddress outsideThermometer = { 0x28, 0xA3, 0x3A, 0xF6, 0x05, 0x00, 0x00, 0x6F };
RTC_DS1307 rtc;
const int sdCardPin = 10; // ss is pin 10 on Arduino
// the logging file
File logfile;
void setup () {
Serial.begin(57600);
// initialize the SD card
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(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(sdCardPin)) {
Serial.print("SD card failed, or not present");
} else
Serial.println("SD card initialized.");
Serial.println("\n\r");
// create a new file
char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
Serial.print("couldnt create file");
}
Serial.print("Logging to: ");
Serial.println(filename);
// write a new header on the file then close it
logfile = SD.open(filename, FILE_WRITE);
String header = "DateTime, OutsideTemp, Mirror1Oclock, Mirror7Oclock, BehindMirrorFanLeft, MirrorBoxBack, MirrorBoxFront, Protoboard1Dot, Protoboard2Dot";
logfile.println(header);
logfile.flush();
logfile.close();
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
rtc.begin();
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(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
// Start up the library
sensors.begin();
// set the resolution to 10 bit (good enough?)
sensors.setResolution(OutsideTemp, 10);
sensors.setResolution(Mirror1Oclock, 10);
sensors.setResolution(Mirror7Oclock, 10);
sensors.setResolution(BehindMirrorFanLeft, 10);
sensors.setResolution(MirrorBoxBack, 10);
sensors.setResolution(MirrorBoxFront, 10);
sensors.setResolution(Protoboard1Dot, 10);
sensors.setResolution(Protoboard2Dot, 10);
pinMode(backLight, OUTPUT);
digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.begin(16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc.
lcd.clear(); // start with a blank screen
}
void printTemperature(DeviceAddress deviceAddress) // Check for temp probe error
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
lcd.print("Error");
} else {
lcd.print(tempC);
lcd.print("/");
lcd.print(DallasTemperature::toFahrenheit(tempC));
}
}
//LOOP
//Fetch the time *echo to serial
//Request temperatures from sensors *echo to serial
//Begin display sensor temperatures sequentially on 16x2 backlit LCD
//First display
//Top row outside temp
//Bottom row individual sensor
//Next display after 2 sec
//Delta between outside and average mirror temperature
//If delta is <=2 degrees C set LCD display red
//If delta is >2 but <=4 degrees C set LCD isplay green
//If delta is >4 degrees C set LCD display blue
//2 seconds between sequential LDC sensor reading display
//If RTC time indictates time to log data, log data
//If RTC time indicated time to write data, write data
//Go back to first display and index to next individual sensor
//Loop repeats
void loop () {
//fetch the time
DateTime now = rtc.now();
//show the time on serial
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(' ');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.print(" since midnight 1/1/1970 = ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");
Serial.println();
// log time on file on the SD card
logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(" ");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
logfile.print('"');
logfile.print("\n");
logfile.flush();
sensors.requestTemperatures();
//String PB1[]= printTemperature(Protoboard1Dot);
//write temperature to the SD card
//logfile.print(PB1);
//logfile.print("/n");
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir: ");
printTemperature(Protoboard2Dot);
delay(2000);
sensors.requestTemperatures();
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("MR1: ");
printTemperature(Mirror1Oclock);
delay(2000);
sensors.requestTemperatures();
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("MR7: ");
printTemperature(Mirror7Oclock);
delay(2000);
sensors.requestTemperatures();
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Fan: ");
printTemperature(BehindMirrorFanLeft);
delay(2000);
sensors.requestTemperatures();
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("BxB: ");
printTemperature(MirrorBoxBack);
delay(2000);
sensors.requestTemperatures();
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("BxF: ");
printTemperature(MirrorBoxFront);
// calculate a date which is 7 days and 30 seconds into the future
//DateTime future (now.unixtime() + 7 * 86400L + 30);
delay(3000);
}
but nothing is making it onto the SD card, the file is empty when I open it, including the header which is printed separately.Initializing SD card...SD card initialized.
Logging to: LOGGER03.CSV
2015/3/25 20:24:59
since midnight 1/1/1970 = 1427315099s = 16519d
2015/3/25 20:25:13
since midnight 1/1/1970 = 1427315113s = 16519d
2015/3/25 20:25:27
since midnight 1/1/1970 = 1427315127s = 16519d
Questions:
1. What do I need to write in the code for the time to be written to the SD card? logfile.print(now.year(), DEC); and similar don't seem to be making it onto the card.
2. How can I write data that is returned from the dallas temperature library to the SD card? If I just try to logfile.print(Protoboard1dot) I get the following error:
3. Am I going to run out of memory on the Arduino for this project with my sloppy coding, and will I need to get a Mega or something similar? I am currently at 26,056 bytes of 32,256 bytes maximum.This report would have more information with
"Show verbose output during compilation"
enabled in File > Preferences.
Arduino: 1.0.6 (Windows 7), Board: "Arduino Uno"
LCD_temp_logger_1.5_2015_03_09.ino: In function 'void loop()':
LCD_temp_logger_1.5_2015_03_09.ino:244: error: call of overloaded 'print(uint8_t [8])' is ambiguous
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:59: note: candidates are: size_t Print::print(const String&) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:60: note: size_t Print::print(const char*) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:61: note: size_t Print::print(char) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:62: note: size_t Print::print(unsigned char, int) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:63: note: size_t Print::print(int, int) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:64: note: size_t Print::print(unsigned int, int) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:65: note: size_t Print::print(long int, int) <near match>
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:66: note: size_t Print::print(long unsigned int, int) <near match>
I am trying to get the time and each probe reading onto a single line in the CSV file for each time the sensors are queried.
Thanks!
Greg