RTC and Dallastemperature save to SD coding help

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

Disclaimer: I am new to Arduino and C, and do not have a background in programming beyond the BASIC I learned back in high school, and so am operating at a very low level.

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);
}
The serial monitor is showing the SD card initializes, and the RTC is showing the current time:
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
but nothing is making it onto the SD card, the file is empty when I open it, including the header which is printed separately.

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

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
Attachments
Arduino temp logger.JPG
Arduino temp logger.JPG (312.22 KiB) Viewed 1459 times

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

Well, you're closing the file after you write the header, so that's why you can't write anything else to it. Of course, that doesn't explain why the header isn't showing up. Get rid of the close and see if things improve.

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

D'oh! You are correct about the file being closed. I had thought to close the file after writing the header, then reopen it to write the RTC and temperature data, but I had trouble getting the sketch to reopen the file.

Here's the current output:
2015/3/26 10:17:50"
2015/3/26 10:18:4"
2015/3/26 10:18:19"
2015/3/26 10:18:33"
2015/3/26 10:18:47"
2015/3/26 10:19:2"
Which is great. Not sure why the header is missing, there is a blank line about the RTC data in the CSV file.

I need some help in code to write the dallastemperature readings to the SD card. As in my prior post, I get an error when I try to write it directly. I have come across two sketches which log ds18b20 readings to an SD card, but I cannot quite understand how to make their method match my sketch. I think I need to change the reading to some type of string, but I am frankly in over my head.

The first is from https://www.youtube.com/watch?v=gPGU_gb9f5I (no this is not a Rick Astley video) which does not use the RTC

Code: Select all

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SD.h>
#include <string.h>
#include <LiquidCrystal.h>
int counterTemp = 0;
float dataInt;
char test[20];

const int chipSelect = 4; 
#define ONE_WIRE_BUS 7
String dataString; 

OneWire oneWire(ONE_WIRE_BUS);
File myFile; 
DallasTemperature sensors(&oneWire);

int backLight = 14;   
LiquidCrystal lcd(15, 16, 17, 5, 4, 3, 2);
void setup(void)
{
   pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH); 

 lcd.begin(16, 2);
  dataString.reserve(4);
  pinMode(10, OUTPUT);

  Serial.begin(57600);
  Serial.println("card initialized.");

  sensors.begin();
  Serial.print(sensors.getDeviceCount(), DEC);
   // SET UP SD CARD FOR WRITING
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  } else {
    Serial.println("SD card initialized");
    myFile = SD.open("temper1.txt", FILE_WRITE);    // open file for writing
    if (myFile) {  // if file can be opened, write to it
      Serial.print("temper1.txt file opened for writing");
      myFile.close();
    } else {  // if not, show an error
      Serial.println("ERROR: not able to open temperature.txt");
    }
  }
 
  
 
  
}
 
 
void loop(void)
{
  lcd.setCursor(0, 0); 
  sensors.requestTemperatures(); // Send the command to get temperatures


  lcd.print(sensors.getTempCByIndex(0));  
   dataString = "";
   dataInt = 0;
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
 // Serial.print(" Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
//  Serial.println("DONE");

 Serial.print("Temperature for Device 1 is: ");
 if(sensors.getTempCByIndex(0) < 0){
 dataInt = 0;
 }
  else{
    dataInt = sensors.getTempCByIndex(0);
  }

  Serial.print(floatToString(test, dataInt, 1, 5)); 
 
 delay(1000);   
 writeDataToCard(counterTemp, dataInt);
  
  delay(59000);
  counterTemp++;
}

void writeDataToCard(int time, float dataInt) {
  myFile = SD.open("temper.txt", FILE_WRITE);
  myFile.print(time);
  myFile.print(", ");
  myFile.print(floatToString(test, dataInt, 1, 5));
  myFile.print("\n");
  myFile.close();
}




