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 "RFM69registers.h"
|
||||
#include <SPI.h>
|
||||
#include <LowPower.h> //http://github.com/LowPowerLab/LowPower
|
||||
|
||||
uint8_t RFM69::DATA[RF69_MAX_DATA_LEN+1];
|
||||
uint8_t RFM69::_mode; // current transceiver state
|
||||
|
|
@ -864,6 +865,73 @@ void RFM69::rcCalibration()
|
|||
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
|
||||
//=============================================================================
|
||||
|
|
|
|||
7
RFM69.h
7
RFM69.h
|
|
@ -228,6 +228,9 @@ class RFM69 {
|
|||
void readAllRegs();
|
||||
void readAllRegsCompact();
|
||||
|
||||
// ListenMode sleep/timer
|
||||
void listenModeSleep(uint16_t millisInterval);
|
||||
|
||||
protected:
|
||||
static void isr0();
|
||||
void interruptHandler();
|
||||
|
|
@ -235,6 +238,10 @@ class RFM69 {
|
|||
static volatile bool _haveData;
|
||||
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 _interruptPin;
|
||||
uint8_t _interruptNum;
|
||||
|
|
|
|||
Loading…
Reference in New Issue