// 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);
}