char * floatToString(char * outstr, double val, byte precision, byte widthp){
  char temp[16];
  byte i;

  // compute the rounding factor and fractional multiplier
  double roundingFactor = 0.5;
  unsigned long mult = 1;
  for (i = 0; i < precision; i++)
  {
    roundingFactor /= 10.0;
    mult *= 10;
  }
  
  temp[0]='\0';
  outstr[0]='\0';

  if(val < 0.0){
    strcpy(outstr,"-\0");
    val = -val;
  }

  val += roundingFactor;

  strcat(outstr, itoa(int(val),temp,10));  //prints the int part
  if( precision > 0) {
    strcat(outstr, ".\0"); // print the decimal point
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
      mult *=10;

    if(val >= 0)
      frac = (val - int(val)) * mult;
    else
      frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;

    while(frac1 /= 10)
      padding--;

    while(padding--)
      strcat(outstr,"0\0");

    strcat(outstr,itoa(frac,temp,10));
  }

  // generate space padding 
  if ((widthp != 0)&&(widthp >= strlen(outstr))){
    byte J=0;
    J = widthp - strlen(outstr);
    
    for (i=0; i< J; i++) {
      temp[i] = ' ';
    }

    temp[i++] = '\0';
    strcat(temp,outstr);
    strcpy(outstr,temp);
  }
  
  return outstr;
}
The second is from someone using a Mega to monitor fishpond temperatures with the ds18b20 which does use the RTC, also using an ethernet card which I am not using. This file would not compile on my arduino IDE as it says the sketch size is too large at 33,378 bytes of 32,256 bytes maximum.

Code: Select all

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "RTClib.h"
#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
#include <LiquidCrystal.h> 

// Pins in use
// 20 21 RTC - SDA - SLC
// 3 2 5 6 7 8 9 LCD 
// 22 ONE WIRE BUS
// 10 11 12 13 53 ETHERSHIELD
// 4 SD

//...........................................................
// defines
//...........................................................
// LCD
//#define BUTTON_ADC_PIN A0 // A0 is the button ADC input
#define LCD_BACKLIGHT_PIN 3 // D3 controls LCD backlight
//some example macros with friendly labels for LCD backlight/pin control, tested and can be swapped into the example code as you like
#define LCD_BACKLIGHT_OFF() digitalWrite( LCD_BACKLIGHT_PIN, LOW )
#define LCD_BACKLIGHT_ON() digitalWrite( LCD_BACKLIGHT_PIN, HIGH )

// do we print to serial 
#define ECHO_TO_SERIAL false 

// Data wire is plugged into pin 10 on the Arduino
#define ONE_WIRE_BUS 22

// RTC
RTC_DS1307 RTC;

// LCD
LiquidCrystal lcd( 8, 9, 2, 5, 6, 7 ); //Pins for the freetronics 16x2 LCD shield. LCD: ( RS, E, LCD-D4, LCD-D5, LCD-D6, LCD-D7 )

// 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.
// Working Probes
//DeviceAddress Probe01 = { 0x28, 0xD2, 0xCD, 0xE6, 0x03, 0x00, 0x00, 0xDE };
//DeviceAddress Probe02 = { 0x28, 0xA8, 0xCD, 0xE6, 0x03, 0x00, 0x00, 0x89 };
//DeviceAddress Probe03 = { 0x28, 0xB2, 0xBB, 0xE6, 0x03, 0x00, 0x00, 0xEC };
//DeviceAddress Probe04 = { 0x28, 0x99, 0xD0, 0xE6, 0x03, 0x00, 0x00, 0xC3 };

// test Probes
DeviceAddress Probe01 = { 0x28, 0x82, 0xBF, 0xE6, 0x03, 0x00, 0x00, 0x1E };
DeviceAddress Probe02 = { 0x28, 0xB1, 0xCB, 0xE6, 0x03, 0x00, 0x00, 0xD8 };
DeviceAddress Probe03 = { 0x28, 0xF3, 0xC9, 0xE6, 0x03, 0x00, 0x00, 0x40 };
DeviceAddress Probe04 = { 0x28, 0xEB, 0xD5, 0xE6, 0x03, 0x00, 0x00, 0xE7 };

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,50,40);

// (port 80 is default for HTTP):
EthernetServer server(80);

//...........................................................
// general variables
//...........................................................
// SD Card
// for the ethernet shield, we use digital pin 2 for the SD cs line
const int chipSelect = 4;
// interval for logging
const int LogInterval = 900; // 15 minutes
const int LCDInterval = 5; // 5 sec

//...........................................................
// general variables
//...........................................................
// log file
File logFile;
char CurrentLogName[] = "00000000.txt";
char LastLogName[] = "00000000.txt";
String DataTimeStamp;
unsigned long NextRun = 0;
unsigned long NextRunLCD = 0;

// probe descriptions
char Probe01N[10] = "Tank";
char Probe02N[10] = "Sump";
char Probe03N[10] = "GBed";
char Probe04N[10] = "OutSide";

