Introduction
Note that this is my first venture using the Arduino and I am amazed with the possibilities. I am also amazed with the amount of dedicated talent that has gone into the Arduino effort.
I used
This program continually measures the temperature at three points using the Dallas DS18B20 1-W thermometer. Note that each device is on its own dedicated pair (DQ and GRD). One might use this to monitor outdoor, indoor and the temperature in the wine cellar. My own experience has been to limited any run to 200 feet.
My plan is to extend this to illustrate how to interface with the DS2438 battery monitor to measure a voltage and a temperature, the DS2423 which has two 32 bit counters and the DS2450 quad A/D converter. I also plan to develop code for a PC to periodically perform measurements and log data or operate a relay or similar to turn on a fan or heater.
I realize there is a library of OneWire routines. However, in the interest of learning I wrote my own OneWireReset, OneWireOutByte and OneWireInByte functions.
Detailed Discussion.
Each transmission is initiated with a reset (or presence) pulse, by bringing the signal lead low for 500 us and then back to high-Z for 500 us.
The commands 0xcc (skip ROM) followed by 0x44 (perform temperature measurement) are written to the device. Note that when using the DS18B20 in the parasite mode, a strong source of +5 VDC must exerted within about 10 us of issuing the perform temperature measurement command. Thus, I opted to implement the strong pull-up in the OneWireOutByte function.
This is followed by the reset pulse and commands 0xcc (skip ROM) and 0xbe (read temperature).
Two byte are then read into variables LowByte and HighByte. The bytes are then combined into a 16-bit quantity TReading. This is a 16-bit signed number which is converted to temperature by multiplying by 0.0625.
However, rather than use floats, 100 times the Tc was calculated and then broken into the whole and fractional parts when displayed.
Note that the serial LCD used to display the result is my LCD #117 Serial LCD.
// DS18B20_1 - Arduino // // Continually measures temperatures at three points using the Dallas DS18B20 on three // separate Arduino pins. // // Uses the parasitic power mode // // Displays to a serial LCD operating at 9600 baud. // // Arduino Board DS18B20 // // +5 VDC // | // 4.7K // 8 ---------------- |----- 2 (DQ) Note that terms 1 and 3 are grounded. // // 7 ---- same as above // 6 ---- same as above // // Tx ---------------------------- To Serial LCD (LCD #117) // // copyright, Peter H Anderson, Baltimore, MD, May 5, '07 void setup() { int n, dev_channel[3] = {8, 7, 6}, _1W_Pin; for (n=0; n<1; n++) { _1W_Pin = dev_channel[n]; digitalWrite(_1W_Pin, LOW); pinMode(_1W_Pin, INPUT); // sets the digital pin as input (logic 1) } Serial.begin(9600); delay(100); Serial.print("?B40"); // set backlight intensity delay(100); } void loop() { int n, dev_channel[3] = {8, 7, 6}, _1W_Pin; int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract; for (n=0; n<3; n++) { _1W_Pin = dev_channel[n]; OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0x44, 1); // perform temperature conversion, strong pullup for one sec OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0xbe, 0); LowByte = OneWireInByte(_1W_Pin); HighByte = OneWireInByte(_1W_Pin); 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 (n==0) // if its the first time, clear the LCD { Serial.print("?f"); delay(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"); } delay(5000); // 5 second delay. Adjust as necessary } void OneWireReset(int _1W_Pin) // reset. Should improve to act as a presence pulse { digitalWrite(_1W_Pin, LOW); pinMode(_1W_Pin, OUTPUT); // bring low for 500 us delayMicroseconds(500); pinMode(_1W_Pin, INPUT); delayMicroseconds(500); } void OneWireOutByte(int _1W_Pin, byte d, byte strong) // output byte d (least sig bit first). { byte n; for(n=8; n!=0; n--) { if ((d & 0x01) == 1) // test least sig bit { digitalWrite(_1W_Pin, LOW); pinMode(_1W_Pin, OUTPUT); delayMicroseconds(5); pinMode(_1W_Pin, INPUT); delayMicroseconds(60); } else { digitalWrite(_1W_Pin, LOW); pinMode(_1W_Pin, OUTPUT); delayMicroseconds(60); pinMode(_1W_Pin, INPUT); } d=d>>1; // now the next bit is in the least sig bit position. } if(strong) { digitalWrite(_1W_Pin, HIGH); // One sec of strong +5 VDC pinMode(_1W_Pin, OUTPUT); delay(1000); pinMode(_1W_Pin, INPUT); digitalWrite(_1W_Pin, LOW); } } byte OneWireInByte(int _1W_Pin) // read byte, least sig byte first { byte d, n, b; for (n=0; n<8; n++) { digitalWrite(_1W_Pin, LOW); pinMode(_1W_Pin, OUTPUT); delayMicroseconds(5); pinMode(_1W_Pin, INPUT); delayMicroseconds(5); b = digitalRead(_1W_Pin); delayMicroseconds(50); d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position } return(d); }