I've written (most of it cut and paste from examples) code to get temperatures from two DS18B20 sensors and display them to a LCD module.
I put the code so might be useful to someone. However there are two drawbacks which I cooked my brain on without finding solution, but hey I'm just a n00b
//1-Wire temperature display on 4-bit LCD sketch
#include <LiquidCrystal.h>
#include <OneWire.h>
//create object to control an LCD.
//number of lines in display=1
LiquidCrystal lcd(7, 0, 6, 2, 3, 4, 5);
OneWire ds(8); // DS18B20 Temperature chip i/o
byte TempDisp; //switch to alternate temperature display
unsigned long Time; //time variable for millis function
void setup() {
Serial.begin(9600);
pinMode(13, OUTPUT); //we'll use the debug LED to output a heartbeat
//optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
//lcd.commandWrite(0x0F);//cursor on, display on, blink on. (nasty!)
}
void loop() {
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
byte i;
byte present = 0;
byte data[12];
byte addr[8];
char tempo[8];
if ( !ds.search(addr)) {
Serial.print("No more addresses.\n");
ds.reset_search();
return;
}
Serial.print("R=");
for( i = 0; i < 8; i++) {
Serial.print(addr[i], HEX);
Serial.print(" ");
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n");
return;
}
if ( addr[0] != 0x28) {
Serial.print("Device is not a DS18S20 family device.\n");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
if (millis()-Time > 1000) { //non blocking refresh of temperature reading and LCD display
Time = millis();
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
Serial.print("P=");
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();
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
if (SignBit) // If its negative
{
Serial.print("-");
}
Serial.print(Whole);
Serial.print(".");
if (Fract < 10)
{
Serial.print("0");
}
Serial.print(Fract);
Serial.print("\n");
tempo[0]= (Whole)/10 +'0' ;
tempo[1]= Whole-(10*(Whole/10)) +'0';
tempo[2]='.';
tempo[3]= (Fract)/10 +'0';
tempo[4]= Fract-(10*(Fract/10)) +'0';
tempo[5]= ' ';
tempo[6]= 223;
tempo[7]= 'C';
tempo[8]= '\0';
if (TempDisp == 0) {
//lcd.clear();
lcd.setCursor(0, 0);
lcd.print(tempo);
lcd.print(" int");
TempDisp = 1;
} else {
lcd.setCursor(0, 1); //line=2, x=0.
lcd.print(tempo);
lcd.print(" ext");
TempDisp = 0;
}
}
}
-
i've put millis() instead of delay for avoiding to block code execution, since I plan to add other functions. But since the 1-wire routine isn't linked to a particular 1-wire device ID but displays all of them, with millis() it happens that the displayed temperature can get exchanged
-
String conversion/manipulation in Arduino is really complicated! Don't know if it's due to space constraints or it's a C++ feature (I have always programmed in VB), but the only way I found so far is to put an ascii character in every item of the string array.
I'd like to write a subroutine that inputs an integer value like 2468 and a positive/negative bit and outputs a string like 24.68.
The temperatures could go from -99.99 to +99.99 so it needs a 6 character string.
I tried to write it but it's really a mess for me and doesn't work
char *Temp2String (int t, int signbit) {
char tempo[5];
int Whole, Fract;
Whole = t / 100; // separate off the whole and fractional portions
Fract = t % 100;
if (signbit) tempo[0]='-';
tempo[1]= (Whole)/10 +'0' ;
tempo[2]= Whole-(10*(Whole/10)) +'0';
tempo[3]='.';
if (Fract < 10) {
tempo[4]='0';
} else {
tempo[4]= (Fract)/10 +'0';
}
tempo[5]= Fract-(10*(Fract/10)) +'0';
return tempo;
}
I hope someone will write a library to manipulate strings like in BASIC which is much easier i.e. strings aren't an array of characters, doesn't need null character at the end, and you can convert easily with val and str$ functions...