// probe results
double ProbeR01, ProbeR02, ProbeR03, ProbeR04;

// rotating lcd display
int nextprobe = 0;

//...........................................................
// setup
//...........................................................
void setup() {
// start serial port
#if ECHO_TO_SERIAL
Serial.begin(9600);
#endif 

digitalWrite( LCD_BACKLIGHT_PIN, HIGH ); //backlight control pin D3 is high (on)
pinMode( LCD_BACKLIGHT_PIN, OUTPUT ); //D3 is an output
//set up the LCD number of columns and rows: 
lcd.begin( 16, 2 );
lcd.setCursor( 0, 0 ); //top left
lcd.print( "LCD READY.." );
lcd.setCursor( 0, 1 ); //top left
lcd.print( " " );

Wire.begin();
RTC.begin();
RTC.sqw(1);	//0 Led off - 1 Freq 1Hz - 2 Freq 4096kHz - 3 Freq 8192kHz - 4 Freq 32768kHz
if (! RTC.isrunning()) {
#if ECHO_TO_SERIAL
Serial.println("RTC is NOT running!");
#endif
logFile.println("// RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}

// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin 
// (10 on most Arduino boards, 53 on the Mega) must be left as an output 
// or the SD library functions will not work. 
// disable w5100 SPI while starting SD
pinMode(53,OUTPUT);
digitalWrite(53,HIGH);

#if ECHO_TO_SERIAL
Serial.print("Starting SD...");
#endif 

if(SD.begin(chipSelect) == 0) {
#if ECHO_TO_SERIAL
Serial.println("SD failed");
#endif 
}
else 
{
#if ECHO_TO_SERIAL
Serial.println(F("ok"));
#endif 
}

#if ECHO_TO_SERIAL
Serial.print(F("Starting w5100..."));
#endif 

lcd.setCursor( 0, 0 ); //top left
lcd.print( "Starting w5100..." );

// start the ethernet card
Ethernet.begin(mac, ip); 
server.begin();

#if ECHO_TO_SERIAL
Serial.println(Ethernet.localIP());
Serial.println("Ethernet Ready...");
#endif 

// lcd.setCursor( 0, 0 ); //top left
// lcd.print( "Ethernet Ready..." );

if (! startlogfile()) {
#if ECHO_TO_SERIAL
Serial.println("failed to write to card!");
#endif 
}
}

//...........................................................
// startlogfile
//...........................................................
// this where we set the log files up
boolean startlogfile()
{
generatedatetimecodes();

for(int x = 0; x < 11; x++) {
LastLogName[x] = CurrentLogName[x];
}

logFile = SD.open(CurrentLogName, FILE_WRITE);
// if the file opened okay, write to it:
if (logFile) {
// the file existed so write a new header then close the it
logFile.print("DateTime,");
logFile.print(Probe01N);
logFile.print(",");
logFile.print(Probe02N);
logFile.print(",");
logFile.print(Probe03N);
logFile.print(",");
logFile.println(Probe04N);
logFile.flush();
logFile.close();
return true;
} 
else {
return false;
}
}

//...........................................................
// generatedatetimecodes
//...........................................................
// we format the two types of time codes required
void generatedatetimecodes() 
{
DateTime now = RTC.now();
int temp;
String SYear, SMonth, SDay, SHour, SMin, SSec;

SYear = (String)now.year();

temp = now.month();
if (temp < 10) {
SMonth = ("0" + (String)temp); 
}
else {
SMonth = (String)temp;
} 

temp = now.day();
if (temp < 10) {
SDay = ("0" + (String)temp); 
}
else {
SDay = (String)temp;
} 

temp = now.hour();
if (temp < 10) {
SHour = ("0" + (String)temp); 
}
else {
SHour = (String)temp;
} 

temp = now.minute();
if (temp < 10) {
SMin = ("0" + (String)temp); 
}
else {
SMin = (String)temp;
} 

temp = now.second();
if (temp < 10) {
SSec = ("0" + (String)temp); 
}
else {
SSec = (String)temp;
} 

// log file name 
// Year
for(int x = 0; x < 4; x++) {
CurrentLogName[x] = SYear[x];
}

// Month
for(int x = 0; x < 2; x++) {
CurrentLogName[x + 4] = SMonth[x];
}

// Day
for(int x = 0; x < 2; x++) {
CurrentLogName[x + 6] = SDay[x];
}

// log date time stamp
DataTimeStamp = SDay;
DataTimeStamp += "/";
DataTimeStamp += SMonth;
DataTimeStamp += "/";
DataTimeStamp += SYear;
DataTimeStamp += " ";
DataTimeStamp += SHour;
DataTimeStamp += ":";
DataTimeStamp += SMin;
DataTimeStamp += ":";
DataTimeStamp += SSec;
}

//...........................................................
// printTemperature
//...........................................................
// read our Dallas Temperature probes DS18B20
double printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
return 0;
} 
else {
return tempC;
}
}

