// DS2438_1 (Arduino) // // Illustrates an interface with a Dallas DS2438 Battery Monitor. // // Measures Temperature, Vad and Vdd // // Displays to a serial LCD operating at 9600 baud. // // Arduino Board DS2438 // // +5 VDC // | // 4.7K // 8 ---------------- |---------------- DQ (term 8) // // +5 VDC ---------- Vdd (term 5) // GRD ------------- GRD (term 1) // // --------- Vad (term 4) // // Tx ---------------------------- To Serial LCD (LCD #117) // // Peter H Anderson, Baltimore, MD, May 11, '07 #define V_AD 1 #define V_DD 0 int MeasTemperature_2438(int _1W_Pin); int MeasADC(int _1W_Pin, int source); int CalcRH(int Vad_100, int Vdd_100); void OneWireReset(int _1W_Pin); void OneWireOutByte(int _1W_Pin, byte d, byte strong); byte OneWireInByte(int _1W_Pin); void setup() { int n, _1W_Pin; _1W_Pin = 8; 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); Serial.print("?f"); // clear LCD delay(100); } void loop() { int _1W_Pin, WordVal, SignBit, Tc_100, Vad_100, Vdd_100, RH_10, Whole, Fract; _1W_Pin = 8; ///// Perfrom Temperature Measurement WordVal = MeasTemperature_2438(_1W_Pin); SignBit = WordVal & 0x8000; if (SignBit) { WordVal = WordVal ^ 0xffff + 1; // take the twos comp } WordVal = WordVal / 8; Tc_100 = 3 * WordVal + WordVal / 8; // 0.03125 Whole = Tc_100 / 100; // separate off the whole and fractional portions Fract = Tc_100 % 100; Serial.print("?f"); // clear LCD if (SignBit) // if negative { Serial.print("-"); } Serial.print(Whole); Serial.print("."); if (Fract < 10) { Serial.print("0"); } Serial.print(Fract); ///// Vad Vad_100 = MeasADC(_1W_Pin, V_AD); Whole = Vad_100 / 100; // separate off the whole and fractional portions Fract = Vad_100 % 100; Serial.print("?n"); // tab Serial.print(Whole); Serial.print("."); if (Fract < 10) { Serial.print("0"); } Serial.print(Fract); ///// Vdd Vdd_100 = MeasADC(_1W_Pin, V_DD); Whole = Vdd_100 / 100; // separate off the whole and fractional portions Fract = Vdd_100 % 100; Serial.print("?n"); // tab Serial.print(Whole); Serial.print("."); if (Fract < 10) { Serial.print("0"); } Serial.print(Fract); RH_10 = CalcRH(Vad_100, Vdd_100); Whole = RH_10 / 10; Fract = RH_10 % 10; Serial.print("?n"); Serial.print(Whole); Serial.print("."); Serial.print(Fract); delay(5000); // 5 second delay. Adjust as necessary } int MeasTemperature_2438(int _1W_Pin) { int a[9], v, tc_100, n; OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0x4e, 0); OneWireOutByte(_1W_Pin, 0x00, 0); //OneWireOutByte(_1W_Pin, 0x00, 0); // setup for VDD input OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0x44, 0); // temperature delay(1000); OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0xb8, 0); OneWireOutByte(_1W_Pin, 0x00, 0); // recall memory OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0xbe, 0); OneWireOutByte(_1W_Pin, 0x00, 0); // read scratchpad beginning at zero for (n=0; n<9; n++) { a[n] = OneWireInByte(_1W_Pin); //Serial.print(a[n]); //Serial.print("...?n"); //delay(100); } v = a[2] * 256 + a[1]; return(v); } int MeasADC(int _1W_Pin, int source) { int n, a[9], v; OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0x4e, 0); OneWireOutByte(_1W_Pin, 0x00, 0); // setup for Vdd or A/D if (source == V_AD) { OneWireOutByte(_1W_Pin, 0x00, 0); // Vad } else { OneWireOutByte(_1W_Pin, 0x08, 0); // Vdd } OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0xb4, 0); // perform A/D delay(1000); // wait for A/D to complete OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0xb8, 0); OneWireOutByte(_1W_Pin, 0x00, 0); // recall to scratchpad OneWireReset(_1W_Pin); OneWireOutByte(_1W_Pin, 0xcc, 0); OneWireOutByte(_1W_Pin, 0xbe, 0); OneWireOutByte(_1W_Pin, 0x00, 0); // read scratchpad for (n=0; n<9; n++) { a[n] = OneWireInByte(_1W_Pin); //Serial.print(a[n]); //Serial.print("...?n"); //delay(100); } v = a[4] * 256 + a[3]; return(v); } int CalcRH(int Vad_100, int Vdd_100) { int x, Vdd_10, RH_10; Vdd_10 = Vdd_100 / 10; x = 10 * Vad_100 / Vdd_10 - 16; RH_10 = 16 * x + x/10; return(RH_10); } 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); }