Hello all, I'm having a bit of trouble working out how I can get this to work the way I need, since most questions I can find that were asked previously don't quite work the way I have my device set up.
Basically, it monitors and prints out temperature to an 8x2 character LCD, however, at any point you can flick a switch, and every 5 seconds, it logs temperature data to a text file on the SD card, simple enough, then you just stick it into excel, and graph it out. (It doesn't have an RTC, so no timestamp, but I am not sure how you'd implement that, aside from using the millis counter and incrementing some other counter, not a priority right now).
Anyhow, since this can run continuously and you can turn on and off logging at will, it just sticks everything into one file, which is fine for single use, but I'd like to add a bit more functionality.
Basically, each time you start logging, it would check for the files on the card, and if it saw files up to "Log 0033", it would then change over the putting the current info into "log 0034", and so forth. It might also work with another text file that keeps the log entries, if you can read the last line in a file.
Anyhow the main thing that has me a little stumped, is that since I have this as a function in the main loop, I will need a way for it to check the files and increment the file name each time I start logging. I figure a variable that will change from true or false will let me bypass the file checking and creation once it's underway, but incrementing the file is the difficult bit.
Here's the section of code which takes care of the datalogging.
logstate = digitalRead(2); // read the input pin
if (logstate == LOW) {
if (currentMillis - sdpreviousMillis >= sdinterval) { //Write to SD card every 5 seconds.
sdpreviousMillis = currentMillis;
digitalWrite(A1, HIGH);
myFile = SD.open("Log.txt", FILE_WRITE);
myFile.print(celsius);
myFile.println(" C ");
myFile.close();
delay(5);
digitalWrite(A1, LOW);
}
}
and here is the code in it's entirety (still needs to be cleaned up a bit, and some of the annotations don't match the values)
#include <OneWire.h>
#include <LiquidCrystal.h>
#include <SPI.h>
#include <SD.h>
unsigned long owpreviousMillis = 0;
const long owinterval = 750;
//---------------------------------------------------------------------------------- One wire temperature sensor stuff
OneWire ds(A3); //Setting one wire bus pin
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit; //Variables for celsius and farenheit conversions
unsigned long previousMillis = 0;
float lasttemp; //Variable for last temperature
float delta; //Variable for temperaturechange
const long interval = 750; //Check once every 1 second
//---------------------------------------------------------------------------------- End of one wire temperature sensor stuff.
LiquidCrystal lcd(8, 7, 5, 6, 3, 4); //Defining pins for the LCD
//---------------------------------------------------------------------------------- SD card stuff
const int chipSelect = 10; //Setting SD chip select pin (obviously)
File myFile;
unsigned long sdpreviousMillis = 0;
const long sdinterval = 4245; //SD card write interval
int logstate = 0;
//-----------------------------------------------------------------------------------End of pre-setup
void setup(void) {
pinMode(9, OUTPUT); //Backlight Pin
digitalWrite(9, LOW);
pinMode(2, INPUT); //Momentary button to toggle logging
digitalWrite(2, HIGH); //Set internal pull-up to stop floating noise.
pinMode(A2, OUTPUT); //Green LED for temperature stability indication
pinMode(A1, OUTPUT); //Red LED for sd card activity indication
Serial.begin(115200);
//------------------------- Testing LCD and LED's, displaying version number and checking for SD card.
lcd.begin(8, 2);
lcd.setCursor(0,0);
lcd.print("STARTING");
lcd.setCursor(0, 1);
lcd.print("VER. 1.6");
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
delay(1000);
digitalWrite(A1, LOW);
digitalWrite(A2, LOW);
lcd.clear();
if (!SD.begin(10)) { // Check for SD card
digitalWrite(A1, HIGH);
lcd.setCursor(0,0);
lcd.print("SD CHECK");
lcd.setCursor(0,1);
lcd.print(" FAIL ");
delay(1000);
lcd.clear();
digitalWrite(A1, LOW);
} else {
delay(1000);
digitalWrite(A1, HIGH);
lcd.setCursor(0,0);
lcd.print("SD CHECK");
lcd.setCursor(0,1);
lcd.print(" PASS ");
delay(1000);
lcd.clear();
digitalWrite(A1, LOW);
}
//----------------------------------- Setting up one wire temperature sensor.
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
return;
}
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}
}
//----------------------------------------------------------------------------- End of setup.
void loop(void) {
unsigned long currentMillis = millis();
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(750);
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
}
else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print(" Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
delta = celsius - lasttemp; //Create value to check how much temperature has changed
if (currentMillis - previousMillis >= interval) { //If it has been 20 seconds, check to turn LED on
previousMillis = currentMillis;
if ((delta < 00.03) && (delta > -00.03)) { //If temperature hasn't changed by +/- .05 turn led on.
digitalWrite(A2, HIGH);
} else if ((delta >= 00.06) || (delta <= -00.06)) {
digitalWrite(A2, LOW);
}
}
lcd.setCursor(0, 0);
lcd.print(celsius);
lcd.print(" C ");
lcd.setCursor(0, 1);
lcd.print(fahrenheit);
lcd.print(" F ");
lasttemp = celsius;
logstate = digitalRead(2); // read the input pin
if (logstate == LOW) {
if (currentMillis - sdpreviousMillis >= sdinterval) { //Write to SD card every 5 seconds.
sdpreviousMillis = currentMillis;
digitalWrite(A1, HIGH);
myFile = SD.open("Log.txt", FILE_WRITE);
myFile.print(celsius);
myFile.println(" C ");
myFile.close();
delay(5);
digitalWrite(A1, LOW);
}
}
if (logstate == LOW) {
digitalWrite(9, HIGH);
} else {
digitalWrite(9, LOW);
}
}
I'll keep to the grindstone once I wake up a bit more, but I figure maybe someone may have encountered this exact same thing and already knows of a solution. May as well tackle it on two fronts