//...........................................................
// displaylog
//...........................................................
void displaylog() 
{
sensors.requestTemperatures();

ProbeR01 = printTemperature(Probe01);
ProbeR02 = printTemperature(Probe02);
ProbeR03 = printTemperature(Probe03);
ProbeR04 = printTemperature(Probe04);

generatedatetimecodes();

// if the new log file name does not match the last one
// ceate a new one with headers.
if (strcmp(LastLogName, CurrentLogName)) {
startlogfile();
}

#if ECHO_TO_SERIAL
Serial.print(DataTimeStamp);
Serial.print(",");
Serial.print(ProbeR01);
Serial.print(",");
Serial.print(ProbeR02);
Serial.print(",");
Serial.print(ProbeR03);
Serial.print(",");
Serial.println(ProbeR04);
#endif

// log the data to file
logFile = SD.open(CurrentLogName, FILE_WRITE);
// if the file opened okay, write to it:
if (logFile) {
// the file existed so write a new header then close it
logFile.print(DataTimeStamp);
logFile.print(",");
logFile.print(ProbeR01);
logFile.print(",");
logFile.print(ProbeR02);
logFile.print(",");
logFile.print(ProbeR03);
logFile.print(",");
logFile.println(ProbeR04);
logFile.flush();
logFile.close();
}
}

//...........................................................
// main
//...........................................................
void loop() {
// data logging
// we check if we are at our future time yet
// if so we display the logs and set a new future time
// get the current time
DateTime now = RTC.now();
unsigned long CurrentTime = now.unixtime();
if (CurrentTime >= NextRun) {
// set the next run time
NextRun = (now.unixtime() + LogInterval);
displaylog();
}

// lcd display to show temps
// we check if we are at our future time yet
// if so we display probe results in sequence and set a new future time
if (CurrentTime >= NextRunLCD) {
// set the next run time
NextRunLCD = (now.unixtime() + LCDInterval);
lcd.setCursor( 0, 0 ); //top left
lcd.print(DataTimeStamp);

switch (nextprobe) {
case 1:
lcd.setCursor( 0, 1 ); //bottom left
lcd.print(" Tank : ");
lcd.print(ProbeR01);
break;
case 2:
lcd.setCursor( 0, 1 ); //bottom left
lcd.print(" Sump : ");
lcd.print(ProbeR02);
break;
case 3:
lcd.setCursor( 0, 1 ); //bottom left
lcd.print("M G-Bed : ");
lcd.print(ProbeR03);
break;
case 4:
lcd.setCursor( 0, 1 ); //bottom left
lcd.print("Outside : ");
lcd.print(ProbeR04);
break;
}
// index our nextprobe couter and if we are over 3 the reset to 0
nextprobe ++;
if (nextprobe > 4) nextprobe = 0;
}
}
Thanks

Greg

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

You can print the temperature to the logfile the same way you print it to the lcd:

Code: Select all

  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    logFile.print("Error");
  } else {
    logFile.print(tempC);
    logFile.print("/");
    logFile.print(DallasTemperature::toFahrenheit(tempC));
  }

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

Thanks for the quick response.

When I put the code you posted into the loop, I get
LCD_temp_logger_1.6_2015_03_26.ino.ino: In function 'void loop()':
LCD_temp_logger_1.6_2015_03_26.ino.ino:254: error: 'deviceAddress' was not declared in this scope
since I have 6 sensors, also need to log the temperatures from each sensor in order so I know which is which, and I am not sure that the posted code could do that.

I thought I would be able to make a function called "logTemperature" which is just like the function "printTemperature", but rather than printing the temp to an LCD via lcd.print, it would write it to the SD card via logfile.print: this way I could call each sensor individually and send it to the SD card in the order I want. The printTemperature function works fine. In the setup the code is:

Code: Select all

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));
}
}


