Permalink
Cannot retrieve contributors at this time
// Sample RFM69 sender/node sketch, with ACK and optional encryption, and Automatic Transmission Control | |
// Sends periodic messages of increasing length to gateway (id=1) | |
// It also looks for an onboard FLASH chip, if present | |
// ********************************************************************************** | |
// Copyright Felix Rusu 2018, 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> //get it here: https://www.github.com/lowpowerlab/rfm69 | |
#include <RFM69_ATC.h> //get it here: https://www.github.com/lowpowerlab/rfm69 | |
#include <SPIFlash.h> //get it here: https://www.github.com/lowpowerlab/spiflash | |
//********************************************************************************************* | |
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************ | |
//********************************************************************************************* | |
// Address IDs are 10bit, meaning usable ID range is 1..1023 | |
// Address 0 is special (broadcast), messages to address 0 are received by all *listening* nodes (ie. active RX mode) | |
// Gateway ID should be kept at ID=1 for simplicity, although this is not a hard constraint | |
//********************************************************************************************* | |
#define NODEID 2 // keep UNIQUE for each node on same network | |
#define NETWORKID 100 // keep IDENTICAL on all nodes that talk to each other | |
#define GATEWAYID 1 // "central" node | |
//********************************************************************************************* | |
// Frequency should be set to match the radio module hardware tuned frequency, | |
// otherwise if say a "433mhz" module is set to work at 915, it will work but very badly. | |
// Moteinos and RF modules from LowPowerLab are marked with a colored dot to help identify their tuned frequency band, | |
// see this link for details: https://lowpowerlab.com/guide/moteino/transceivers/ | |
// The below examples are predefined "center" frequencies for the radio's tuned "ISM frequency band". | |
// You can always set the frequency anywhere in the "frequency band", ex. the 915mhz ISM band is 902..928mhz. | |
//********************************************************************************************* | |
//#define FREQUENCY RF69_433MHZ | |
//#define FREQUENCY RF69_868MHZ | |
#define FREQUENCY RF69_915MHZ | |
//#define FREQUENCY_EXACT 916000000 // you may define an exact frequency/channel in Hz | |
#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! | |
#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW! | |
//********************************************************************************************* | |
//Auto Transmission Control - dials down transmit power to save battery | |
//Usually you do not need to always transmit at max output power | |
//By reducing TX power even a little you save a significant amount of battery power | |
//This setting enables this gateway to work with remote nodes that have ATC enabled to | |
//dial their power down to only the required level (ATC_RSSI) | |
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL | |
#define ATC_RSSI -80 | |
//********************************************************************************************* | |
#define SERIAL_BAUD 115200 | |
int TRANSMITPERIOD = 200; //transmit a packet to gateway so often (in ms) | |
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
char buff[20]; | |
byte sendSize=0; | |
boolean requestACK = false; | |
SPIFlash flash(SS_FLASHMEM, 0xEF30); //EF30 for 4mbit Windbond chip (W25X40CL) | |
#ifdef ENABLE_ATC | |
RFM69_ATC radio; | |
#else | |
RFM69 radio; | |
#endif | |
void setup() { | |
Serial.begin(SERIAL_BAUD); | |
radio.initialize(FREQUENCY,NODEID,NETWORKID); | |
#ifdef IS_RFM69HW_HCW | |
radio.setHighPower(); //must include this only for RFM69HW/HCW! | |
#endif | |
#ifdef ENCRYPTKEY | |
radio.encrypt(ENCRYPTKEY); | |
#endif | |
#ifdef FREQUENCY_EXACT | |
radio.setFrequency(FREQUENCY_EXACT); //set frequency to some custom frequency | |
#endif | |
//Auto Transmission Control - dials down transmit power to save battery (-100 is the noise floor, -90 is still pretty good) | |
//For indoor nodes that are pretty static and at pretty stable temperatures (like a MotionMote) -90dBm is quite safe | |
//For more variable nodes that can expect to move or experience larger temp drifts a lower margin like -70 to -80 would probably be better | |
//Always test your ATC mote in the edge cases in your own environment to ensure ATC will perform as you expect | |
#ifdef ENABLE_ATC | |
radio.enableAutoPower(ATC_RSSI); | |
#endif | |
char buff[50]; | |
sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); | |
Serial.println(buff); | |
if (flash.initialize()) | |
{ | |
Serial.print("SPI Flash Init OK ... UniqueID (MAC): "); | |
flash.readUniqueId(); | |
for (byte i=0;i<8;i++) | |
{ | |
Serial.print(flash.UNIQUEID[i], HEX); | |
Serial.print(' '); | |
} | |
Serial.println(); | |
} | |
else | |
Serial.println("SPI Flash MEM not found (is chip soldered?)..."); | |
#ifdef ENABLE_ATC | |
Serial.println("RFM69_ATC Enabled (Auto Transmission Control)\n"); | |
#endif | |
} | |
void Blink(byte PIN, int DELAY_MS) | |
{ | |
pinMode(PIN, OUTPUT); | |
digitalWrite(PIN,HIGH); | |
delay(DELAY_MS); | |
digitalWrite(PIN,LOW); | |
} | |
long lastPeriod = 0; | |
void loop() { | |
//process any serial input | |
if (Serial.available() > 0) | |
{ | |
char input = Serial.read(); | |
if (input >= 48 && input <= 57) //[0,9] | |
{ | |
TRANSMITPERIOD = 100 * (input-48); | |
if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000; | |
Serial.print("\nChanging delay to "); | |
Serial.print(TRANSMITPERIOD); | |
Serial.println("ms\n"); | |
} | |
if (input == 'r') //d=dump register values | |
radio.readAllRegs(); | |
//if (input == 'E') //E=enable encryption | |
// radio.encrypt(KEY); | |
//if (input == 'e') //e=disable encryption | |
// radio.encrypt(null); | |
if (input == 'd') //d=dump flash area | |
{ | |
Serial.println("Flash content:"); | |
uint16_t counter = 0; | |
Serial.print("0-256: "); | |
while(counter<=256){ | |
Serial.print(flash.readByte(counter++), HEX); | |
Serial.print('.'); | |
} | |
while(flash.busy()); | |
Serial.println(); | |
} | |
if (input == 'e') | |
{ | |
Serial.print("Erasing Flash chip ... "); | |
flash.chipErase(); | |
while(flash.busy()); | |
Serial.println("DONE"); | |
} | |
if (input == 'i') | |
{ | |
Serial.print("DeviceID: "); | |
word jedecid = flash.readDeviceId(); | |
Serial.println(jedecid, HEX); | |
} | |
} | |
//check for any received packets | |
if (radio.receiveDone()) | |
{ | |
Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); | |
for (byte i = 0; i < radio.DATALEN; i++) | |
Serial.print((char)radio.DATA[i]); | |
Serial.print(" [RX_RSSI:");Serial.print(radio.RSSI);Serial.print("]"); | |
if (radio.ACKRequested()) | |
{ | |
radio.sendACK(); | |
Serial.print(" - ACK sent"); | |
} | |
Blink(LED_BUILTIN,3); | |
Serial.println(); | |
} | |
int currPeriod = millis()/TRANSMITPERIOD; | |
if (currPeriod != lastPeriod) | |
{ | |
lastPeriod=currPeriod; | |
//send FLASH id | |
if(sendSize==0) | |
{ | |
sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId()); | |
byte buffLen=strlen(buff); | |
if (radio.sendWithRetry(GATEWAYID, buff, buffLen)) | |
Serial.print(" ok!"); | |
else Serial.print(" nothing..."); | |
//sendSize = (sendSize + 1) % 31; | |
} | |
else | |
{ | |
Serial.print("Sending["); | |
Serial.print(sendSize); | |
Serial.print("]: "); | |
for(byte i = 0; i < sendSize; i++) | |
Serial.print((char)payload[i]); | |
if (radio.sendWithRetry(GATEWAYID, payload, sendSize)) | |
Serial.print(" ok!"); | |
else Serial.print(" nothing..."); | |
} | |
sendSize = (sendSize + 1) % 31; | |
Serial.println(); | |
Blink(LED_BUILTIN,3); | |
} | |
} |