Hello all, I have a temperature sensor device that I want add datalogging too, and finally grabbed some SD card boards.
Now, this is the code as follows, it interfaces with the dallas instruments one wire temperature sensors. It continuously reads out the temperature, and when the temperature stabilizes, it turns on an LED to indicate this, and when the temperature shifts, it turns it off.
#include <OneWire.h>
#include <LiquidCrystal.h>
OneWire ds(10);
LiquidCrystal lcd(6, 7, 5, 4, 3, 2);
float lasttemp; //Variable for last temperature
float delta; //Variable for temperaturechange
long previousMillis = 0;
long interval = 20000; //Check once every 20 seconds
void setup(void) {
pinMode(13, OUTPUT);
Serial.begin(115200);
lcd.begin(8, 2);
lcd.setCursor(0,0);
lcd.print("STARTING");
lcd.setCursor(0, 1);
lcd.print("VER. 1.1");
delay(1000);
lcd.clear();
}
void loop(void) {
unsigned long currentMillis = millis();
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
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;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
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(13, HIGH);
}
}
if (delta >= 00.06) { //If temperature has changed by more than .1 turn LED off
digitalWrite(13, LOW);
}
if (delta <= -00.06) {
digitalWrite(13, LOW); // If temperature has changed by more than -.1 turn LED off
}
lcd.setCursor(0, 0);
lcd.print(celsius);
lcd.print(" C ");
lcd.setCursor(0, 1);
lcd.print(fahrenheit);
lcd.print(" F ");
lasttemp = celsius;
}
Now, I want to maintain this functionality, but also add in a button to toggle SD card logging, which will write to the sd card every x milliseconds (not sure on the length of time I want right now, probably every 5 seconds or so).
I'm wondering what the best way to implement this is, I don't want to add any delays to the temperature readout, and certainly don't want to have it update once every 5 seconds. I think you need a timeout to make sure the button press doesn't repeat though, correct?
It's been a while so I can't recall how to set up smaller sections that you can run once (not in the main loop as an if/else statement, but in one which will run once).
I also saw multipleblinks, and it seems that some arduinos can run multiple loops at once now? I'm not sure if that works for all, or if a pro mini would be capable of this.
Anyways, I can handle the sd card writing and delay, all that stuff, I'm just a bit stuck on how to basically be able to press the button at any time to start/stop datalogging.
