This lesson will demonstrate how to use the Oak to read and publish temperature data from the DS18B20 1-Wire Digital Thermometer.
Part | Quantity | Identification |
---|---|---|
Oak with soldered headers | 1 | |
Breadboard | 1 | |
One Wire Temperature Sensor TO-92 | 1 | DS18B20 |
4.7K Ohm ¼W Resistor | 1 | Yellow-Purple-Red |
Jumper Wires | 6 |
[NOTE: You can find an index of the parts in the starter and ultimate kits here: Starter and Ultimate Kit Parts List]
In this lesson we demonstrate how to connect a 1-Wire device to the Oak platform using the 1-Wire bus compatible DS18B20 Digital Thermometer. We demonstrate the use of a pull-up resistor on the DS18B20 device DQ line (1-Wire Bus Data Input/Output). And finally, we show you how to publish the temperature data received from the device to the Particle.io Dashboard log.
Note the orientation of the leads on the DS18B20 device. From left to right they are: (1) GND, (2) DQ, (3) Vdd.
The 1-Wire DS18B20 digital thermometer can operate at either 3.3V or 5V. For this lesson we use the 3.3V supplied by the Oak's VCC 3.3V pin. The DS18B20 Data Input/Output lead (DQ) is pulled up to 3.3V by using a 4.7K ohm resister between VCC and the DQ lead.
If you would like to learn more about the DS18B20 1-Wire device features and capabilities, please refer to the Maxim Integrated datasheet for the device. https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
The Particle.io provides a method to display events and data to a Dashboard log that is associated with an active device. Since the Oak does not support serial output through the USB connector, this is a convenient and useful way to view your Oak device output. To take advantage of this functionality, you simply need to create an account on Particle.io, claim your Oak device there and make sure that it is seen and active on Particle.io. You can find more information for Particle.io here: https://www.particle.io/
Once you are setup on Particle.io, publishing data to the log is quite simple. The function Particle.publish()allows one to easily send events and data to the log.
Particle.publish("Temp (F)", tempFstring, 60, PRIVATE);
Where “Temp(F)“ is the event name and tempFstring is the actual temperature reading in string format.
You should see log entries with temperature like this.
For more information and other examples for how to use the Particle.publish function and other Particle device firmware Cloud functions, see https://docs.particle.io/reference/firmware/core/
1-Wire bus access and protocol is done by the function getTemp(). This is basically the standard DS18B20 example sketch. The only changes made to getTemp() are the addition of temperature conversion to Fahrenheit and modified return errors to provide additional info for any errors encountered by getTemp().
// OneWire DS18B20 temperature reader with conversion to degrees F float getTemp(){ // Returns the temperature from a single 1-Wire DS18S20 in DEG Fahrenheit byte data[12]; byte addr[8]; if ( !ds.search(addr)) { //no more sensors on chain, reset search //Serial.println("No more addresses."); ds.reset_search(); return -1000; } if ( OneWire::crc8( addr, 7) != addr[7]) { //Serial.println("CRC is not valid!"); return -2000; } if ( addr[0] != 0x10 && addr[0] != 0x28) { //Serial.print("Device is not recognized"); return -3000; } ds.reset(); ds.select(addr); ds.write(0x44,1); // start conversion, with parasite power on at the end byte present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for (int i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } ds.reset_search(); byte MSB = data[1]; byte LSB = data[0]; float tempRead = ((MSB << 8) | LSB); //using two's compliment float TemperatureSum = tempRead / 16; // Convert to degrees Fahrenheit TemperatureSum = TemperatureSum * 9 / 5 + 32; return TemperatureSum; } //END getTemp()
DS18B20_Pin defines the pin to use for the 1-Wire bus (DQ line). In this example it is set to pin 2 but can be changed to any pin that can tolerate being pulled up at power on.
The OakLEDpin, pin 1 is used to provide a visual output when temperature is being read.
sleepTimeS specifies the delay in seconds between readings. We don't actually sleep but rather simply delay a specified amount of time in seconds before that next temperature update. It's important to keep this relatively coarse as we don't want to flood Particle.io with constant updates to the log. For slow changing inputs, 30 seconds to 1 minute is about right but you can easily change this to suit your own needs.
/********************************************************************* Digistump Oak example reading the DS18B20 digital thermometer with periodic calls to particle.Publish() to log temperature readings. Requires: * Particle.io account to facilitate temperature output. * Digistump Oak with current firmware and active on particle.io * DS18B20 OneWire temperature probe * 4.7K ohm resistor * OneWire library with ESP8266 support Does: * Periodic temperature reads - frequency controlled by sleepTimeS * Publishes readings to particle.io ********************************************************************** */ #include <OneWire.h> // Using OneWire lib from the Oak package int DS18S20_Pin = 2; // DS18S20 Signal on pin 2 int OakLEDpin = 1; // Oak onboard LED pin 1 int sleepTimeS = 30; // 30 seconds - adjust as needed float tempF = 0; // Temperature in degrees F char tempFstring[6]; // Used to store a temperature value as a string //Temperature chip i/o OneWire ds(DS18S20_Pin); void setup(void) { pinMode(OakLEDpin, OUTPUT); digitalWrite(OakLEDpin,HIGH); // Turn on onboard LED Particle.publish("Oak Setup", "Started", 60, PRIVATE); if (!ds.reset()) { Particle.publish("Oak Setup", "DS18B20 not found", 60, PRIVATE); } else { Particle.publish("Oak Setup", "DS18B20 present", 60, PRIVATE); // Discard first reading (sometimes in error after power up) tempF = getTemp(); // Ignore this one delay(1000); tempF = getTemp(); // Use this reading sprintf(tempFstring, "%d", (int)tempF); // Convert to string Particle.publish("Temp (F)", tempFstring, 60, PRIVATE); } Particle.publish("Oak Setup", "Complete", 60, PRIVATE); delay(1000); // Pluse stretch onboard LED digitalWrite(OakLEDpin,LOW); } //END setup()
Once we enter loop() the example sketch continues to read temperature from the DS18B20 and publishes the reading and/or errors to the Particle.io Dashboard log. The Oak onboard LED is simply used to provide a visual (local display) of activity. There is a user specified delay between each call to getTemp() to provide course updates to Particle.io.
void loop(void) { // Get DS18B20 device temperature readings a publish to Particle.io Dashboard log. digitalWrite(OakLEDpin,HIGH); // Turn on onboard LED tempF = getTemp(); sprintf(tempFstring, "%d", (int)tempF); // Convert to string // Check for errors (-1000 no device, -2000 CRC error, -3000 device not recognized) if(tempF <= -1000) { Particle.publish("DS18B20 Error", tempFstring, 60, PRIVATE); } else { Particle.publish("Temp (F)", tempFstring, 60, PRIVATE); } digitalWrite(OakLEDpin,LOW); // Turn off onboard LED // Delay sleepTimeS number of seconds before next read for(int i=0; i<sleepTimeS; i++) { delay(1000); // This delay * sleepTimes slows updates to particle.io log } } //END loop()
In this lesson we demonstrated how to connect a 1-Wire device to the Oak and read temperature data from a 1-Wire DS18B20 digital thermometer. We also demonstrated how to publish that data to the Particle.io Dashboard log. We hope that you found this lesson to be both useful and informative. If you would like to explore the 1-Wire bus protocols and other 1-Wire devices, a simple search should yield plenty of useful information, tutorials and examples. As for the DS18B20 Digital Thermometer, why not drop a waterproof version of the device into your pool and have it tell you when the water is fine or simply use it as the basis for a home grown weather station.