From 21a981a44f4beb99b308327b740deedffcb09a51 Mon Sep 17 00:00:00 2001 From: Felix Rusu Date: Mon, 18 May 2020 14:30:34 -0400 Subject: [PATCH] Add DS18B20 example --- Examples/DS18B20_Sensor/DS18B20_Sensor.ino | 253 +++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 Examples/DS18B20_Sensor/DS18B20_Sensor.ino diff --git a/Examples/DS18B20_Sensor/DS18B20_Sensor.ino b/Examples/DS18B20_Sensor/DS18B20_Sensor.ino new file mode 100644 index 0000000..819bfca --- /dev/null +++ b/Examples/DS18B20_Sensor/DS18B20_Sensor.ino @@ -0,0 +1,253 @@ +// ********************************************************************************** +// Sample RFM69 sender/node sketch for DS18B20 +// Periodically wakes up, reads the sensor, and goes back to sleep +// Compensates sleep time for the conversion time which can take up to 700ms on this sensor +// +// ************************************ +// **** IMPORTANT NOTES ON DS18B20 **** +// ************************************ +// +// DS18B20 requires a pullup on the data pin (2.2K-10K) +// Adjust DS18B20 read resolution based on required accuracy and conversion time +// Radio & MCU are WDT slept during conversion but DS18B20 still uses ~1mA during conversion +// Conversion times: ~95ms @9bit, ~180ms @10bit, 370ms @11bit, ~650ms @12bit) +// ********************************************************************************** +// Copyright Felix Rusu 2020, http://www.LowPowerLab.com/contact +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +//********************************************************************************************* +#include //https://www.github.com/lowpowerlab/rfm69 +#include //included in RFM69 +#include //https://www.github.com/lowpowerlab/lowpower +#include //https://github.com/PaulStoffregen/OneWire +//********************************************************************************************* +#define DALLAS_PIN 7 +#define DALLAS_RESOLUTION 12 +#define TRANSMITPERIOD 5000 //read and send data every this many ms (WDT sleep) +//********************************************************************************************* +#define NODEID 789 +#define NETWORKID 100 +#define GATEWAYID 1 //as a rule of thumb the gateway ID should always be 1 +#define FREQUENCY RF69_915MHZ //match the RFM69 version! Others: RF69_433MHZ, RF69_868MHZ +//#define FREQUENCY_EXACT 916000000 +#define ENCRYPTKEY "sampleEncryptKey" //same 16 characters on all nodes, comment this line to disable encryption +#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW! +//********************************************************************************************* +#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL +#define ATC_RSSI -90 +//********************************************************************************************* +#define SERIAL_BAUD 115200 //comment out to turn off serial output +#ifdef SERIAL_BAUD + #define DEBUG(input) Serial.print(input) + #define DEBUGln(input) Serial.println(input) + #define DEBUGHEX(x) Serial.print(x, HEX) + #define DEBUGflush() Serial.flush() +#else + #define DEBUG(input) + #define DEBUGln(input) + #define DEBUGflush() + #define DEBUGHEX(x) +#endif + +#define LED_HIGH digitalWrite(LED_BUILTIN, HIGH) +#define LED_LOW digitalWrite(LED_BUILTIN, LOW) +//********************************************************************************************* +#ifdef ENABLE_ATC + RFM69_ATC radio; +#else + RFM69 radio; +#endif + +int HighByte, LowByte, TReading, SignBit, Tc_100, Fh_100, Whole, Fract; +char buff[61]; //max packet size is 61 with encryption enabled +char Fstr[10]; +byte buffLen; +float fahrenheit, celsius; +uint32_t time=0, now=0, LASTPACKETTIME=-1; +uint16_t conversionTime=0; + +void setup() { +#ifdef SERIAL_BAUD + Serial.begin(SERIAL_BAUD); +#endif + pinMode(LED_BUILTIN, OUTPUT); + + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HCW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif +#ifdef FREQUENCY_EXACT + radio.setFrequency(FREQUENCY_EXACT); //set frequency to some custom frequency +#endif +#ifdef ENCRYPTKEY + radio.encrypt(ENCRYPTKEY); +#endif + +#ifdef ENABLE_ATC + radio.enableAutoPower(ATC_RSSI); +#endif + radio.sleep(); + sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); + DEBUGln(buff); +} + +void loop() { + fahrenheit = 0; + celsius = 0; + getTemp(DALLAS_PIN, DALLAS_RESOLUTION); + + if (fahrenheit !=0) { + dtostrf(fahrenheit, 3,2, Fstr); + sprintf(buff, "F:%s", Fstr); + buffLen = strlen(buff); + + LED_HIGH; + DEBUG("Sending '"); DEBUG(buff); DEBUG("' .. "); + if (radio.sendWithRetry(GATEWAYID, buff, buffLen)) + DEBUG("ok!"); + else DEBUG("nok..."); + radio.sleep(); + DEBUGln(); + LED_LOW; + } + else DEBUGln("Nothing to send: fahrenheit=0"); + + DEBUGflush(); + LowPower.longPowerDown(TRANSMITPERIOD - conversionTime); + DEBUGln("WAKEUP"); +} + +void getTemp(byte dataPin, byte resolution) { + byte dsaddr[8]; // Device identifier + OneWire myds(dataPin); + getFirstDSAddr(myds,dsaddr); + conversionTime=0; + + DEBUG(F("DallasAddress:")); + for (int j=0;j<8;j++) { + if (dsaddr[j] < 16) DEBUG('0'); + DEBUGHEX(dsaddr[j]); + } + DEBUGln(); + getdstemp(myds, dsaddr, resolution); +} + +void getFirstDSAddr(OneWire myds, byte firstAddr[]){ + byte i; + byte present = 0; + byte addr[8]; + float celsius, fahrenheit; + int length = 8; + + //DEBUGln("Looking for 1-Wire devices..."); + while(myds.search(addr)) { + for( i = 0; i < 8; i++) firstAddr[i]=addr[i]; + if (OneWire::crc8( addr, 7) != addr[7]) { + DEBUGln("FAIL:INVALID CRC"); + return; + } + return; + } +} + +float getdstemp(OneWire myds, byte addr[8], byte resolution) { + byte present = 0; + byte data[12]; + byte type_s; + uint32_t starttime=millis(); + uint32_t sleeptime=0; + + switch (addr[0]) { + case 0x10: + //DEBUGln(F(" Chip = DS18S20")); // or old DS1820 + type_s = 1; + break; + case 0x28: + //DEBUGln(F(" Chip = DS18B20")); + type_s = 0; + break; + case 0x22: + //DEBUGln(F(" Chip = DS1822")); + type_s = 0; + break; + default: + DEBUGln(F("Device is not a DS18x20 family device.")); + } + + // Set reading resolution + byte resbyte = 0x1F; + if (resolution == 12) resbyte = 0x7F; + else if (resolution == 11) resbyte = 0x5F; + else if (resolution == 10) resbyte = 0x3F; + + // Set configuration + myds.reset(); + myds.select(addr); + myds.write(0x4E); // Write scratchpad + myds.write(0); // TL + myds.write(0); // TH + myds.write(resbyte); // Configuration Register + myds.write(0x48); // Copy Scratchpad + myds.reset(); + myds.select(addr); + myds.write(0x44,1); // start conversion, with parasite power on at the end + + // Sleep while waiting for conversion to complete + while (!myds.read()) { + LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + sleeptime+=15; + } + + conversionTime = millis() - starttime+sleeptime; + DEBUG("Conversion took: "); DEBUG(conversionTime); DEBUGln(" ms"); + + present = myds.reset(); + myds.select(addr); + myds.write(0xBE); // Read Scratchpad + + DEBUG("Raw Scratchpad Data: "); + for (byte i = 0; i < 9; i++) { // we need 9 bytes + data[i] = myds.read(); + DEBUGHEX(data[i]); + } + DEBUGln(); + + // convert the data to actual temperature + unsigned int raw = (data[1] << 8) | data[0]; + if (type_s) { + raw = raw << 3; // 9 bit resolution default + if (data[7] == 0x10) { + // count remain gives full 12 bit resolution + raw = (raw & 0xFFF0) + 12 - data[6]; + } else { + byte cfg = (data[4] & 0x60); + // default is 12 bit resolution: ~650 ms conversion time + if (cfg == 0x00) raw = raw << 3; // 9 bit resolution: ~95ms + else if (cfg == 0x20) raw = raw << 2; // 10 bit res: ~180ms + else if (cfg == 0x40) raw = raw << 1; // 11 bit res: ~370ms + } + } + + celsius = (float)raw / 16.0; + fahrenheit = celsius * 1.8 + 32.0; + return conversionTime; +}