Add DS18B20 example
This commit is contained in:
parent
64eb36ba85
commit
21a981a44f
|
|
@ -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 <RFM69.h> //https://www.github.com/lowpowerlab/rfm69
|
||||
#include <RFM69_ATC.h> //included in RFM69
|
||||
#include <LowPower.h> //https://www.github.com/lowpowerlab/lowpower
|
||||
#include <OneWire.h> //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;
|
||||
}
|
||||
Loading…
Reference in New Issue