add listenModeSleep() + example
This commit is contained in:
parent
1bc4b02f22
commit
64eb36ba85
|
|
@ -0,0 +1,142 @@
|
||||||
|
// **********************************************************************************
|
||||||
|
// Sample RFM69 sender/node sketch with radio listen mode sleep
|
||||||
|
// Saves additional 2-3uA over WDT sleep
|
||||||
|
// **********************************************************************************
|
||||||
|
// 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>
|
||||||
|
#include <RFM69_ATC.h>
|
||||||
|
#include <LowPower.h>
|
||||||
|
#include <PString.h> //easy string manipulator: http://arduiniana.org/libraries/pstring/
|
||||||
|
//*********************************************************************************************
|
||||||
|
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************
|
||||||
|
//*********************************************************************************************
|
||||||
|
#define NODEID 123 //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
|
||||||
|
#define NETWORKID 100 //the same on all nodes that talk to each other (range up to 255)
|
||||||
|
#define GATEWAYID 1
|
||||||
|
#define FREQUENCY RF69_915MHZ //match the RFM69 version! Others: RF69_433MHZ, RF69_868MHZ
|
||||||
|
//#define FREQUENCY_EXACT 916000000
|
||||||
|
#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
|
||||||
|
#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
|
||||||
|
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL
|
||||||
|
#define ATC_RSSI -90
|
||||||
|
// **********************************************************************************
|
||||||
|
//to avoid the buggy listen mode high resolution timer TRANSMITPERIOD should always be > 262ms
|
||||||
|
#define TRANSMITPERIOD 3000 //sleep time in ms
|
||||||
|
//#define WDTSLEEP //uncomment to sleep with WDT instead (compare sleep currents!)
|
||||||
|
// **********************************************************************************
|
||||||
|
#define SERIAL_EN //comment this out when deploying to an installed SM to save a few KB of sketch size
|
||||||
|
#define SERIAL_BAUD 115200
|
||||||
|
#ifdef SERIAL_EN
|
||||||
|
#define DEBUG(input) Serial.print(input)
|
||||||
|
#define DEBUGln(input) Serial.println(input)
|
||||||
|
#define DEBUGFlush() Serial.flush()
|
||||||
|
#else
|
||||||
|
#define DEBUG(input)
|
||||||
|
#define DEBUGln(input)
|
||||||
|
#define DEBUGFlush()
|
||||||
|
#endif
|
||||||
|
// **********************************************************************************
|
||||||
|
#ifdef ENABLE_ATC
|
||||||
|
RFM69_ATC radio;
|
||||||
|
#else
|
||||||
|
RFM69 radio;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char buff[61]; //61 max payload for radio
|
||||||
|
PString Pbuff(buff, sizeof(buff));
|
||||||
|
// **********************************************************************************
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
#ifdef SERIAL_EN
|
||||||
|
Serial.begin(SERIAL_BAUD);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!radio.initialize(FREQUENCY,NODEID,NETWORKID))
|
||||||
|
DEBUG("radio.init() FAIL");
|
||||||
|
else
|
||||||
|
DEBUG("radio.init() SUCCESS");
|
||||||
|
|
||||||
|
#ifdef IS_RFM69HW
|
||||||
|
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
|
||||||
|
|
||||||
|
Pbuff = F("Transmitting at ");
|
||||||
|
Pbuff.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
|
||||||
|
Pbuff.print(F("Mhz..."));
|
||||||
|
DEBUGln(buff);
|
||||||
|
|
||||||
|
#ifdef ENABLE_ATC
|
||||||
|
DEBUGln("RFM69_ATC Enabled (Auto Transmission Control)\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t packetCounter=0;
|
||||||
|
void loop() {
|
||||||
|
Pbuff = F("PACKET #");
|
||||||
|
Pbuff.print(packetCounter++);
|
||||||
|
DEBUGln(buff);
|
||||||
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
|
radio.sendWithRetry(GATEWAYID, buff, Pbuff.length());
|
||||||
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
|
DEBUGFlush();
|
||||||
|
|
||||||
|
#ifdef WDTSLEEP
|
||||||
|
radio.sleep();
|
||||||
|
LowPower.longPowerDown(TRANSMITPERIOD);
|
||||||
|
#else
|
||||||
|
if (TRANSMITPERIOD%262 && TRANSMITPERIOD > 262*2)
|
||||||
|
{
|
||||||
|
DEBUG("Sleeping "); DEBUGln(TRANSMITPERIOD-TRANSMITPERIOD%262-262); DEBUGFlush();
|
||||||
|
radio.listenModeSleep(TRANSMITPERIOD-TRANSMITPERIOD%262-262);
|
||||||
|
DEBUG("Sleeping "); DEBUGln(TRANSMITPERIOD%262 + 262); DEBUGFlush();
|
||||||
|
radio.listenModeSleep(TRANSMITPERIOD%262 + 262);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG("Sleeping "); DEBUGln(TRANSMITPERIOD); DEBUGFlush();
|
||||||
|
radio.listenModeSleep(TRANSMITPERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
//wakeup (must reinit)
|
||||||
|
radio.RFM69::initialize(FREQUENCY,NODEID,NETWORKID); //call base init!
|
||||||
|
#ifdef ENCRYPTKEY
|
||||||
|
radio.encrypt(ENCRYPTKEY);
|
||||||
|
#endif
|
||||||
|
#ifdef FREQUENCY_EXACT
|
||||||
|
radio.setFrequency(FREQUENCY_EXACT);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
68
RFM69.cpp
68
RFM69.cpp
|
|
@ -26,6 +26,7 @@
|
||||||
#include "RFM69.h"
|
#include "RFM69.h"
|
||||||
#include "RFM69registers.h"
|
#include "RFM69registers.h"
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include <LowPower.h> //http://github.com/LowPowerLab/LowPower
|
||||||
|
|
||||||
uint8_t RFM69::DATA[RF69_MAX_DATA_LEN+1];
|
uint8_t RFM69::DATA[RF69_MAX_DATA_LEN+1];
|
||||||
uint8_t RFM69::_mode; // current transceiver state
|
uint8_t RFM69::_mode; // current transceiver state
|
||||||
|
|
@ -864,6 +865,73 @@ void RFM69::rcCalibration()
|
||||||
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
|
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListenMode sleep/timer
|
||||||
|
void RFM69::listenModeSleep(uint16_t millisInterval)
|
||||||
|
{
|
||||||
|
setMode( RF69_MODE_STANDBY );
|
||||||
|
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady
|
||||||
|
|
||||||
|
detachInterrupt( _interruptNum );
|
||||||
|
//attachInterrupt( _interruptNum, delayIrq, RISING);
|
||||||
|
writeReg( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 );
|
||||||
|
writeReg( REG_BITRATEMSB, RF_BITRATEMSB_200000);
|
||||||
|
writeReg( REG_BITRATELSB, RF_BITRATELSB_200000);
|
||||||
|
writeReg( REG_FDEVMSB, RF_FDEVMSB_100000 );
|
||||||
|
writeReg( REG_FDEVLSB, RF_FDEVLSB_100000 );
|
||||||
|
writeReg( REG_RXBW, RF_RXBW_DCCFREQ_000 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0 );
|
||||||
|
|
||||||
|
uint8_t idleResol;
|
||||||
|
uint32_t divisor;
|
||||||
|
uint32_t microInterval = millisInterval * 1000L;
|
||||||
|
|
||||||
|
if( microInterval > 255 * 4100L ) {
|
||||||
|
idleResol = RF_LISTEN1_RESOL_IDLE_262000;
|
||||||
|
divisor = 262000;
|
||||||
|
}
|
||||||
|
else if( microInterval > 255 * 64L ) {
|
||||||
|
idleResol = RF_LISTEN1_RESOL_IDLE_4100;
|
||||||
|
divisor = 4100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idleResol = RF_LISTEN1_RESOL_IDLE_64;
|
||||||
|
divisor = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeReg( REG_LISTEN1, RF_LISTEN1_RESOL_RX_64 | idleResol | RF_LISTEN1_CRITERIA_RSSI | RF_LISTEN1_END_10 );
|
||||||
|
writeReg( REG_LISTEN2, (microInterval + (divisor >> 1 ) ) / divisor );
|
||||||
|
writeReg( REG_LISTEN3, 4 );
|
||||||
|
writeReg( REG_RSSITHRESH, 255 );
|
||||||
|
writeReg( REG_RXTIMEOUT2, 1 );
|
||||||
|
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY );
|
||||||
|
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY | RF_OPMODE_LISTEN_ON );
|
||||||
|
|
||||||
|
attachInterrupt( _interruptNum, delayIrq, RISING);
|
||||||
|
|
||||||
|
LowPower.powerDown( SLEEP_FOREVER, ADC_OFF, BOD_OFF );
|
||||||
|
LowPower.powerDown( SLEEP_FOREVER, ADC_OFF, BOD_OFF );
|
||||||
|
LowPower.powerDown( SLEEP_FOREVER, ADC_OFF, BOD_OFF );
|
||||||
|
|
||||||
|
endListenModeSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// endListenModeSleep() - called by listenModeSleep()
|
||||||
|
//=============================================================================
|
||||||
|
void RFM69::endListenModeSleep()
|
||||||
|
{
|
||||||
|
detachInterrupt( _interruptNum );
|
||||||
|
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTENABORT | RF_OPMODE_STANDBY );
|
||||||
|
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY );
|
||||||
|
writeReg( REG_RXTIMEOUT2, 0 );
|
||||||
|
setMode( RF69_MODE_STANDBY );
|
||||||
|
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// delayIRQ() - called by listenModeSleep()
|
||||||
|
//=============================================================================
|
||||||
|
void RFM69::delayIrq() { return; }
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// ListenMode specific functions
|
// ListenMode specific functions
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
||||||
7
RFM69.h
7
RFM69.h
|
|
@ -228,6 +228,9 @@ class RFM69 {
|
||||||
void readAllRegs();
|
void readAllRegs();
|
||||||
void readAllRegsCompact();
|
void readAllRegsCompact();
|
||||||
|
|
||||||
|
// ListenMode sleep/timer
|
||||||
|
void listenModeSleep(uint16_t millisInterval);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void isr0();
|
static void isr0();
|
||||||
void interruptHandler();
|
void interruptHandler();
|
||||||
|
|
@ -235,6 +238,10 @@ class RFM69 {
|
||||||
static volatile bool _haveData;
|
static volatile bool _haveData;
|
||||||
virtual void sendFrame(uint16_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
|
virtual void sendFrame(uint16_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
|
||||||
|
|
||||||
|
// for ListenMode sleep/timer
|
||||||
|
static void delayIrq();
|
||||||
|
void endListenModeSleep();
|
||||||
|
|
||||||
uint8_t _slaveSelectPin;
|
uint8_t _slaveSelectPin;
|
||||||
uint8_t _interruptPin;
|
uint8_t _interruptPin;
|
||||||
uint8_t _interruptNum;
|
uint8_t _interruptNum;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue