Onboard BallastHalo 3 there are 4 temperature sensors; 1 DS18S20 and 3 DS18B20. These ICs are self contained sensor that do not require calibration, uses the Dallas One-Wire protocol and has a range that extends down to -55oC - perfect for ballooning!
There are 2 power setups for the DS18x20 either power can be provided directly from the regulator or can be provided over the data line from the arduino, this 2nd mode is known as parasite power. In this case as I have an easily accessible 3.3v supply I'll be providing the power directly.
One-Wire allows you to create a sensor network on a single I/O pin out out the AVR, each module has a unique ID address which allows you to directly communicate the the sensor and collect the data.
There is a
3rd party library that provides the One-wire functions and many examples online of how to hook up the sensor to an arduino.
DS18S20 and DS18B20 differ slightly in how they report temperature and therefore the data received requires slightly different conversion to get a valid temperature. Using the examples from
OneWire Reference as a basis I wrote a function that if passed the unique ID address would identify, collect and correctly convert the temperature. The function identifies what type of sensor as the DS18B20's address begin with 0x28 while DS18S20 start with 0x10:
#include <OneWire.h
// DS18x20 Temperature chip i/o
OneWire ds(11); // on pin 10
byte address0[8] = {0x10, 0x22, 0x4A, 0xDB, 0x0, 0x8, 0x0, 0x94}; //Internal DS18S20 onboard daughter board
byte address1[8] = {0x28, 0x2D, 0x28, 0x2E, 0x2, 0x0, 0x0, 0xE}; // External DS18B20
byte address2[8] = {0x28, 0x5D, 0x26, 0x2E, 0x2, 0x0, 0x0, 0x34}; // Internal DS18B20 Pump Sensor
byte address3[8] = {0x28, 0x26, 0xF5, 0x2D, 0x2, 0x0, 0x0, 0xCC}; // Internal DS18B20 GPS Sensor
void loop()
{
delay(1000);
temp0 = getTempdata(address0);
delay(100);
temp1 = getTempdata(address1);
delay(100);
temp2 = getTempdata(address2);
delay(100);
temp3 = getTempdata(address3);
Serial.print(temp0);
Serial.print(",");
Serial.print(temp1);
Serial.print(",");
Serial.print(temp2);
Serial.print(",");
Serial.print(temp3);
Serial.print("\n");
}
// gets temperature data from onewire sensor network, need to supply byte address, it'll check to see what type of sensor and convert appropriately
int getTempdata(byte sensorAddress[8]) {
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole;
byte data[12], i, present = 0;
ds.reset();
ds.select(sensorAddress);
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(sensorAddress);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
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
}
if (sensorAddress[0] == 0x10) {
Tc_100 = TReading * 50; // multiply by (100 * 0.0625) or 6.25
}
else {
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
if (SignBit) // If its negative
{
Whole = Whole * -1;
}
return Whole;
}