void logTemperature(DeviceAddress deviceAddress) // Check for temp probe error
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
lcd.print("Error");
} else {
logfile.print(tempC);
}
}

In the loop the code is:

Code: Select all

sensors.requestTemperatures();

logTemperature(Protoboard1Dot);
logfile.print(",");
logTemperature*(Protoboard2Dot);
logfile.print("/n");
logfile.flush();
However I get this error when I try to compile:
LCD_temp_logger_1.6_2015_03_26.ino.ino: In function 'void loop()':
LCD_temp_logger_1.6_2015_03_26.ino.ino:261: error: invalid operands of types 'void ()(uint8_t*)' and 'uint8_t [8]' to binary 'operator*'
I am having trouble figuring out what this error code means and how to correct it, please excuse my ignorance if I am doing something fundamentally wrong.

Greg

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

You've got a stray '*' in this line:

Code: Select all

logTemperature*(Protoboard2Dot);

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

Thanks for finding the error. The SD card is now able to log the tempC and the time stamp, yay!

I am trying to get the LCD to display the difference in temperatures between sensors, but i am unable to limit the number of digits.

Code: Select all

// record temps temperatures

float tempProtoboard1Dot = sensors.getTempC(Protoboard1Dot);
float tempProtoboard2Dot = sensors.getTempC(Protoboard2Dot);

// calculate differences in temps

float deltaProtoboard1Dot = tempProtoboard1Dot - tempProtoboard2Dot;

Code: Select all

//display the temperatures on the LCD
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir: ");
printTemperature(Protoboard2Dot);

delay(2000);
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Delta: ");
lcd.print (deltaProtoboard1Dot,2);
but the Delta is being displayed as more digits than I want (2 decimal places is enough) and has an extra period.

Why is the 2 in lcd.print(deltaProtoboard1Dot, 2) not limiting the LCD display of delta to only 2 digits?

when I use serial.print(deltaProtoboard1Dot, 2) it returns a value of only 2 decimal places (e.g. -0.25), as expected.
when I use serial.print(deltaProtoboard1Dot, 5) it returns a value of -0.25000.
when I use lcd.print(deltaProtobard1Dot, 2) it returns a close but not exactly the same number. e.g. (-0.253.40)

Why is lcd.print showing the correct number, and lcd.print showing a slightly different number with an extra "." in the # that I cannot truncate to 2 digits?

Thanks

Greg
Attachments
Arduino LCD2.JPG
Arduino LCD2.JPG (310.96 KiB) Viewed 1358 times
Arduino LCD1.JPG
Arduino LCD1.JPG (307.01 KiB) Viewed 1358 times
Last edited by Gumbajoe on Fri Mar 27, 2015 4:58 pm, edited 1 time in total.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

Actually, it is limiting it to 2 decimal places. the "3.40" is part of the "73.40". See? The "-0.25" is overwriting it.
You need to re-align your cursor locations to accommodate the longer "Delta:" header on the LCD

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

You are correct, I forgot how lcd.print function works - of course it does not blank out the rest of the line. I can clear the bottom line with lcd.clear(). My ignorance seems boundless.

I wanted to put a delta symbol on the LCD since there is limited room on the LCD: in the Adafruit LCD tutorial is shows a link to this page for special characters: http://www.quinapalus.com/hd44780udg.html

and states that
Click in the green grid to the left to set and clear pixels to create the graphic you want. Then copy the decimal, hex or binary values as necessary and paste them into your program.
A delta symbol gives the code
In decimal: 0,0,4,10,31,0,0
In hex: 0x0,0x0,0x4,0xa,0x1f,0x0,0x0
In binary: %0,%0,%100,%1010,%11111,%0,%0
but where do I "paste it into my program", and using what command? lcd.createChar()? Do I insert the decimal, hex, or binary or does it not matter? Do I have to put in some command to let the compiler know that the data is decimal, hex or binary? The page which the quinaplus page refers to http://robo.fe.uni-lj.si/~kamnikr/sola/ ... isplay.pdf is more technical and really does not address how to write code to display special characters that you generate yourself.

I also tried using something based on the Arduino webpage http://arduino.cc/en/Reference/LiquidCrystalCreateChar

Code: Select all

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte smiley[8] = {
  B00000,
  B10001,
  B00000,
  B00000,
  B10001,
  B01110,
  B00000,
};

void setup() {
  lcd.createChar(0, smiley);
  lcd.begin(16, 2);  
  lcd.write(byte(0));
}

