diff --git a/DHTxx.cpp b/DHTxx.cpp deleted file mode 100644 index 6865c29..0000000 --- a/DHTxx.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// DHT11 & 22 sensor interface extracted from... -// 2009-02-13 http://opensource.org/licenses/mit-license.php - -#include "DHTxx.h" -// #include -#include - -#define DEBUG_DHT 0 // add code to send info over the serial port of non-zero - -DHTxx::DHTxx (byte pinNum) : pin (pinNum) { - digitalWrite(pin, HIGH); -} - -bool DHTxx::reading (int& temp, int &humi, bool precise) { - pinMode(pin, OUTPUT); - delay(10); // wait for any previous transmission to end - digitalWrite(pin, LOW); - delay(18); - - cli(); - - digitalWrite(pin, HIGH); - delayMicroseconds(30); - pinMode(pin, INPUT); - - byte data[6]; // holds a few start bits and then the 5 real payload bytes -#if DEBUG_DHT - static byte times[48]; - memset(times, 0, sizeof times); -#endif - - // each bit is a high edge followed by a var-length low edge - for (byte i = 7; i < 48; ++i) { - // wait for the high edge, then measure time until the low edge - byte timer; - for (byte j = 0; j < 2; ++j) - for (timer = 0; timer < 250; ++timer) - if (digitalRead(pin) != j) - break; -#if DEBUG_DHT - times[i] = timer; -#endif - // if no transition was seen, return - if (timer >= 250) { - sei(); - return false; - } - // collect each bit in the data buffer - byte offset = i / 8; - data[offset] <<= 1; - data[offset] |= timer > 7; - } - - sei(); - -#if DEBUG_DHT - Serial.print("DHT"); - for (byte i = 7; i < 48; ++i) { - Serial.print(' '); - Serial.print(times[i]); - } - Serial.println(); - Serial.print("HEX"); - for (byte i = 0; i < sizeof data; ++i) { - Serial.print(' '); - Serial.print(data[i], HEX); - } - Serial.print(" : "); - byte s = data[1] + data[2] + data[3] + data[4]; - Serial.print(s, HEX); - Serial.println(); -#endif - - byte sum = data[1] + data[2] + data[3] + data[4]; - if (sum != data[5]) - return false; - - humi = precise ? (data[1] << 8) | data[2] : 10 * data[1]; - - word t = precise ? ((data[3] & 0x7F) << 8) | data[4] : 10 * data[3]; - temp = data[3] & 0x80 ? - t : t; - - return true; -} diff --git a/DHTxx.h b/DHTxx.h deleted file mode 100644 index ecb1efd..0000000 --- a/DHTxx.h +++ /dev/null @@ -1,20 +0,0 @@ -// DHT11 & 22 sensor interface extracted from... -// 2009-02-13 http://opensource.org/licenses/mit-license.php - -#ifndef DHTXX_H -#define DHTXX_H -#include // Arduino 1.0 -#include -#include - -/// Interface for the DHT11 and DHT22 sensors, does not use floating point -class DHTxx { - byte pin; -public: - DHTxx (byte pinNum); - /// Results are returned in tenths of a degree and percent, respectively. - /// Set "precise" to true for the more accurate DHT21 and DHT22 sensors. - bool reading (int& temp, int &humi, bool precise =false); -}; - -#endif // DHTXX_H diff --git a/DavisRFM69.cpp b/DavisRFM69.cpp index d784782..797ec4b 100644 --- a/DavisRFM69.cpp +++ b/DavisRFM69.cpp @@ -1,9 +1,10 @@ // Driver implementation for HopeRF RFM69W/RFM69HW, Semtech SX1231/1231H used for // compatibility with the frequency hopped, spread spectrum signals from a Davis Instrument -// wireless Integrated Sensor Suite (ISS) +// wireless Integrated Sensor Suite (ISS). This library has been tested against both the +// Moteino from LowPowerLab, and an ESP-12E wired directly to an RFM69W module. // // This is part of the DavisRFM69 library from https://github.com/dekay/DavisRFM69 -// (C) DeKay 2014 dekaymail@gmail.com +// (C) DeKay 2014-2015 dekaymail@gmail.com // // As I consider this to be a derived work for now from the RFM69W library from LowPowerLab, // it is released under the same Creative Commons Attrib Share-Alike License @@ -18,7 +19,7 @@ volatile uint8_t DavisRFM69::DATA[DAVIS_PACKET_LEN]; volatile uint8_t DavisRFM69::_mode; // current transceiver state volatile bool DavisRFM69::_packetReceived = false; volatile uint8_t DavisRFM69::CHANNEL = 0; -volatile int16_t DavisRFM69::RSSI; // RSSI measured immediately after payload reception +volatile int16_t DavisRFM69::RSSI; // RSSI measured after packet data read DavisRFM69* DavisRFM69::selfPointer; void DavisRFM69::initialize() @@ -31,13 +32,13 @@ void DavisRFM69::initialize() /* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_19200}, /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_4800}, // Davis uses a deviation of 4.8 kHz on Rx /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_4800}, - /* 0x07 to 0x09 are REG_FRFMSB to LSB. No sense setting them here. Done in main routine. + // 0x07 to 0x09 are REG_FRFMSB to LSB. No sense setting them here. Done in main routine. /* 0x0B */ { REG_AFCCTRL, RF_AFCCTRL_LOWBETA_OFF }, // TODO: Should use LOWBETA_ON, but having trouble getting it working // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm // +17dBm and +20dBm are possible on RFM69HW // +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**) // +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)** - // +20dBpaym formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) + // +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111}, ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, //over current protection (default is 95mA) /* 0x18 */ { REG_LNA, RF_LNA_ZIN_50 | RF_LNA_GAINSELECT_AUTO}, // Not sure which is correct! @@ -57,7 +58,7 @@ void DavisRFM69::initialize() /* 0x2a & 0x2b RegRxTimeout1 and 2, respectively */ /* 0x2c RegPreambleMsb - use zero default */ /* 0x2d */ { REG_PREAMBLELSB, 4 }, // Davis has four preamble bytes 0xAAAAAAAA - /* 0x2e */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_2 }, // Allow a couple erros in the sync word + /* 0x2e */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_2 }, // Allow a couple errors in the sync word /* 0x2f */ { REG_SYNCVALUE1, 0xcb }, // Davis ISS first sync byte. http://madscientistlabs.blogspot.ca/2012/03/first-you-get-sugar.html /* 0x30 */ { REG_SYNCVALUE2, 0x89 }, // Davis ISS second sync byte. /* 0x31 - 0x36 REG_SYNCVALUE3 - 8 not used */ @@ -78,22 +79,30 @@ void DavisRFM69::initialize() pinMode(_slaveSelectPin, OUTPUT); SPI.begin(); + // Is the RFM69 module alive? do writeReg(REG_SYNCVALUE1, 0xaa); while (readReg(REG_SYNCVALUE1) != 0xaa); do writeReg(REG_SYNCVALUE1, 0x55); while (readReg(REG_SYNCVALUE1) != 0x55); for (uint8_t i = 0; CONFIG[i][0] != 255; i++) writeReg(CONFIG[i][0], CONFIG[i][1]); - setHighPower(_isRFM69HW); //called regardless if it's a RFM69W or RFM69HW + setHighPower(_isRFM69HW); // Called regardless if it's a RFM69W or RFM69HW setMode(RF69_MODE_STANDBY); while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady + pinMode(RF69_IRQ_PIN, INPUT); attachInterrupt(_interruptNum, DavisRFM69::isr0, RISING); + rcCalibration(); // Perform the coarse cal in case we haven't done POR in a long time + selfPointer = this; } void DavisRFM69::interruptHandler() { - RSSI = readRSSI(); // Read up front when it is most likely the carrier is still up +// See https://github.com/esp8266/Arduino/issues/1020 for how user libraries with +// interrupts can crash the ESP. Better to be safe than sorry for now. +#if defined(ESP8266) + ETS_GPIO_INTR_DISABLE(); +#endif if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) { setMode(RF69_MODE_STANDBY); @@ -104,7 +113,11 @@ void DavisRFM69::interruptHandler() { _packetReceived = true; unselect(); // Unselect RFM69 module, enabling interrupts + RSSI = readRSSI(); // RSSI of last received packet remains available after reception } +#if defined(ESP8266) + ETS_GPIO_INTR_ENABLE(); +#endif } bool DavisRFM69::canSend() @@ -155,12 +168,18 @@ void DavisRFM69::setChannel(uint8_t channel) { CHANNEL = channel; if (CHANNEL > DAVIS_FREQ_TABLE_LENGTH - 1) CHANNEL = 0; + setMode(RF69_MODE_STANDBY); writeReg(REG_FRFMSB, pgm_read_byte(&FRF[CHANNEL][0])); writeReg(REG_FRFMID, pgm_read_byte(&FRF[CHANNEL][1])); writeReg(REG_FRFLSB, pgm_read_byte(&FRF[CHANNEL][2])); receiveBegin(); } +void DavisRFM69::waitHere() +{ + _packetReceived = false; +} + void DavisRFM69::hop() { setChannel(++CHANNEL); @@ -202,7 +221,6 @@ void DavisRFM69::setFrequency(uint32_t FRF) void DavisRFM69::setMode(uint8_t newMode) { - //Serial.println(newMode); if (newMode == _mode) return; switch (newMode) { @@ -229,11 +247,9 @@ void DavisRFM69::setMode(uint8_t newMode) // we are using packet mode, so this check is not really needed // but waiting for mode ready is necessary when going from sleep because the FIFO may not // be immediately available from previous mode - while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady + while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady _mode = newMode; - //Serial.print("Mode set to "); - //Serial.println(_mode); } void DavisRFM69::sleep() { @@ -289,9 +305,13 @@ void DavisRFM69::writeReg(uint8_t addr, uint8_t value) // Select the transceiver void DavisRFM69::select() { noInterrupts(); - // Save current SPI settings +#if defined(ARDUINO_ARCH_AVR) + // Save current SPI settings on Moteino's. That board has a SPI flash + // as well as a SPI interface to the RFM69, so you need to save the old + // SPI config before talking to the RFM69. We aren't doing this on the ESP. _SPCR = SPCR; _SPSR = SPSR; +#endif // Set RFM69 SPI settings SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); @@ -302,9 +322,12 @@ void DavisRFM69::select() { // Unselect the transceiver chip void DavisRFM69::unselect() { digitalWrite(_slaveSelectPin, HIGH); - // Restore SPI settings to what they were before talking to RFM69 + // Restore SPI settings on Moteino to what they were before talking to RFM69. + // See comment in DavisRFM69::select() for why. +#if defined(ARDUINO_ARCH_AVR) SPCR = _SPCR; SPSR = _SPSR; +#endif interrupts(); } @@ -341,9 +364,9 @@ void DavisRFM69::readAllRegs() unselect(); Serial.print(regAddr, HEX); - Serial.print(" - "); + Serial.print(F(" - ")); Serial.print(regVal,HEX); - Serial.print(" - "); + Serial.print(F(" - ")); Serial.println(regVal,BIN); } unselect(); @@ -353,7 +376,7 @@ uint8_t DavisRFM69::readTemperature(uint8_t calFactor) // Returns centigrade { setMode(RF69_MODE_STANDBY); writeReg(REG_TEMP1, RF_TEMP1_MEAS_START); - while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) Serial.print('*'); + while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) Serial.print(F("*")); return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; //'complement'corrects the slope, rising temp = rising val } // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction diff --git a/DavisRFM69.h b/DavisRFM69.h index 576bdcb..38d424e 100644 --- a/DavisRFM69.h +++ b/DavisRFM69.h @@ -1,9 +1,10 @@ // Driver definition for HopeRF RFM69W/RFM69HW, Semtech SX1231/1231H used for // compatibility with the frequency hopped, spread spectrum signals from a Davis Instrument -// wireless Integrated Sensor Suite (ISS) +// wireless Integrated Sensor Suite (ISS). This library has been tested against both the +// Moteino from LowPowerLab, and an ESP-12E wired directly to an RFM69W module. // // This is part of the DavisRFM69 library from https://github.com/dekay/DavisRFM69 -// (C) DeKay 2014 dekaymail@gmail.com +// (C) DeKay 2014-2016 dekaymail@gmail.com // // As I consider this to be a derived work from the RFM69W library from LowPowerLab, // it is released under the same Creative Commons Attrib Share-Alike License @@ -18,7 +19,7 @@ // America) and EU frequencies are defined at this time. Australia and New // Zealand are placeholders. Note however that the frequencies for AU and NZ // are not known at this time. -#define DAVIS_FREQS_US +//#define DAVIS_FREQS_US //#define DAVIS_FREQS_EU //#define DAVIS_FREQS_AU //#define DAVIS_FREQS_NZ @@ -26,9 +27,10 @@ #include #include //assumes Arduino IDE v1.0 or greater -#define DAVIS_PACKET_LEN 10 // ISS has fixed packet length of 10 bytes, including CRC and retransmit CRC -#define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on ATmega328 - +#define DAVIS_PACKET_LEN 10 // ISS has fixed packet length of 10 bytes, + // including CRC and retransmit CRC +#define RF69_SPI_CS SS // SS is the SPI slave select pin + // For instance D10 on ATmega328 // INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on ATmega644/1284 it's D2) #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) #define RF69_IRQ_PIN 2 @@ -39,6 +41,14 @@ #elif defined(__AVR_ATmega32U4__) #define RF69_IRQ_PIN 3 #define RF69_IRQ_NUM 0 +#elif defined(ESP8266) + // ESP interrupt number and pin number are a direct relation + // See http://www.esp8266.com/viewtopic.php?f=32&t=4694 + #define RF69_IRQ_PIN 5 + #define RF69_IRQ_NUM 5 +#elif defined(ARDUINO_ARCH_STM32F1) + #define RF69_IRQ_PIN PA0 + #define RF69_IRQ_NUM 0 #endif #define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access @@ -109,6 +119,7 @@ class DavisRFM69 { static volatile uint8_t hopIndex; void setChannel(uint8_t channel); void hop(); + void waitHere(); uint16_t crc16_ccitt(volatile uint8_t *buf, uint8_t len, uint16_t initCrc = 0); void initialize(); diff --git a/README.md b/README.md index f2d1119..a20ac2d 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ This library is in its early stages but I wanted to get something functional out This library has been developed on a Moteino R3 [(see here for the new R4 version)](http://lowpowerlab.com/shop/Moteino-R4) fitted with an RFM69W (Semtech SX1231/SX1231) transceiver module. +Support has also been added for ESP8266 modules. The ISSRx_ESP example was developed on a NodeMCU ESP-12E based module connected directly to an RFM69W transceiver. See the code for a description of the hookup. + ##Installation [See this blog post](http://madscientistlabs.blogspot.ca/2014/02/build-your-own-davis-weather-station_17.html) where I combines ISS Reception capabilities along with hookups to sensors for indoor monitoring of temperature, pressure, and humidity. Note that this code no longer requires the installation of [LowPowerLab's RFM69 library](https://github.com/LowPowerLab/RFM69) discussed in that post, but you will still need to install his [SPIFlash library](https://github.com/LowPowerLab/SPIFlash). Since that post was written, I have also added support for the DS3231 Real Time Clock chip. To get this to work from a software perspective, you will need [this RTC library](https://github.com/mizraith/RTClib) in your Arduino "libraries" folder. @@ -37,9 +39,9 @@ fitted with an RFM69W (Semtech SX1231/SX1231) transceiver module. Reception quality has been greatly improved in this release. ~~There looks to be a bug where the hop-ahead code has broken, but I expect that will be fixed soon~~ I am getting around 99% good packets now. Please let me know if you find any issues. ##Sample Usage -[VP2](https://github.com/dekay/DavisRFM69/blob/master/Examples/VP2/VP2.ino) is an emulation of the Davis Vantage Pro2 console that works with Sandaysoft's Cumulus weather software. As noted above, you will need [this RTC library](https://github.com/mizraith/RTClib) in your Arduino "libraries" folder. +[ISSRx](https://github.com/dekay/DavisRFM69/blob/master/examples/ISSRx/ISSRx.ino) is an example of sniffing the wireless packets out of the air and streaming them out the serial port. A version for the ESP8266 is in progress. -The ISSRx Example hasn't been updated in a while and may be broken. Just so you know... +[VP2](https://github.com/dekay/DavisRFM69/blob/master/Examples/VP2/VP2.ino) is an emulation of the Davis Vantage Pro2 console that works with Sandaysoft's Cumulus weather software. As noted above, you will need [this RTC library](https://github.com/mizraith/RTClib) in your Arduino "libraries" folder. Unfortunately, this example will be broken right now as I've concentrated on the ESP8266 for now. ##Blog Writeups [ISS Reception](http://madscientistlabs.blogspot.ca/2014/01/more-than-one-way-to-skin-cat.html), along with the best GIF ever. @@ -51,4 +53,4 @@ I started playing around with my VP2 Wireless console when I discovered its litt I learned a lot by doing this and I like to think that opening up the console has been an overall win for Davis. I also consider this to be MY data, and I want access to it ([Davis' failed attempts to shut this down notwithstanding](http://meteo.annoyingdesigns.com/DavisSPI.pdf)). -And, just because. \ No newline at end of file +And, just because. diff --git a/Examples/ISSRx/ISSRx.ino b/examples/ISSRx/ISSRx.ino similarity index 71% rename from Examples/ISSRx/ISSRx.ino rename to examples/ISSRx/ISSRx.ino index 273685b..cea49bc 100644 --- a/Examples/ISSRx/ISSRx.ino +++ b/examples/ISSRx/ISSRx.ino @@ -5,7 +5,7 @@ // functionality of the LowPowerLabs Gateway sketch, on which this code is based. // // This is part of the DavisRFM69 library from https://github.com/dekay/DavisRFM69 -// (C) DeKay 2014 dekaymail@gmail.com +// (C) DeKay 2014-2016 dekaymail@gmail.com // Example released under the MIT License (http://opensource.org/licenses/mit-license.php) // Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ // @@ -24,6 +24,7 @@ #define LED 9 // Moteinos have LEDs on D9 #define SERIAL_BAUD 19200 #define PACKET_INTERVAL 2555 +#define DEBUG true boolean strmon = false; // Print the packet when received? DavisRFM69 radio; @@ -39,46 +40,49 @@ void setup() { #endif Serial.println(F("Waiting for signal in region defined in DavisRFM69.h")); if (flash.initialize()) - Serial.println("SPI Flash Init OK!"); + Serial.println(F("SPI Flash Init OK!")); else - Serial.println("SPI Flash Init FAIL! (is chip present?)"); + Serial.println(F("SPI Flash Init FAIL! (is chip present?)")); } unsigned long lastRxTime = 0; byte hopCount = 0; +boolean goodCrc = false; +int16_t goodRssi = -999; + void loop() { //process any serial input if (Serial.available() > 0) { char input = Serial.read(); - if (input == 'r') //d=dump all register values + if (input == 'r') //r=dump all register values { radio.readAllRegs(); Serial.println(); } if (input == 'd') //d=dump flash area { - Serial.println("Flash content:"); + Serial.println(F("Flash content:")); int counter = 0; while(counter<=256){ Serial.print(flash.readByte(counter++), HEX); - Serial.print('.'); + Serial.print(F(".")); } while(flash.busy()); Serial.println(); } if (input == 'e') { - Serial.print("Erasing Flash chip ... "); + Serial.print(F("Erasing Flash chip ... ")); flash.chipErase(); while(flash.busy()); - Serial.println("DONE"); + Serial.println(F("Done")); } if (input == 'i') { - Serial.print("DeviceID: "); + Serial.print(F("DeviceID: ")); word jedecid = flash.readDeviceId(); Serial.println(jedecid, HEX); } @@ -86,11 +90,11 @@ void loop() { { byte temperature = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient byte fTemp = 1.8 * temperature + 32; // 9/5=1.8 - Serial.print( "Radio Temp is "); + Serial.print(F("Radio Temp is ")); Serial.print(temperature); - Serial.print("C, "); + Serial.print(F("C, ")); Serial.print(fTemp); //converting to F loses some resolution, obvious when C is on edge between 2 values (ie 26C=78F, 27C=80F) - Serial.println('F'); + Serial.println(F("F")); } } @@ -101,46 +105,71 @@ void loop() { packetStats.packetsReceived++; unsigned int crc = radio.crc16_ccitt(radio.DATA, 6); if ((crc == (word(radio.DATA[6], radio.DATA[7]))) && (crc != 0)) { + // This is a good packet + goodCrc = true; + goodRssi = radio.RSSI; packetStats.receivedStreak++; hopCount = 1; blink(LED,3); } else { + goodCrc = false; packetStats.crcErrors++; packetStats.receivedStreak = 0; } if (strmon) printStrm(); -#if 1 +#if DEBUG Serial.print(radio.CHANNEL); Serial.print(F(" - Data: ")); for (byte i = 0; i < DAVIS_PACKET_LEN; i++) { Serial.print(radio.DATA[i], HEX); Serial.print(F(" ")); - } - Serial.print(F(" RSSI: ")); - Serial.println(radio.RSSI); + } + Serial.print(F(" RSSI: ")); + Serial.println(radio.RSSI); + int freqError = radio.readReg(0x21) << 8 |radio.readReg(0x22); + Serial.print(F(" Freq error): ")); + Serial.println(freqError); +#endif + // If packet was received earlier than expected, that was probably junk. Don't hop. + // I use a simple heuristic for this. If the CRC is bad and the received RSSI is + // a lot less than the last known good RSSI, then don't hop. + if (goodCrc && (radio.RSSI < (goodRssi + 15))) { + lastRxTime = millis(); + radio.hop(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Hopped channel and ready to receive.")); #endif - // Whether CRC is right or not, we count that as reception and hop. - lastRxTime = millis(); - radio.hop(); + } else { + radio.waitHere(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Waiting here")); +#endif + } } // If a packet was not received at the expected time, hop the radio anyway - // in an attempt to keep up. Give up after 25 failed attempts. Keep track + // in an attempt to keep up. Give up after 4 failed attempts. Keep track // of packet stats as we go. I consider a consecutive string of missed // packets to be a single resync. Thx to Kobuki for this algorithm. if ((hopCount > 0) && ((millis() - lastRxTime) > (hopCount * PACKET_INTERVAL + 200))) { packetStats.packetsMissed++; if (hopCount == 1) packetStats.numResyncs++; - if (++hopCount > 25) hopCount = 0; + if (++hopCount > 4) hopCount = 0; radio.hop(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Hopped channel and ready to receive.")); +#endif } } void printStrm() { for (byte i = 0; i < DAVIS_PACKET_LEN; i++) { Serial.print(i); - Serial.print(" = "); + Serial.print(F(" = ")); Serial.print(radio.DATA[i], HEX); Serial.print(F("\n\r")); } diff --git a/examples/ISSRx_ESP/ISSRx_ESP.ino b/examples/ISSRx_ESP/ISSRx_ESP.ino new file mode 100644 index 0000000..2b8f948 --- /dev/null +++ b/examples/ISSRx_ESP/ISSRx_ESP.ino @@ -0,0 +1,159 @@ +// Sample usage of the DavisRFM69 library to sniff the packets from a Davis Instruments +// wireless Integrated Sensor Suite (ISS), demostrating compatibility between the RFM69 +// and the TI CC1020 transmitter used in that hardware. Packets received from the ISS are +// passes through to the serial port. This code retains some of the debugging +// functionality of the LowPowerLabs Gateway sketch, on which this code is based. +// +// This is part of the DavisRFM69 library from https://github.com/dekay/DavisRFM69 +// (C) DeKay 2014-2016 dekaymail@gmail.com +// Example released under the MIT License (http://opensource.org/licenses/mit-license.php) +// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ +// +// This program has been developed on an ESP-12E based NodeMCU module with an +// attached RFM69W transceiver module connected as follows: +// RFM69W ESP-12E NodeMCU +// MISO GPIO12 D6 +// MOSI GPIO13 D7 +// SCK GPIO14 D5 +// CS/SS GPIO15 D8 +// DIO0 GPIO5 D1 (Interrupt) +// +// Do NOT connect the Reset of the two together!!! Reset on the ESP8266 is active LOW and on +// the RFM69 it is active HIGH. +// +// See also https://github.com/esp8266/Arduino/blob/master/doc/reference.md +// and https://github.com/someburner/esp-rfm69 and +// http://www.cnx-software.com/2015/04/18/nodemcu-is-both-a-breadboard-friendly-esp8266-wi-fi-board-and-a-lua-based-firmware/ + +#include "DavisRFM69.h" +#include + +// NOTE: *** One of DAVIS_FREQS_US, DAVIS_FREQS_EU, DAVIS_FREQS_AU, or +// DAVIS_FREQS_NZ MUST be defined at the top of DavisRFM69.h *** + +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define SERIAL_BAUD 115200 +#define PACKET_INTERVAL 2555 +#define DEBUG true +boolean strmon = false; // Print the packet when received? + +DavisRFM69 radio; + +void setup() { + Serial.begin(SERIAL_BAUD); + delay(10); + radio.initialize(); + radio.setChannel(0); // Frequency / Channel is *not* set in the initialization. Do it right after. +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + Serial.println(F("Waiting for signal in region defined in DavisRFM69.h")); +} + +unsigned long lastRxTime = 0; +byte hopCount = 0; + +boolean goodCrc = false; +int16_t goodRssi = -999; + +void loop() { + //process any serial input + if (Serial.available() > 0) + { + char input = Serial.read(); + if (input == 'r') //r=dump all register values + { + radio.readAllRegs(); + Serial.println(); + } + if (input == 't') + { + byte temperature = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient + byte fTemp = 1.8 * temperature + 32; // 9/5=1.8 + Serial.print(F("Radio Temp is ")); + Serial.print(temperature); + Serial.print(F("C, ")); + Serial.print(fTemp); //converting to F loses some resolution, obvious when C is on edge between 2 values (ie 26C=78F, 27C=80F) + Serial.println(F("F")); + } + } + + // The check for a zero CRC value indicates a bigger problem that will need + // fixing, but it needs to stay until the fix is in. + // TODO Reset the packet statistics at midnight once I get my clock module. + if (radio.receiveDone()) { + packetStats.packetsReceived++; + unsigned int crc = radio.crc16_ccitt(radio.DATA, 6); + if ((crc == (word(radio.DATA[6], radio.DATA[7]))) && (crc != 0)) { + // This is a good packet + goodCrc = true; + goodRssi = radio.RSSI; + packetStats.receivedStreak++; + hopCount = 1; + } else { + goodCrc = false; + packetStats.crcErrors++; + packetStats.receivedStreak = 0; + } + + if (strmon) printStrm(); +#if DEBUG + // Debugging stuff + Serial.print(millis()); + Serial.print(F(": ")); + Serial.print(radio.CHANNEL); + Serial.print(F(" - Data: ")); + for (byte i = 0; i < DAVIS_PACKET_LEN; i++) { + Serial.print(radio.DATA[i], HEX); + Serial.print(F(" ")); + } + Serial.print(F(" RSSI: ")); + Serial.println(radio.RSSI); + int freqError = radio.readReg(0x21) << 8 |radio.readReg(0x22); + Serial.print(F(" Freq error): ")); + Serial.println(freqError); +#endif + // If packet was received earlier than expected, that was probably junk. Don't hop. + // I use a simple heuristic for this. If the CRC is bad and the received RSSI is + // a lot less than the last known good RSSI, then don't hop. + if (goodCrc && (radio.RSSI < (goodRssi + 15))) { + lastRxTime = millis(); + radio.hop(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Hopped channel and ready to receive.")); +#endif + } else { + radio.waitHere(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Waiting here")); +#endif + } + } + + // If a packet was not received at the expected time, hop the radio anyway + // in an attempt to keep up. Give up after 4 failed attempts. Keep track + // of packet stats as we go. I consider a consecutive string of missed + // packets to be a single resync. Thx to Kobuki for this algorithm. + if ((hopCount > 0) && ((millis() - lastRxTime) > (hopCount * PACKET_INTERVAL + 200))) { + packetStats.packetsMissed++; + if (hopCount == 1) packetStats.numResyncs++; + if (++hopCount > 4) hopCount = 0; + radio.hop(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Hopped channel and ready to receive.")); +#endif + } +} + +void printStrm() { + for (byte i = 0; i < DAVIS_PACKET_LEN; i++) { + Serial.print(i); + Serial.print(F(" = ")); + Serial.print(radio.DATA[i], HEX); + Serial.print(F("\n\r")); + } + Serial.print(F("\n\r")); +} diff --git a/examples/ISSRx_STM32F1/ISSRx_STM32F1.ino b/examples/ISSRx_STM32F1/ISSRx_STM32F1.ino new file mode 100644 index 0000000..f66f6fe --- /dev/null +++ b/examples/ISSRx_STM32F1/ISSRx_STM32F1.ino @@ -0,0 +1,157 @@ +// Sample usage of the DavisRFM69 library to sniff the packets from a Davis Instruments +// wireless Integrated Sensor Suite (ISS), demostrating compatibility between the RFM69 +// and the TI CC1020 transmitter used in that hardware. Packets received from the ISS are +// passes through to the serial port. This code retains some of the debugging +// functionality of the LowPowerLabs Gateway sketch, on which this code is based. +// +// This is part of the DavisRFM69 library from https://github.com/dekay/DavisRFM69 +// (C) DeKay 2014-2016 dekaymail@gmail.com +// Example released under the MIT License (http://opensource.org/licenses/mit-license.php) +// Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ +// +// This program has been tested on an STM32F103C8 module with an +// attached RFM69W transceiver module connected as follows: +// RFM69W STM32F103C8 +// MISO A6 +// MOSI A7 +// SCK A5 +// CS/SS A4 +// DIO0 A0 (Interrupt 0) +// +// Do NOT connect the Reset of the two together!!! Reset on the STM32F1 is active LOW and on +// the RFM69 it is active HIGH. +// +// See also http://wiki.stm32duino.com/index.php?title=Blue_Pill + +#include "DavisRFM69.h" +#include + +// NOTE: *** One of DAVIS_FREQS_US, DAVIS_FREQS_EU, DAVIS_FREQS_AU, or +// DAVIS_FREQS_NZ MUST be defined at the top of DavisRFM69.h *** + +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define SERIAL_BAUD 115200 +#define PACKET_INTERVAL 2555 +#define DEBUG true +boolean strmon = false; // Print the packet when received? + +DavisRFM69 radio; + +void setup() { + Serial.begin(SERIAL_BAUD); + delay(10); + radio.initialize(); + radio.setChannel(0); // Frequency / Channel is *not* set in the initialization. Do it right after. +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + Serial.println(F("Waiting for signal in region defined in DavisRFM69.h")); +} + +unsigned long lastRxTime = 0; +byte hopCount = 0; + +boolean goodCrc = false; +int16_t goodRssi = -999; + +void loop() { + //process any serial input + if (Serial.available() > 0) + { + char input = Serial.read(); + if (input == 'r') //r=dump all register values + { + radio.readAllRegs(); + Serial.println(); + } + if (input == 't') + { + byte temperature = radio.readTemperature(-1); // -1 = user cal factor, adjust for correct ambient + byte fTemp = 1.8 * temperature + 32; // 9/5=1.8 + Serial.print(F("Radio Temp is ")); + Serial.print(temperature); + Serial.print(F("C, ")); + Serial.print(fTemp); //converting to F loses some resolution, obvious when C is on edge between 2 values (ie 26C=78F, 27C=80F) + Serial.println(F("F")); + } + } + + // The check for a zero CRC value indicates a bigger problem that will need + // fixing, but it needs to stay until the fix is in. + // TODO Reset the packet statistics at midnight once I get my clock module. + if (radio.receiveDone()) { + packetStats.packetsReceived++; + unsigned int crc = radio.crc16_ccitt(radio.DATA, 6); + if ((crc == (word(radio.DATA[6], radio.DATA[7]))) && (crc != 0)) { + // This is a good packet + goodCrc = true; + goodRssi = radio.RSSI; + packetStats.receivedStreak++; + hopCount = 1; + } else { + goodCrc = false; + packetStats.crcErrors++; + packetStats.receivedStreak = 0; + } + + if (strmon) printStrm(); +#if DEBUG + // Debugging stuff + Serial.print(millis()); + Serial.print(F(": ")); + Serial.print(radio.CHANNEL); + Serial.print(F(" - Data: ")); + for (byte i = 0; i < DAVIS_PACKET_LEN; i++) { + Serial.print(radio.DATA[i], HEX); + Serial.print(F(" ")); + } + Serial.print(F(" RSSI: ")); + Serial.println(radio.RSSI); + int freqError = radio.readReg(0x21) << 8 |radio.readReg(0x22); + Serial.print(F(" Freq error): ")); + Serial.println(freqError); +#endif + // If packet was received earlier than expected, that was probably junk. Don't hop. + // I use a simple heuristic for this. If the CRC is bad and the received RSSI is + // a lot less than the last known good RSSI, then don't hop. + if (goodCrc && (radio.RSSI < (goodRssi + 15))) { + lastRxTime = millis(); + radio.hop(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Hopped channel and ready to receive.")); +#endif + } else { + radio.waitHere(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Waiting here")); +#endif + } + } + + // If a packet was not received at the expected time, hop the radio anyway + // in an attempt to keep up. Give up after 4 failed attempts. Keep track + // of packet stats as we go. I consider a consecutive string of missed + // packets to be a single resync. Thx to Kobuki for this algorithm. + if ((hopCount > 0) && ((millis() - lastRxTime) > (hopCount * PACKET_INTERVAL + 200))) { + packetStats.packetsMissed++; + if (hopCount == 1) packetStats.numResyncs++; + if (++hopCount > 4) hopCount = 0; + radio.hop(); +#if DEBUG + Serial.print(millis()); + Serial.println(F(": Hopped channel and ready to receive.")); +#endif + } +} + +void printStrm() { + for (byte i = 0; i < DAVIS_PACKET_LEN; i++) { + Serial.print(i); + Serial.print(F(" = ")); + Serial.print(radio.DATA[i], HEX); + Serial.print(F("\n\r")); + } + Serial.print(F("\n\r")); +} diff --git a/Examples/VP2/VP2.ino b/examples/VP2/VP2.ino similarity index 100% rename from Examples/VP2/VP2.ino rename to examples/VP2/VP2.ino