// **********************************************************************************************************
// Moteino gateway/base sketch that works with Moteinos equipped with RFM69W/RFM69HW/RFM69CW/RFM69HCW
// This is a basic gateway sketch that receives packets from end node Moteinos, formats them as ASCII strings
// with the end node [ID] and passes them to Pi/host computer via serial port
// (ex: "messageFromNode" from node 123 gets passed to serial as "[123] messageFromNode")
// It also listens to serial messages that should be sent to listening end nodes
// (ex: "123:messageToNode" sends "messageToNode" to node 123)
// Make sure to adjust the settings to match your transceiver settings (frequency, HW etc).
// **********************************************************************************
// Copyright Felix Rusu 2016, 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://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <RFM69_OTA.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <SPIFlash.h> //get it here: https://github.com/lowpowerlab/spiflash
#include <SPI.h> //included with Arduino IDE (www.arduino.cc)
//****************************************************************************************************************
//**** IMPORTANT RADIO SETTINGS - YOU MUST CHANGE/CONFIGURE TO MATCH YOUR HARDWARE TRANSCEIVER CONFIGURATION! ****
//****************************************************************************************************************
#define NODEID 1 //the ID of this node
#define NETWORKID 200 //the network ID of all nodes this node listens/talks to
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //identical 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
#define ACK_TIME 30 // # of ms to wait for an ack packet
//*****************************************************************************************************************************
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI -75 //target RSSI for RFM69_ATC (recommended > -80)
//*****************************************************************************************************************************
// Serial baud rate must match your Pi/host computer serial port baud rate!
#define SERIAL_EN //comment out if you don't want any serial verbose output
#define SERIAL_BAUD 115200
//*****************************************************************************************************************************
#ifdef __AVR_ATmega1284P__
#define LED 15 // Moteino MEGAs have LEDs on D15
#define FLASH_SS 23 // and FLASH SS on D23
#else
#define LED 9 // Moteinos have LEDs on D9
#define FLASH_SS 8 // and FLASH SS on D8
#endif
#ifdef SERIAL_EN
#define DEBUG(input) {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
// #define DEBUG(input) {Serial.print(input);}
// #define DEBUGln(input) {Serial.println(input);}
#else
#define DEBUG(input);
#define DEBUGln(input);
#endif
#ifdef ENABLE_ATC
RFM69_ATC radio;
#else
RFM69 radio;
#endif
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond FlashMEM chip
void setup() {
Serial.begin(SERIAL_BAUD);
delay(10);
radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW_HCW
radio.setHighPower(); //must include this only for RFM69HW/HCW!
#endif
radio.encrypt(ENCRYPTKEY);
#ifdef ENABLE_ATC
radio.enableAutoPower(ATC_RSSI);
#endif
char buff[50];
sprintf(buff, "\nTransmitting at %d Mhz...", radio.getFrequency()/1000000);
DEBUGln(buff);
if (flash.initialize())
{
DEBUGln("SPI Flash Init OK!");
}
else
{
DEBUGln("SPI FlashMEM not found (is chip onboard?)");
}
}
byte ackCount=0;
byte inputLen=0;
char input[64];
byte buff[61];
String inputstr;
void loop() {
inputLen = readSerialLine(input);
inputstr = String(input);
inputstr.toUpperCase();
if (inputLen > 0)
{
if (inputstr.equals("KEY?"))
{
DEBUG("ENCRYPTKEY:");
DEBUG(ENCRYPTKEY);
}
byte targetId = inputstr.toInt(); //extract ID if any
byte colonIndex = inputstr.indexOf(":"); //find position of first colon
if (targetId > 0)
{
inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any
}
if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0)
{
inputstr.getBytes(buff, 61);
//DEBUGln((char*)buff);
//DEBUGln(targetId);
//DEBUGln(colonIndex);
if (radio.sendWithRetry(targetId, buff, inputstr.length()))
{
DEBUGln("ACK:OK");
}
else
DEBUGln("ACK:NOK");
}
}
if (radio.receiveDone())
{
int rssi = radio.RSSI;
DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
if (radio.DATALEN > 0)
{
for (byte i = 0; i < radio.DATALEN; i++)
DEBUG((char)radio.DATA[i]);
DEBUG(" [RSSI:");DEBUG(rssi);DEBUG("]");
}
CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG
if (radio.ACKRequested())
{
byte theNodeID = radio.SENDERID;
radio.sendACK();
DEBUG("[ACK-sent]");
}
DEBUGln();
Blink(LED,3);
}
}
void Blink(byte PIN, int DELAY_MS)
{
pinMode(PIN, OUTPUT);
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}
/* ***************************************************************************************************
// Example sketch from John's DIY Playground
// to demonstrate the Moteino IoT device using an RFM69 transceiver attached to it.
// Visit http://www.lowpowerlab.com/ to purchase a Moteino of your own
//
// This sketch will demonstrate a few basic features of the Moteino:
// 1. It will flash the onboard LED located at pin D9
// 2. It will report sensor light levels from a photoresistor on pin A5 to the Home Automation gateway
// 3. It will allow us to control an LED connected to pin D3 remotely
//
// Demonstration of this code can be found on my YouTube channel, called John's DIY Playground
// The channel's URL is http://www.youtube.com/c/johnsdiyplayground
// Software code examples can be found on my GitHub page at
// https://github.com/johnsdiyplayground
//
// Hardware Required:
// 1. Moteino or Moteino USB with RFM69 transceiver (http://www.lowpowerlab.com/)
// 2. LED
// 3. 2 quantity of 220 ohm resistor for the external LED and photoresistor circuits
// Put the resistors in series; the LED to ground and the other from photoresistor A5 to ground
// 4. Photoresistor
// 5. USB to micro USB cable for powering the Moteino
// 6. Another USB Moteino with the Pi Gateway code loaded on it and connected to a Raspberry Pi
// NOTE: this second Moteino must have the same frequency RFM69 transceiver attached to it
// 7. FTDI USB to Moteino programming interface (Not needed if you are using Moteino USB devices)
******************************************************************************************************
*/
#include <RFM69.h> //get it here: http://github.com/lowpowerlab/rfm69
#include <SPIFlash.h> //get it here: http://github.com/lowpowerlab/spiflash
//#include <WirelessHEX69.h> //get it here: https://github.com/LowPowerLab/WirelessProgramming
#include <SPI.h> //comes with Arduino IDE (www.arduino.cc)
#define SERIAL_EN //comment out if you don't want any serial output
//*****************************************************************************************************************************
// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS
//*****************************************************************************************************************************
#define GATEWAYID 1 // this is the node ID of your gateway (which is probably tied to a Raspberry Pi)
#define NODEID 44 // must be unique to each sensor node
#define NETWORKID 200 // every node must match the same network ID to hear messages from each other and take actions directly
//#define FREQUENCY RF69_433MHZ
//#define FREQUENCY RF69_868MHZ
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino's transceiver! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //has to be same 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*****************************************************************************************************************************
#ifdef SERIAL_EN
#define SERIAL_BAUD 115200
#define DEBUG(input) {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#else
#define DEBUG(input);
#define DEBUGln(input);
#define SERIALFLUSH();
#endif
// Define our pins
#define onboardLED 9 // Moteino onboard LED is on digital pin 9
#define photoResistor A5
#define photoResistorPower A2 // The photoresistor will be hooked to pins A2 and A5
#define externalLED 3 // careful about which pins are already in use by Moteino's RFM69 transceiver!
// For example, on Moteino you CANNOT use D2, D8, D10, D11, D12, D13!!
// Now we will define how often to flash our onboard LED
const long blinkLEDtime = 1000; // 1000 is milliseconds so this means blink on/off in 1 second intervals
// and we need a way to record the last time we turned the LED on or off
unsigned long lastBlinkTime;
// The next variable defines how often to check the photoresistor's light level
//const long photoResistorCheckTime = 30000; // 10000 milliseconds is 10 seconds
const long photoResistorCheckTime = 5000; // 10000 milliseconds is 10 seconds
// and we also record the time we report the photoresistor status with this
unsigned long lastPhotoResistorReport;
// We don't need to define how often to check commands to turn on/off the external LED. That's because
// our Moteino will respond to commands to request it come on or off from the Raspberry Pi / Moteino gateway device.
// The only thing we do track is the external LED's current status as on (1) or off (0)
int ledStatus;
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //this is for transmitting to the Pi Gateway
byte STATUS;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)
#define MAXRETRIES 5
#define MAXTIMEOUT 50
void setup() {
#ifdef SERIAL_EN
Serial.begin(SERIAL_BAUD);
#endif
// Tell Moteino if our pins are inputs or outputs
pinMode(onboardLED, OUTPUT);
pinMode(photoResistor, INPUT);
pinMode(photoResistorPower, OUTPUT);
pinMode(externalLED, OUTPUT);
// Initialize our onboard and external LEDs to start up turned off (set to low)
digitalWrite(onboardLED, LOW);
digitalWrite(externalLED, LOW);
// Turn on power to the photoresistor
digitalWrite(photoResistorPower, HIGH);
// Initialize our timers for the onboard LED and photoresistor using millis which is the Photon's internal clock
lastBlinkTime = millis();
lastPhotoResistorReport = millis();
char buff[20]; // create a variable called buff (short for "buffer") that can hold up to 20 characters
radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
radio.setHighPower(); //uncomment only for RFM69HW!
#endif
radio.encrypt(ENCRYPTKEY);
if (flash.initialize()){
DEBUGln("EEPROM flash chip found, and is OK ...");
}
else
DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");
sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); // sprintf command creates a string to put in the buff variable
DEBUGln(payload); // check what we are transmitting to the gateway receiver
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
{
DEBUGln("Init: ACK Success!");
}
else
{
DEBUGln("Init: ACK Fail!");
}
// We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
if (radio.sendWithRetry(GATEWAYID, "9900:0", 6, MAXRETRIES, MAXTIMEOUT))
{
DEBUGln("Startup: ACK Success!");
}
else
{
DEBUGln("Startup: ACK Fail!");
}
delay(5000);
}
void loop() {
// wireless programming token check
// DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
//CheckForWirelessHEX(radio, flash, true);
// check for messages from the home automation gateway or other Moteino nodes
if (radio.receiveDone()){
DEBUG("Msg received from sender ID ");DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
for (byte i = 0; i < radio.DATALEN; i++)
DEBUG((char)radio.DATA[i]);
DEBUGln();
//first send any ACK to request
DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUGln("]");
DEBUG(" Payload length = ");
DEBUGln(radio.DATALEN);
if (radio.DATALEN==3){
//check for a web page request from Pi Gateway to turn on or off the external LED
//we will receive from the Pi Gateway either a message of "LOF" or LON"
if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='F'){ // "LOF" is short for "LED off", keep radio messages short for best results
digitalWrite(externalLED, LOW); // Tell our external LED to turn OFF
ledStatus = 0; // this sets our LED status variable
delay(50);
transmitStatus(9900, ledStatus); // now we transmit LED status back to the Pi Gateway that we turned the LED off using transmitStatus subroutine
// We are passing a unique 4-digit number to identify a unique data type for our Pi Gateway, since it listens
// to a lot of sensor nodes in our house. Each sensor node gets its own set of 4-digit codes.
// Any time we transmit an LED status, we will always identify it with sensor code "9900"
}
else if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='N'){ // "LON" is short for "LED on"
digitalWrite(externalLED, HIGH); // Tell our external LED to turn ON
ledStatus = 1; // this sets our LED status variable
delay(50);
transmitStatus(9900, ledStatus); // now we transmit LED status back to the Pi Gateway that we turned the LED off
}
}
}
if (radio.ACKRequested())
{
radio.sendACK();
DEBUGln("ACK sent.");
}
// check if the onboard LED should be turned on or off
if ((millis() - lastBlinkTime) >= blinkLEDtime) {
lastBlinkTime = millis(); // update current time for the next time through the loop
digitalWrite(onboardLED, !digitalRead(onboardLED)); // this says in one simple line to flip-flop the status of the pin
}
// check if it is time to report the photoresistor's value to the Moteino USB gateway (receives data for the Raspberry Pi)
if ((millis() - lastPhotoResistorReport) >= photoResistorCheckTime) {
lastPhotoResistorReport = millis(); // update current time for the next time through the loop
int lightLevel = analogRead(photoResistor); // we read in the photoResistor level here (value can be 0 to 4095)
// publish the actual value of the light level. We will call this sensor ID data code "9912"
transmitStatus(9905, lightLevel);
}
} // this is the end of the loop
// The function below will transmit the LED status to our Moteino USB / Pi Gateway
void transmitStatus(int item, int status){
sprintf(payload, "%d:%d", item, status);
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
{
DEBUGln("XMit ACK - Success!");
}
else
{
DEBUGln("XMit ACK - Fail!");
}
DEBUG("Transmitted payload: ");
DEBUGln(payload);
delay(10);
}
18:30:37.115 -> EEPROM flash chip found, and is OK ...
18:30:37.115 -> Moteino Example : 915 Mhz...
18:30:37.419 -> Init: ACK Fail!
18:30:37.748 -> Startup: ACK Fail!
18:30:42.756 -> Msg received from sender ID [1]
18:30:42.756 -> [RX_RSSI:-31]
18:30:42.756 -> Payload length = 0
18:30:42.931 -> XMit ACK - Success!
18:30:42.931 -> Transmitted payload: 9905:751
18:30:47.934 -> XMit ACK - Success!
18:30:47.934 -> Transmitted payload: 9905:752
18:30:52.978 -> XMit ACK - Success!
18:30:52.978 -> Transmitted payload: 9905:746
18:30:57.992 -> XMit ACK - Success!
18:30:57.992 -> Transmitted payload: 9905:746
18:31:03.005 -> XMit ACK - Success!
18:31:03.005 -> Transmitted payload: 9905:751
18:31:08.006 -> XMit ACK - Fail!
18:31:08.006 -> Transmitted payload: 9905:756
18:31:08.006 -> Msg received from sender ID [1]
18:31:08.006 -> [RX_RSSI:-32]
18:31:08.041 -> Payload length = 0
18:31:12.998 -> XMit ACK - Fail!
18:31:12.998 -> Transmitted payload: 9905:749
18:31:13.043 -> Msg received from sender ID [1]
18:31:13.043 -> [RX_RSSI:-31]
18:31:13.043 -> Payload length = 0
18:31:17.993 -> XMit ACK - Fail!
18:31:17.993 -> Transmitted payload: 9905:745
18:31:18.031 -> Msg received from sender ID [1]
18:31:18.031 -> [RX_RSSI:-32]
18:31:18.066 -> Payload length = 0
18:31:22.999 -> XMit ACK - Fail!
18:31:22.999 -> Transmitted payload: 9905:746
18:31:23.037 -> Msg received from sender ID [1]
18:31:23.037 -> [RX_RSSI:-32]
18:31:23.037 -> Payload length = 0
6:31:33 PM : {"_id":44,"updated":1547253092959,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547253092959,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:28 PM : {"_id":44,"updated":1547253087949,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":753,"unit":" level","updated":1547253087949,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:23 PM : {"_id":44,"updated":1547253082939,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253082939,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:18 PM : {"_id":44,"updated":1547253077915,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":745,"unit":" level","updated":1547253077915,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:13 PM : {"_id":44,"updated":1547253072907,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":749,"unit":" level","updated":1547253072907,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:08 PM : {"_id":44,"updated":1547253067897,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547253067897,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:03 PM : {"_id":44,"updated":1547253062889,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547253062889,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:58 PM : {"_id":44,"updated":1547253057879,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253057879,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:53 PM : {"_id":44,"updated":1547253052870,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253052870,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:47 PM : {"_id":44,"updated":1547253047811,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547253047811,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:42 PM : {"_id":44,"updated":1547253042802,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547253042802,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:37 PM : {"_id":44,"updated":1547253037790,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253031760,"pin":0},"LED Status":{"label":"LED
if (flash.initialize()){
DEBUGln("EEPROM flash chip found, and is OK ...");
}
else
DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");
}
bool started = false;
void loop() {
if (!started) // only do first time through loop
{
sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); // sprintf command creates a string to put in the buff variable
DEBUGln(payload); // check what we are transmitting to the gateway receiver
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
{
DEBUGln("Init: ACK Success!");
}
else
{
DEBUGln("Init: ACK Fail!");
}
// We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
if (radio.sendWithRetry(GATEWAYID, "9900:0", 6, MAXRETRIES, MAXTIMEOUT))
{
DEBUGln("Startup: ACK Success!");
}
else
{
DEBUGln("Startup: ACK Fail!");
}
delay(5000);
started = true;
}
// wireless programming token check
// DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
//CheckForWirelessHEX(radio, flash, true);
// check for messages from the home automation gateway or other Moteino nodes
if (radio.receiveDone()){
18:33:37.587 -> EEPROM flash chip found, and is OK …
18:33:37.587 -> Moteino Example : 915 Mhz...
18:33:37.868 -> Init: ACK Fail!
18:33:38.198 -> Startup: ACK Fail!
18:33:43.210 -> Msg received from sender ID [1]
18:33:43.210 -> [RX_RSSI:-31]
18:33:43.210 -> Payload length = 0
18:33:43.339 -> XMit ACK - Success!
18:33:43.339 -> Transmitted payload: 9905:757
18:33:48.381 -> XMit ACK - Success!
18:33:48.381 -> Transmitted payload: 9905:750
18:33:53.381 -> XMit ACK - Success!
18:33:53.381 -> Transmitted payload: 9905:746
18:33:58.393 -> XMit ACK - Success!
18:33:58.393 -> Transmitted payload: 9905:747
18:34:03.398 -> XMit ACK - Success!
18:34:03.398 -> Transmitted payload: 9905:753
18:34:08.422 -> XMit ACK - Success!
18:34:08.422 -> Transmitted payload: 9905:757
18:34:13.435 -> XMit ACK - Success!
18:34:13.435 -> Transmitted payload: 9905:748
18:34:18.442 -> XMit ACK - Success!
18:34:18.442 -> Transmitted payload: 9905:745
18:34:23.434 -> XMit ACK - Success!
18:34:23.434 -> Transmitted payload: 9905:750
18:34:28.407 -> XMit ACK - Fail!
18:34:28.454 -> Transmitted payload: 9905:757
18:34:28.454 -> Msg received from sender ID [1]
18:34:28.454 -> [RX_RSSI:-31]
18:34:28.454 -> Payload length = 0
18:34:33.399 -> XMit ACK - Fail!
18:34:33.399 -> Transmitted payload: 9905:754
18:34:33.470 -> Msg received from sender ID [1]
18:34:33.470 -> [RX_RSSI:-30]
18:34:33.470 -> Payload length = 0
18:34:38.430 -> XMit ACK - Fail!
18:34:38.430 -> Transmitted payload: 9905:747
18:34:38.466 -> Msg received from sender ID [1]
18:34:38.466 -> [RX_RSSI:-30]
18:34:38.466 -> Payload length = 0
18:34:43.402 -> XMit ACK - Fail!
18:34:43.402 -> Transmitted payload: 9905:745
18:34:43.489 -> Msg received from sender ID [1]
18:34:43.489 -> [RX_RSSI:-31]
18:34:43.489 -> Payload length = 0
// **********************************************************************************************************
// Moteino gateway/base sketch that works with Moteinos equipped with RFM69W/RFM69HW/RFM69CW/RFM69HCW
// This is a basic gateway sketch that receives packets from end node Moteinos, formats them as ASCII strings
// with the end node [ID] and passes them to Pi/host computer via serial port
// (ex: "messageFromNode" from node 123 gets passed to serial as "[123] messageFromNode")
// It also listens to serial messages that should be sent to listening end nodes
// (ex: "123:messageToNode" sends "messageToNode" to node 123)
// Make sure to adjust the settings to match your transceiver settings (frequency, HW etc).
// **********************************************************************************
// Copyright Felix Rusu 2016, 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://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <RFM69_OTA.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <SPIFlash.h> //get it here: https://github.com/lowpowerlab/spiflash
#include <SPI.h> //included with Arduino IDE (www.arduino.cc)
//****************************************************************************************************************
//**** IMPORTANT RADIO SETTINGS - YOU MUST CHANGE/CONFIGURE TO MATCH YOUR HARDWARE TRANSCEIVER CONFIGURATION! ****
//****************************************************************************************************************
#define NODEID 1 //the ID of this node
#define NETWORKID 200 //the network ID of all nodes this node listens/talks to
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //identical 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
#define ACK_TIME 30 // # of ms to wait for an ack packet
//*****************************************************************************************************************************
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI -75 //target RSSI for RFM69_ATC (recommended > -80)
//*****************************************************************************************************************************
// Serial baud rate must match your Pi/host computer serial port baud rate!
#define SERIAL_EN //comment out if you don't want any serial verbose output
#define SERIAL_BAUD 115200
//*****************************************************************************************************************************
#ifdef __AVR_ATmega1284P__
#define LED 15 // Moteino MEGAs have LEDs on D15
#define FLASH_SS 23 // and FLASH SS on D23
#else
#define LED 9 // Moteinos have LEDs on D9
#define FLASH_SS 8 // and FLASH SS on D8
#endif
#ifdef SERIAL_EN
#define DEBUG(input) Serial.print(input)
#define DEBUGln(input) Serial.println(input)
#define SERIALFLUSH() Serial.flush()
#else
#define DEBUG(input);
#define DEBUGln(input);
#define SERIALFLUSH();
#endif
#ifdef ENABLE_ATC
RFM69_ATC radio;
#else
RFM69 radio;
#endif
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond FlashMEM chip
void setup() {
Serial.begin(SERIAL_BAUD);
delay(10);
radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW_HCW
radio.setHighPower(); //must include this only for RFM69HW/HCW!
#endif
radio.encrypt(ENCRYPTKEY);
#ifdef ENABLE_ATC
radio.enableAutoPower(ATC_RSSI);
#endif
char buff[50];
sprintf(buff, "\nTransmitting at %d Mhz...", radio.getFrequency()/1000000);
DEBUGln(buff);
if (flash.initialize())
{
DEBUGln("SPI Flash Init OK!");
}
else
{
DEBUGln("SPI FlashMEM not found (is chip onboard?)");
}
}
byte ackCount=0;
byte inputLen=0;
char input[64];
byte buff[61];
String inputstr;
void loop() {
inputLen = readSerialLine(input);
inputstr = String(input);
inputstr.toUpperCase();
if (inputLen > 0)
{
if (inputstr.equals("KEY?"))
{
DEBUG("ENCRYPTKEY:");
DEBUG(ENCRYPTKEY);
}
byte targetId = inputstr.toInt(); //extract ID if any
byte colonIndex = inputstr.indexOf(":"); //find position of first colon
if (targetId > 0)
{
inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any
}
if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0)
{
inputstr.getBytes(buff, 61);
//DEBUGln((char*)buff);
//DEBUGln(targetId);
//DEBUGln(colonIndex);
if (radio.sendWithRetry(targetId, buff, inputstr.length()))
{
DEBUGln("ACK:OK");
}
else
DEBUGln("ACK:NOK");
}
}
if (radio.receiveDone())
{
int rssi = radio.RSSI;
int senderId = radio.SENDERID;
int dataLen = radio.DATALEN;
strncpy((char *)buff, (const char *)radio.DATA, dataLen);
buff[dataLen] = '\0';
bool ackSent = false;
CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG
if (radio.ACKRequested())
{
byte theNodeID = radio.SENDERID;
radio.sendACK();
ackSent = true;
}
if (dataLen > 0)
{
DEBUG('[');DEBUG(senderId);DEBUG("] ");
DEBUG((char *)buff);
DEBUG(" [RSSI:");DEBUG(rssi);DEBUG("]");
}
if (ackSent)
DEBUG("[ACK-sent]");
DEBUGln();
Blink(LED,3);
SERIALFLUSH();
}
}
void Blink(byte PIN, int DELAY_MS)
{
pinMode(PIN, OUTPUT);
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}
18:39:43.995 -> EEPROM flash chip found, and is OK ...
18:39:43.995 -> Moteino Example : 915 Mhz...
18:39:44.312 -> Init: ACK Fail!
18:39:44.641 -> Startup: ACK Fail!
18:39:49.638 -> Msg received from sender ID [1]
18:39:49.638 -> [RX_RSSI:-30]
18:39:49.685 -> Payload length = 0
18:39:49.954 -> XMit ACK - Success!
18:39:49.954 -> Transmitted payload: 9905:757
18:39:54.924 -> XMit ACK - Success!
18:39:54.924 -> Transmitted payload: 9905:747
18:39:59.935 -> XMit ACK - Success!
18:39:59.935 -> Transmitted payload: 9905:746
18:40:04.916 -> XMit ACK - Success!
18:40:04.916 -> Transmitted payload: 9905:752
18:40:09.933 -> XMit ACK - Success!
18:40:09.933 -> Transmitted payload: 9905:757
18:40:14.912 -> XMit ACK - Fail!
18:40:14.912 -> Transmitted payload: 9905:756
18:40:14.946 -> Msg received from sender ID [1]
18:40:14.946 -> [RX_RSSI:-30]
18:40:14.946 -> Payload length = 0
18:40:19.907 -> XMit ACK - Fail!
18:40:19.907 -> Transmitted payload: 9905:746
18:40:19.942 -> Msg received from sender ID [1]
18:40:19.942 -> [RX_RSSI:-31]
18:40:19.942 -> Payload length = 0
18:40:24.897 -> XMit ACK - Fail!
18:40:24.897 -> Transmitted payload: 9905:746
18:40:24.932 -> Msg received from sender ID [1]
18:40:24.932 -> [RX_RSSI:-30]
18:40:24.932 -> Payload length = 0
18:40:29.881 -> XMit ACK - Fail!
18:40:29.881 -> Transmitted payload: 9905:750
18:40:29.916 -> Msg received from sender ID [1]
18:40:29.916 -> [RX_RSSI:-31]
18:40:29.916 -> Payload length = 0
18:40:34.887 -> XMit ACK - Fail!
18:40:34.887 -> Transmitted payload: 9905:757
18:40:34.887 -> Msg received from sender ID [1]
18:40:34.887 -> [RX_RSSI:-29]
18:40:34.887 -> Payload length = 0
sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); // sprintf command creates a string to put in the buff variable
DEBUGln(payload); // check what we are transmitting to the gateway receiver
byte buffLen=strlen(payload);
radio.sendWithRetry(GATEWAYID, payload, buffLen);
// We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
radio.sendWithRetry(GATEWAYID, "9900:0", 6);
delay(5000);
void transmitStatus(int item, int status){
sprintf(payload, "%d:%d", item, status);
byte buffLen=strlen(payload);
radio.sendWithRetry(GATEWAYID, payload, buffLen);
DEBUG("Transmitted payload: ");
DEBUGln(payload);
delay(10);
}
sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); // sprintf command creates a string to put in the buff variable
DEBUGln(payload); // check what we are transmitting to the gateway receiver
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen))
{
DEBUGln("Init: ACK Success!");
}
else
{
DEBUGln("Init: ACK Fail!");
}
// We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
if (radio.sendWithRetry(GATEWAYID, "9900:0", 6))
{
DEBUGln("Startup: ACK Success!");
}
else
{
DEBUGln("Startup: ACK Fail!");
}
delay(5000);
void transmitStatus(int item, int status){
sprintf(payload, "%d:%d", item, status);
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
{
DEBUGln("XMit ACK - Success!");
}
else
{
DEBUGln("XMit ACK - Fail!");
}
DEBUG("Transmitted payload: ");
DEBUGln(payload);
delay(10);
}
/* ***************************************************************************************************
// Example sketch from John's DIY Playground
// to demonstrate the Moteino IoT device using an RFM69 transceiver attached to it.
// Visit http://www.lowpowerlab.com/ to purchase a Moteino of your own
//
// This sketch will demonstrate a few basic features of the Moteino:
// 1. It will flash the onboard LED located at pin D9
// 2. It will report sensor light levels from a photoresistor on pin A5 to the Home Automation gateway
// 3. It will allow us to control an LED connected to pin D3 remotely
//
// Demonstration of this code can be found on my YouTube channel, called John's DIY Playground
// The channel's URL is http://www.youtube.com/c/johnsdiyplayground
// Software code examples can be found on my GitHub page at
// https://github.com/johnsdiyplayground
//
// Hardware Required:
// 1. Moteino or Moteino USB with RFM69 transceiver (http://www.lowpowerlab.com/)
// 2. LED
// 3. 2 quantity of 220 ohm resistor for the external LED and photoresistor circuits
// Put the resistors in series; the LED to ground and the other from photoresistor A5 to ground
// 4. Photoresistor
// 5. USB to micro USB cable for powering the Moteino
// 6. Another USB Moteino with the Pi Gateway code loaded on it and connected to a Raspberry Pi
// NOTE: this second Moteino must have the same frequency RFM69 transceiver attached to it
// 7. FTDI USB to Moteino programming interface (Not needed if you are using Moteino USB devices)
******************************************************************************************************
*/
#include <RFM69.h> //get it here: http://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <RFM69_OTA.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <SPIFlash.h> //get it here: http://github.com/lowpowerlab/spiflash
//#include <WirelessHEX69.h> //Replaced by rfm69_ota.h
#include <SPI.h> //comes with Arduino IDE (www.arduino.cc)
#define SERIAL_EN //comment out if you don't want any serial output
//*****************************************************************************************************************************
// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS
//*****************************************************************************************************************************
#define GATEWAYID 1 // this is the node ID of your gateway (which is probably tied to a Raspberry Pi)
#define NODEID 44 // must be unique to each sensor node
#define NETWORKID 200 // every node must match the same network ID to hear messages from each other and take actions directly
//#define FREQUENCY RF69_433MHZ
//#define FREQUENCY RF69_868MHZ
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino's transceiver! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //has to be same 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*****************************************************************************************************************************
#ifdef SERIAL_EN
#define SERIAL_BAUD 115200
#define DEBUG(input) {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#else
#define DEBUG(input);
#define DEBUGln(input);
#define SERIALFLUSH();
#endif
// Define our pins
#define onboardLED 9 // Moteino onboard LED is on digital pin 9
#define photoResistor A5
#define photoResistorPower A2 // The photoresistor will be hooked to pins A2 and A5
#define externalLED 3 // careful about which pins are already in use by Moteino's RFM69 transceiver!
// For example, on Moteino you CANNOT use D2, D8, D10, D11, D12, D13!!
// Now we will define how often to flash our onboard LED
const long blinkLEDtime = 1000; // 1000 is milliseconds so this means blink on/off in 1 second intervals
// and we need a way to record the last time we turned the LED on or off
unsigned long lastBlinkTime;
// The next variable defines how often to check the photoresistor's light level
const long photoResistorCheckTime = 30000; // 10000 milliseconds is 10 seconds
// and we also record the time we report the photoresistor status with this
unsigned long lastPhotoResistorReport;
// We don't need to define how often to check commands to turn on/off the external LED. That's because
// our Moteino will respond to commands to request it come on or off from the Raspberry Pi / Moteino gateway device.
// The only thing we do track is the external LED's current status as on (1) or off (0)
int ledStatus;
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //this is for transmitting to the Pi Gateway
byte STATUS;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)
void setup() {
#ifdef SERIAL_EN
Serial.begin(SERIAL_BAUD);
#endif
// Tell Moteino if our pins are inputs or outputs
pinMode(onboardLED, OUTPUT);
pinMode(photoResistor, INPUT);
pinMode(photoResistorPower, OUTPUT);
pinMode(externalLED, OUTPUT);
// Initialize our onboard and external LEDs to start up turned off (set to low)
digitalWrite(onboardLED, LOW);
digitalWrite(externalLED, LOW);
// Turn on power to the photoresistor
digitalWrite(photoResistorPower, HIGH);
// Initialize our timers for the onboard LED and photoresistor using millis which is the Photon's internal clock
lastBlinkTime = millis();
lastPhotoResistorReport = millis();
char buff[20]; // create a variable called buff (short for "buffer") that can hold up to 20 characters
radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
radio.setHighPower(); //uncomment only for RFM69HW!
#endif
radio.encrypt(ENCRYPTKEY);
if (flash.initialize()){
DEBUGln("EEPROM flash chip found, and is OK ...");
}
else
DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");
sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); // sprintf command creates a string to put in the buff variable
DEBUGln(payload); // check what we are transmitting to the gateway receiver
byte buffLen=strlen(payload);
radio.sendWithRetry(GATEWAYID, payload, buffLen);
// We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
radio.sendWithRetry(GATEWAYID, "9900:0", 6);
delay(5000);
}
void loop() {
// wireless programming token check
// DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
CheckForWirelessHEX(radio, flash, true);
// check for messages from the home automation gateway or other Moteino nodes
if (radio.receiveDone()){
DEBUG("Msg received from sender ID ");DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
for (byte i = 0; i < radio.DATALEN; i++)
DEBUG((char)radio.DATA[i]);
DEBUGln();
//first send any ACK to request
DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUGln("]");
DEBUG(" Payload length = ");
DEBUGln(radio.DATALEN);
if (radio.DATALEN==3){
//check for a web page request from Pi Gateway to turn on or off the external LED
//we will receive from the Pi Gateway either a message of "LOF" or LON"
if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='F'){ // "LOF" is short for "LED off", keep radio messages short for best results
digitalWrite(externalLED, LOW); // Tell our external LED to turn OFF
ledStatus = 0; // this sets our LED status variable
delay(50);
transmitStatus(9900, ledStatus); // now we transmit LED status back to the Pi Gateway that we turned the LED off using transmitStatus subroutine
// We are passing a unique 4-digit number to identify a unique data type for our Pi Gateway, since it listens
// to a lot of sensor nodes in our house. Each sensor node gets its own set of 4-digit codes.
// Any time we transmit an LED status, we will always identify it with sensor code "9900"
}
else if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='N'){ // "LON" is short for "LED on"
digitalWrite(externalLED, HIGH); // Tell our external LED to turn ON
ledStatus = 1; // this sets our LED status variable
delay(50);
transmitStatus(9900, ledStatus); // now we transmit LED status back to the Pi Gateway that we turned the LED off
}
}
}
if (radio.ACKRequested())
{
radio.sendACK();
DEBUGln("ACK sent.");
}
// check if the onboard LED should be turned on or off
if ((millis() - lastBlinkTime) >= blinkLEDtime) {
lastBlinkTime = millis(); // update current time for the next time through the loop
digitalWrite(onboardLED, !digitalRead(onboardLED)); // this says in one simple line to flip-flop the status of the pin
}
// check if it is time to report the photoresistor's value to the Moteino USB gateway (receives data for the Raspberry Pi)
if ((millis() - lastPhotoResistorReport) >= photoResistorCheckTime) {
lastPhotoResistorReport = millis(); // update current time for the next time through the loop
int lightLevel = analogRead(photoResistor); // we read in the photoResistor level here (value can be 0 to 4095)
// publish the actual value of the light level. We will call this sensor ID data code "9912"
transmitStatus(9905, lightLevel);
}
} // this is the end of the loop
// The function below will transmit the LED status to our Moteino USB / Pi Gateway
void transmitStatus(int item, int status){
sprintf(payload, "%d:%d", item, status);
byte buffLen=strlen(payload);
radio.sendWithRetry(GATEWAYID, payload, buffLen);
DEBUG("Transmitted payload: ");
DEBUGln(payload);
delay(10);
}
19:45:04.993 -> EEPROM flash chip found, and is OK ...
19:45:04.993 -> Moteino Example : 915 Mhz...
19:45:35.049 -> Transmitted payload: 9905:752
19:45:35.177 -> Msg received from sender ID [1]
19:45:35.177 -> [RX_RSSI:-29]
19:45:35.177 -> Payload length = 0
19:45:56.174 -> Msg received from sender ID [1] LON
19:45:56.174 -> [RX_RSSI:-32]
19:45:56.174 -> Payload length = 3
19:45:56.382 -> Transmitted payload: 9900:1
19:45:57.324 -> Msg received from sender ID [1]
19:45:57.324 -> [RX_RSSI:-32]
19:45:57.324 -> Payload length = 0
19:46:03.679 -> Msg received from sender ID [1] LOF
19:46:03.725 -> [RX_RSSI:-31]
19:46:03.725 -> Payload length = 3
19:46:03.889 -> Transmitted payload: 9900:0
19:46:04.805 -> Msg received from sender ID [1]
19:46:04.805 -> [RX_RSSI:-31]
19:46:04.805 -> Payload length = 0
19:46:05.007 -> Transmitted payload: 9905:753
19:46:12.271 -> Msg received from sender ID [1] LON
19:46:12.271 -> [RX_RSSI:-32]
19:46:12.271 -> Payload length = 3
19:46:12.458 -> Transmitted payload: 9900:1
19:46:13.413 -> Msg received from sender ID [1]
19:46:13.413 -> [RX_RSSI:-32]
19:46:13.413 -> Payload length = 0
19:46:18.040 -> Msg received from sender ID [1] LOF
19:46:18.040 -> [RX_RSSI:-32]
19:46:18.040 -> Payload length = 3
19:46:18.174 -> Transmitted payload: 9900:0
19:46:19.150 -> Msg received from sender ID [1]
19:46:19.150 -> [RX_RSSI:-31]
19:46:19.150 -> Payload length = 0
19:46:27.484 -> Msg received from sender ID [1] LON
19:46:27.484 -> [RX_RSSI:-32]
19:46:27.484 -> Payload length = 3
19:46:27.660 -> Transmitted payload: 9900:1
19:46:28.607 -> Msg received from sender ID [1]
19:46:28.641 -> [RX_RSSI:-31]
19:46:28.641 -> Payload length = 0
19:46:30.601 -> Msg received from sender ID [1] LOF
19:46:30.635 -> [RX_RSSI:-32]
19:46:30.635 -> Payload length = 3
19:46:30.822 -> Transmitted payload: 9900:0
19:46:31.729 -> Msg received from sender ID [1]
19:46:31.764 -> [RX_RSSI:-32]
19:46:31.764 -> Payload length = 0
19:46:34.912 -> Transmitted payload: 9905:763
19:46:35.775 -> Msg received from sender ID [1]
19:46:35.775 -> [RX_RSSI:-30]
19:46:35.775 -> Payload length = 0
19:47:04.856 -> Transmitted payload: 9905:761
19:47:05.702 -> Msg received from sender ID [1]
19:47:05.702 -> [RX_RSSI:-31]
19:47:05.702 -> Payload length = 0
19:47:34.803 -> Transmitted payload: 9905:756
19:47:35.650 -> Msg received from sender ID [1]
19:47:35.650 -> [RX_RSSI:-31]
19:47:35.650 -> Payload length = 0
19:48:04.735 -> Transmitted payload: 9905:759
19:48:05.588 -> Msg received from sender ID [1]
19:48:05.588 -> [RX_RSSI:-32]
19:48:05.588 -> Payload length = 0
7:48:35 PM : {"_id":44,"updated":1547689715421,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":754,"unit":" level","updated":1547689715421},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:48:05 PM : {"_id":44,"updated":1547689685480,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":759,"unit":" level","updated":1547689685480},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:47:35 PM : {"_id":44,"updated":1547689655540,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547689655540},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:47:05 PM : {"_id":44,"updated":1547689625597,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689625597},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:46:35 PM : {"_id":44,"updated":1547689595656,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":763,"unit":" level","updated":1547689595656},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:46:31 PM : {"_id":44,"updated":1547689591639,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:46:28 PM : {"_id":44,"updated":1547689588519,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"ON","updated":1547689588519}}}
7:46:25 PM : {"_id":44,"updated":1547689579028,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689579028}}}
7:46:19 PM : {"_id":44,"updated":1547689579028,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689579028}}}
7:46:13 PM : {"_id":44,"updated":1547689573299,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"ON","updated":1547689573299}}}
7:46:04 PM : {"_id":44,"updated":1547689564689,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689564689}}}
7:45:57 PM : {"_id":44,"updated":1547689557216,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"ON","updated":1547689557216}}}
7:45:35 PM : {"_id":44,"updated":1547689535066,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:45:04 PM : {"_id":44,"updated":1547689504116,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689486129},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:44:46 PM : {"_id":44,"updated":1547689486129,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689486129},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:44:16 PM : {"_id":44,"updated":1547689456187,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689456187},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:43:46 PM : {"_id":44,"updated":1547689426245,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689426245},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:43:33 PM : {"_id":44,"updated":1547689413234,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689395663},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:43:26 PM : {"_id":44,"updated":1547689406769,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689395663},"LED Status":{"label":"LED Status","value":"ON","updated":1547689406769}}}
7:43:15 PM : {"_id":44,"updated":1547689395663,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689395663}}}
7:43:06 PM : {"_id":44,"updated":1547689365722,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":753,"unit":" level","updated":1547689365722}}}
7:42:45 PM : {"_id":44,"updated":1547689365722,"metrics":{"Light Level":{"label":"Light Level","value":753,"unit":" level","updated":1547689365722}}}
7:41:39 PM : SERVERTIME OFFSET: 195ms
7:41:39 PM : Connected!
7:41:34 PM : Disconnected!
7:35:12 PM : SERVERTIME OFFSET: 172ms
7:35:12 PM : Connected!
7:35:06 PM : Disconnected!
7:29:50 PM : SERVERTIME OFFSET: 230ms
7:29:50 PM : Connected!
7:29:47 PM : Disconnected!
/* ***************************************************************************************************
// Example sketch from John's DIY Playground
// to demonstrate the Moteino IoT device using an RFM69 transceiver attached to it.
// Visit http://www.lowpowerlab.com/ to purchase a Moteino of your own
//
// This sketch will demonstrate a few basic features of the Moteino:
// 1. It will flash the onboard LED located at pin D9
// 2. It will report sensor light levels from a photoresistor on pin A5 to the Home Automation gateway
// 3. It will allow us to control an LED connected to pin D3 remotely
//
// Demonstration of this code can be found on my YouTube channel, called John's DIY Playground
// The channel's URL is http://www.youtube.com/c/johnsdiyplayground
// Software code examples can be found on my GitHub page at
// https://github.com/johnsdiyplayground
//
// Hardware Required:
// 1. Moteino or Moteino USB with RFM69 transceiver (http://www.lowpowerlab.com/)
// 2. LED
// 3. 2 quantity of 220 ohm resistor for the external LED and photoresistor circuits
// Put the resistors in series; the LED to ground and the other from photoresistor A5 to ground
// 4. Photoresistor
// 5. USB to micro USB cable for powering the Moteino
// 6. Another USB Moteino with the Pi Gateway code loaded on it and connected to a Raspberry Pi
// NOTE: this second Moteino must have the same frequency RFM69 transceiver attached to it
// 7. FTDI USB to Moteino programming interface (Not needed if you are using Moteino USB devices)
******************************************************************************************************
*/
#include <RFM69.h> //get it here: http://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <RFM69_OTA.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <SPIFlash.h> //get it here: http://github.com/lowpowerlab/spiflash
//#include <WirelessHEX69.h> //Replaced by rfm69_ota.h
#include <SPI.h> //comes with Arduino IDE (www.arduino.cc)
#define SERIAL_EN //comment out if you don't want any serial output
//*****************************************************************************************************************************
// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS
//*****************************************************************************************************************************
#define GATEWAYID 1 // this is the node ID of your gateway (which is probably tied to a Raspberry Pi)
#define NODEID 44 // must be unique to each sensor node
#define NETWORKID 200 // every node must match the same network ID to hear messages from each other and take actions directly
//#define FREQUENCY RF69_433MHZ
//#define FREQUENCY RF69_868MHZ
#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino's transceiver! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY "$d4N1BO99l2G.()[" //has to be same 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*****************************************************************************************************************************
#ifdef SERIAL_EN
#define SERIAL_BAUD 115200
#define DEBUG(input) {Serial.print(input); delay(1);}
#define DEBUGln(input) {Serial.println(input); delay(1);}
#else
#define DEBUG(input);
#define DEBUGln(input);
#define SERIALFLUSH();
#endif
// Define our pins
#define onboardLED 9 // Moteino onboard LED is on digital pin 9
#define photoResistor A5
#define photoResistorPower A2 // The photoresistor will be hooked to pins A2 and A5
#define externalLED 3 // careful about which pins are already in use by Moteino's RFM69 transceiver!
// For example, on Moteino you CANNOT use D2, D8, D10, D11, D12, D13!!
// Now we will define how often to flash our onboard LED
const long blinkLEDtime = 1000; // 1000 is milliseconds so this means blink on/off in 1 second intervals
// and we need a way to record the last time we turned the LED on or off
unsigned long lastBlinkTime;
// The next variable defines how often to check the photoresistor's light level
const long photoResistorCheckTime = 30000; // 10000 milliseconds is 10 seconds
// and we also record the time we report the photoresistor status with this
unsigned long lastPhotoResistorReport;
// We don't need to define how often to check commands to turn on/off the external LED. That's because
// our Moteino will respond to commands to request it come on or off from the Raspberry Pi / Moteino gateway device.
// The only thing we do track is the external LED's current status as on (1) or off (0)
int ledStatus;
char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //this is for transmitting to the Pi Gateway
byte STATUS;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)
void setup() {
#ifdef SERIAL_EN
Serial.begin(SERIAL_BAUD);
#endif
// Tell Moteino if our pins are inputs or outputs
pinMode(onboardLED, OUTPUT);
pinMode(photoResistor, INPUT);
pinMode(photoResistorPower, OUTPUT);
pinMode(externalLED, OUTPUT);
// Initialize our onboard and external LEDs to start up turned off (set to low)
digitalWrite(onboardLED, LOW);
digitalWrite(externalLED, LOW);
// Turn on power to the photoresistor
digitalWrite(photoResistorPower, HIGH);
// Initialize our timers for the onboard LED and photoresistor using millis which is the Photon's internal clock
lastBlinkTime = millis();
lastPhotoResistorReport = millis();
char buff[20]; // create a variable called buff (short for "buffer") that can hold up to 20 characters
radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
radio.setHighPower(); //uncomment only for RFM69HW!
#endif
radio.encrypt(ENCRYPTKEY);
if (flash.initialize()){
DEBUGln("EEPROM flash chip found, and is OK ...");
}
else
DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");
sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); // sprintf command creates a string to put in the buff variable
DEBUGln(payload); // check what we are transmitting to the gateway receiver
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen))
{
DEBUGln("Init: ACK Success!");
}
else
{
DEBUGln("Init: ACK Fail!");
}
// We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
if (radio.sendWithRetry(GATEWAYID, "9900:0", 6))
{
DEBUGln("Startup: ACK Success!");
}
else
{
DEBUGln("Startup: ACK Fail!");
}
delay(5000);
}
void loop() {
// wireless programming token check
// DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
CheckForWirelessHEX(radio, flash, true);
// check for messages from the home automation gateway or other Moteino nodes
if (radio.receiveDone()){
DEBUG("Msg received from sender ID ");DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
for (byte i = 0; i < radio.DATALEN; i++)
DEBUG((char)radio.DATA[i]);
DEBUGln();
//first send any ACK to request
DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUGln("]");
DEBUG(" Payload length = ");
DEBUGln(radio.DATALEN);
if (radio.DATALEN==3){
//check for a web page request from Pi Gateway to turn on or off the external LED
//we will receive from the Pi Gateway either a message of "LOF" or LON"
if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='F'){ // "LOF" is short for "LED off", keep radio messages short for best results
digitalWrite(externalLED, LOW); // Tell our external LED to turn OFF
ledStatus = 0; // this sets our LED status variable
delay(50);
transmitStatus(9900, ledStatus); // now we transmit LED status back to the Pi Gateway that we turned the LED off using transmitStatus subroutine
// We are passing a unique 4-digit number to identify a unique data type for our Pi Gateway, since it listens
// to a lot of sensor nodes in our house. Each sensor node gets its own set of 4-digit codes.
// Any time we transmit an LED status, we will always identify it with sensor code "9900"
}
else if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='N'){ // "LON" is short for "LED on"
digitalWrite(externalLED, HIGH); // Tell our external LED to turn ON
ledStatus = 1; // this sets our LED status variable
delay(50);
transmitStatus(9900, ledStatus); // now we transmit LED status back to the Pi Gateway that we turned the LED off
}
}
}
if (radio.ACKRequested())
{
radio.sendACK();
DEBUGln("ACK sent.");
}
// check if the onboard LED should be turned on or off
if ((millis() - lastBlinkTime) >= blinkLEDtime) {
lastBlinkTime = millis(); // update current time for the next time through the loop
digitalWrite(onboardLED, !digitalRead(onboardLED)); // this says in one simple line to flip-flop the status of the pin
}
// check if it is time to report the photoresistor's value to the Moteino USB gateway (receives data for the Raspberry Pi)
if ((millis() - lastPhotoResistorReport) >= photoResistorCheckTime) {
lastPhotoResistorReport = millis(); // update current time for the next time through the loop
int lightLevel = analogRead(photoResistor); // we read in the photoResistor level here (value can be 0 to 4095)
// publish the actual value of the light level. We will call this sensor ID data code "9912"
transmitStatus(9905, lightLevel);
}
} // this is the end of the loop
// The function below will transmit the LED status to our Moteino USB / Pi Gateway
void transmitStatus(int item, int status){
sprintf(payload, "%d:%d", item, status);
byte buffLen=strlen(payload);
if (radio.sendWithRetry(GATEWAYID, payload, buffLen))
{
DEBUGln("XMit ACK - Success!");
}
else
{
DEBUGln("XMit ACK - Fail!");
}
DEBUG("Transmitted payload: ");
DEBUGln(payload);
delay(10);
}
19:55:15.024 -> EEPROM flash chip found, and is OK ...
19:55:15.024 -> Moteino Example : 915 Mhz...
19:55:15.159 -> Init: ACK Fail!
19:55:15.289 -> Startup: ACK Fail!
19:55:20.266 -> Msg received from sender ID [1]
19:55:20.266 -> [RX_RSSI:-31]
19:55:20.266 -> Payload length = 0
19:55:40.838 -> Msg received from sender ID [1] LON
19:55:40.838 -> [RX_RSSI:-29]
19:55:40.838 -> Payload length = 3
19:55:41.025 -> XMit ACK - Fail!
19:55:41.025 -> Transmitted payload: 9900:1
19:55:41.948 -> Msg received from sender ID [1]
19:55:41.948 -> [RX_RSSI:-29]
19:55:41.981 -> Payload length = 0
19:55:44.394 -> Msg received from sender ID [1] LOF
19:55:44.394 -> [RX_RSSI:-29]
19:55:44.394 -> Payload length = 3
19:55:44.580 -> XMit ACK - Fail!
19:55:44.580 -> Transmitted payload: 9900:0
19:55:45.055 -> XMit ACK - Fail!
19:55:45.055 -> Transmitted payload: 9905:761
19:55:45.548 -> Msg received from sender ID [1]
19:55:45.548 -> [RX_RSSI:-29]
19:55:45.548 -> Payload length = 0
19:56:14.994 -> XMit ACK - Fail!
19:56:14.994 -> Transmitted payload: 9905:756
19:56:15.468 -> Msg received from sender ID [1]
19:56:15.503 -> [RX_RSSI:-29]
19:56:15.503 -> Payload length = 0
19:56:35.161 -> Msg received from sender ID [1] LON
19:56:35.161 -> [RX_RSSI:-30]
19:56:35.161 -> Payload length = 3
19:56:35.335 -> XMit ACK - Fail!
19:56:35.335 -> Transmitted payload: 9900:1
19:56:36.282 -> Msg received from sender ID [1]
19:56:36.282 -> [RX_RSSI:-31]
19:56:36.282 -> Payload length = 0
19:56:39.950 -> Msg received from sender ID [1] LOF
19:56:39.987 -> [RX_RSSI:-31]
19:56:39.987 -> Payload length = 3
19:56:40.148 -> XMit ACK - Fail!
19:56:40.148 -> Transmitted payload: 9900:0
19:56:41.085 -> Msg received from sender ID [1]
19:56:41.085 -> [RX_RSSI:-30]
19:56:41.120 -> Payload length = 0
19:56:44.953 -> XMit ACK - Fail!
19:56:44.953 -> Transmitted payload: 9905:763
19:56:45.117 -> Msg received from sender ID [1]
19:56:45.117 -> [RX_RSSI:-31]
19:56:45.117 -> Payload length = 0
19:57:14.863 -> XMit ACK - Fail!
19:57:14.863 -> Transmitted payload: 9905:762
19:57:15.039 -> Msg received from sender ID [1]
19:57:15.039 -> [RX_RSSI:-29]
19:57:15.039 -> Payload length = 0
7:57:15 PM : {"_id":44,"updated":1547690234950,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690234950},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690200986}}}
7:56:45 PM : {"_id":44,"updated":1547690205004,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":763,"unit":" level","updated":1547690205004},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690200986}}}
7:56:41 PM : {"_id":44,"updated":1547690200986,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547690175366},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690200986}}}
7:56:36 PM : {"_id":44,"updated":1547690196170,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547690175366},"LED Status":{"label":"LED Status","value":"ON","updated":1547690196170}}}
7:56:15 PM : {"_id":44,"updated":1547690175366,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547690175366},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690145425}}}
7:55:45 PM : {"_id":44,"updated":1547690145425,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690145425}}}
7:55:41 PM : {"_id":44,"updated":1547690141857,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"ON","updated":1547690141857}}}
7:55:15 PM : {"_id":44,"updated":1547690115739,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:55:13 PM : {"_id":44,"updated":1547690113691,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}