void loop() {}
but the LCD would not display the character on the LCD, just a blank, see the attached images. My code in setup:

Code: Select all

//make a delta sign for the LCD display
byte delta[8] =
{
  B00000,
  B00000,
  B00100,
  B01010,
  B11111,
  B00000,
  B00000,
  B00000
};
My code in loop:

Code: Select all

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir");
lcd.createChar(0, delta);
lcd.write(byte(0));
lcd.print(":");
lcd.print(deltaProtoboard2Dot, 2);
lcd.print("C");
I assume with the above code the delta sign would be printed after the "Mir", but maybe I am just getting the format wrong.

I am OK producing the symbol either way (the http://www.quinapalus.com method would seem to use less memory): I am sure I am missing something obvious, but all of the examples showing generation of special characters on an LCD I can find show them displayed by themselves, and not on a line with other characters.

Thanks

Greg
Attachments
LCD with temps.JPG
LCD with temps.JPG (302.45 KiB) Viewed 1338 times
LCD delta blank.JPG
LCD delta blank.JPG (289.15 KiB) Viewed 1338 times

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

I notice that the smiley example does the createChar before the begin. I'd try doing that, too. Take the createChar out of your loop and put it in setup before the begin.

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

Moving createChar out of the loop did the trick, thanks.

Yet another problem - I am now trying to control the color display of the LCD via LCD pins 16,17, and 18 (red, green, blue respectively) with arduino pins A1, 5, and 6 (I ran out of digital pins). When I wrote some code to turn on each LED color one at a time, turning off the other LED backlight colors, I was suprised to see some unusual colors, see attached.
LCD pin 16 Arduino Pin A1 high RED.JPG
LCD pin 16 Arduino Pin A1 high RED.JPG (96.59 KiB) Viewed 1270 times
LCD pin 17 Arduino Pin 5 high GREEN.JPG
LCD pin 17 Arduino Pin 5 high GREEN.JPG (93.34 KiB) Viewed 1270 times
LCD pin 18 Arduino Pin 6 high BLUE.JPG
LCD pin 18 Arduino Pin 6 high BLUE.JPG (94.28 KiB) Viewed 1270 times
These are obviously not red, green, and blue.

By detaching all LCD backlight pins except one I could get the correct color to show on the LCD, but I noticed that the backlight was being activated when it should not be activated according to the code:

In Setup:

Code: Select all

LiquidCrystal lcd (14, 2, 4, 7, 8, 9); // (rs,en,db4,db5,db6,db7)

int backLightRed = A1; // pin 15 (A1) will control the backlight (red)
int backLightGreen = 5;
int backLightBlue = 6;

Code: Select all

pinMode(backLightGreen, OUTPUT);
pinMode(backLightBlue, OUTPUT);
pinMode(backLightRed, OUTPUT);
digitalWrite(backLightGreen, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightBlue, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.createChar(0, delta);
lcd.begin(16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc.
lcd.clear(); // start with a blank screen.
In Loop

Code: Select all

//display the temperatures on the LCD
lcd.clear();
digitalWrite(backLightGreen, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightBlue, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir: ");
printTemperature(Protoboard2Dot);

delay(2000);
lcd.clear();
digitalWrite(backLightGreen, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightBlue, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir");
lcd.write(byte(0));
lcd.print(":");
lcd.print(deltaProtoboard1Dot, 2);
lcd.print("C");

delay(2000);
lcd.clear();
digitalWrite(backLightBlue, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightGreen, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir");
lcd.write(byte(0));
lcd.print(":");
lcd.print(deltaProtoboard1DotF, 2);
lcd.print("F");
When the code is run, this is what I see:

For the first display in the loop which is "Out: " and "Mir:", Red is off green is on blue is on
For the second display in the loop which is "Out: " and "Mir delta symbol C", Red is on green is on blue is off
For the third display in the loop which is "Out: " and "Mir delta symbol F", Red is on green is off blue is on

The surprising thing is that even when I put a set of digitalWrite to LOW for all 3 arduino pins at the beginning of each of the displays listed above before setting the desired backlight pin HIGH, there is no change to the pattern above.

Why is my code activating more than one backlight at a time, and why is my command to turn off all backlights except one being ignored? This has to be a code error but I cannot find it.

Here's the whole sketch (I need to do some clean-up as some commands are duplicated, but you should be able to understand what I am doing throughout)

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 backLightRed = A1; // pin 15 (A1) will control the backlight (red)
int backLightGreen = 5;
int backLightBlue = 6;

//make a delta sign for the LCD display
byte delta[8] =
{
  B00000,
  B00000,
  B00100,
  B01010,
  B11111,
  B00000,
  B00000,
  B00000
};



// 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
logfile = SD.open(filename, FILE_WRITE);
logfile.print("DateTime,");
logfile.print("Protoboard1Dot,");
logfile.print("Protoboard2Dot,");
logfile.print("OutsideTemp,");
logfile.print("Mirror1Oclock,");
logfile.print("Mirror7Oclock,");
logfile.print("BehindMirrorFanLeft,");
logfile.print("MirrorBoxBack,");
logfile.print("MirrorBoxFront,");
logfile.println();
logfile.flush();

#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);

// define temp C at each sensor as a float
float tempOutside = sensors.getTempC(OutsideTemp);
float tempProtoboard1Dot = sensors.getTempC(Protoboard1Dot);
float tempProtoboard1DotF = sensors.getTempF(Protoboard1Dot);
float tempProtoboard2Dot = sensors.getTempC(Protoboard2Dot);
float tempProtoboard2DotF = sensors.getTempC(Protoboard2Dot);
float tempMirror1Oclock = sensors.getTempC(Mirror1Oclock);
float tempMirror7Oclock = sensors.getTempC(Mirror7Oclock);
float tempBehindMirrorFanLeft = sensors.getTempC(BehindMirrorFanLeft);
float tempMirrorBoxBack = sensors.getTempC(MirrorBoxBack);
float tempMirrorBoxFront = sensors.getTempC(MirrorBoxFront);


//define the delta temp C for ambient and each sensor as a float
float deltaProtoboard1Dot = tempProtoboard1Dot - tempProtoboard2Dot;
float deltaProtoboard1DotF = tempProtoboard1DotF - tempProtoboard2DotF;
float deltaProtoboard2Dot;
float deltaMirror1Oclock;
float deltaMirror7Oclock;
float deltaBehindMirrorFanLeft;
float deltaMirrorBoxBack;
float deltaMirrorBoxFront;



pinMode(backLightGreen, OUTPUT);
pinMode(backLightBlue, OUTPUT);
pinMode(backLightRed, OUTPUT);
digitalWrite(backLightGreen, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightBlue, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.createChar(0, delta);
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));
}
}


void logTemperature(DeviceAddress deviceAddress) // Check for temp probe error
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
lcd.print("Error");
} else {
logfile.print(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(", ");

sensors.requestTemperatures();

// record temps temperatures Protoboard1dot simulates outside temp

float tempOutside = sensors.getTempC(OutsideTemp);
float tempProtoboard1Dot = sensors.getTempC(Protoboard1Dot);
float tempProtoboard1DotF = sensors.getTempF(Protoboard1Dot);
float tempProtoboard2Dot = sensors.getTempC(Protoboard2Dot);
float tempProtoboard2DotF = sensors.getTempF(Protoboard2Dot);
float tempMirror1Oclock = sensors.getTempC(Mirror1Oclock);
float tempMirror7Oclock = sensors.getTempC(Mirror7Oclock);
float tempBehindMirrorFanLeft = sensors.getTempC(BehindMirrorFanLeft);
float tempMirrorBoxBack = sensors.getTempC(MirrorBoxBack);
float tempMirrorBoxFront = sensors.getTempC(MirrorBoxFront);

// calculate differences in temps Protpboard1Dot simulates outside temp
float deltaProtoboard1Dot = tempProtoboard1Dot - tempProtoboard2Dot;
float deltaProtoboard1DotF = tempProtoboard1DotF - tempProtoboard2DotF;
float deltaProtoboard2Dot = tempProtoboard2Dot - tempProtoboard1Dot;
float deltaMirror1Oclock = tempMirror1Oclock - tempProtoboard1Dot;
float deltaMirror7Oclock = tempMirror7Oclock - tempProtoboard1Dot;
float deltaBehindMirrorFanLeft = tempBehindMirrorFanLeft - tempProtoboard1Dot;
float deltaMirrorBoxBack = tempMirrorBoxBack - tempProtoboard1Dot;
float deltaMirrorBoxFront = tempMirrorBoxFront - tempProtoboard1Dot;

Serial.print("protoboard1dotF:");
Serial.print(tempProtoboard1DotF);
Serial.print("\n");
Serial.print("protoboard2dotF:");
Serial.print(tempProtoboard2DotF);
Serial.print("\n");
Serial.print("deltaprotoboard1dotF:");
Serial.print(deltaProtoboard1DotF);
Serial.print("\n");

// log the temperatures to the SD card
logTemperature(Protoboard1Dot);
logfile.print(", ");
logTemperature(Protoboard2Dot);
logfile.print(", ");
logTemperature(OutsideTemp);
logfile.print(", ");
logTemperature(Mirror1Oclock);
logfile.print(", ");
logTemperature(Mirror7Oclock);
logfile.print(", ");
logTemperature(BehindMirrorFanLeft);
logfile.print(", ");
logTemperature(MirrorBoxBack);
logfile.print(", ");
logTemperature(MirrorBoxFront);
logfile.println();
logfile.flush();

//display the temperatures on the LCD
lcd.clear();
digitalWrite(backLightGreen, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightBlue, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir: ");
printTemperature(Protoboard2Dot);

delay(2000);
lcd.clear();
digitalWrite(backLightGreen, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightBlue, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir");
lcd.write(byte(0));
lcd.print(":");
lcd.print(deltaProtoboard1Dot, 2);
lcd.print("C");

delay(2000);
lcd.clear();
digitalWrite(backLightBlue, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightRed, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
digitalWrite(backLightGreen, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
lcd.setCursor(0,0);
lcd.print("Out: ");
printTemperature(Protoboard1Dot);
lcd.setCursor(0,1);
lcd.print("Mir");
lcd.write(byte(0));
lcd.print(":");
lcd.print(deltaProtoboard1DotF, 2);
lcd.print("F");


//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(2000);
}
Thanks

Greg

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

The LCD backlight leds are active low. So, to turn on a LED, you write your output pin to LOW. To turn off the LED, you write it HIGH.

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

That worked - I thought it was the reverse. I didn't see anything stating this in the adafruit documentation, and couldn't figure it out from looking at the code from the Adafruit RGB blacklit code at https://learn.adafruit.com/character-lc ... cklit-lcds.

Hope others can learn from my blunders.

next steps are to

change the color on the display depending on the temperature difference displayed (I figure I can use some "if" commands to do this without too much trouble).

make the LCD backlight brightness controllable via a button or knob (need to be able to read the screen both in daylight and at night, but need to limit backlight brightness at night to maintain night vision (this seems to be more complicated, in my understanding you need to change the mA, not the voltage to the backlight).

I have the Adafruit 16 x 2 LCD shield which contains buttons, but I would have to think about how to implement this. A lot of stuff I find online is going over my head, and while the shield has a pot to control contrast, there is not one for controlling background LED brightness. It does seem that using the shield makes a lot of sense, but I can't seem to find an enclosure which has an opening which accommodates the shield buttons. Does Adafruit make such an enclosure or what have other people done in a similar situation? A flip-lid enclosure? This project will be free-standing and mounted to the side of a telescope and running off batteries, and I would have to worry about dew forming on the surface of any exposed hardware as it will be outside periodically at night.

Thanks for all of the help on this project Adafruit_support_rick!

Greg

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: RTC and Dallastemperature save to SD coding help

Post by adafruit_support_rick »

You won't control the display brightness in software. You'll have to wire a pot to the backlight anode pin on the LCD module (pin 15). That way you can adjust the current going to the LEDs.

You can use one of these enclosures. For the dimmer pot and any buttons you need, you can wire them to the shield, then drill a hole and use a cable gland for the wires.
https://www.adafruit.com/product/762

User avatar
Gumbajoe
 
Posts: 43
Joined: Fri Nov 14, 2014 4:04 pm

Re: RTC and Dallastemperature save to SD coding help

Post by Gumbajoe »

Thanks for the tips - I notice that the red LED seems brighter than the other LEDs (not sure if it really is or not - can't seem to figure it out from the documentation). Could I put a potentiometer in line with each of the 3 LED pins (16-18) to allow adjusting the brightness of each LED individually rather than only on pin 15?

The cable gland looks like a good idea. I didn't see links to an enclosure in your post you referenced - My project is a little problematic as there is an SD card shield which I need to be able to access for insertion/removal of the SD card, along with accessing the pots to control brightness.

Thanks

Greg

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”