diff --git a/Examples/Gateway/Gateway.ino b/Examples/Gateway/Gateway.ino index d934b88..491f743 100644 --- a/Examples/Gateway/Gateway.ino +++ b/Examples/Gateway/Gateway.ino @@ -4,9 +4,9 @@ // Library and code by Felix Rusu - felix@lowpowerlab.com // Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ -#include +#include //get it here: https://www.github.com/lowpowerlab/rfm69 #include -#include +#include //get it here: https://www.github.com/lowpowerlab/spiflash #define NODEID 1 //unique for each node on same network #define NETWORKID 100 //the same on all nodes that talk to each other @@ -40,19 +40,21 @@ void setup() { #endif radio.encrypt(ENCRYPTKEY); radio.promiscuous(promiscuousMode); + //radio.setFrequency(919000000); char buff[50]; sprintf(buff, "\nListening 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): "); + Serial.print("SPI Flash Init OK. Unique MAC = ["); flash.readUniqueId(); for (byte i=0;i<8;i++) { Serial.print(flash.UNIQUEID[i], HEX); - Serial.print(' '); + if (i!=8) Serial.print(':'); } - + Serial.println(']'); + //alternative way to read it: //byte* MAC = flash.readUniqueId(); //for (byte i=0;i<8;i++) @@ -60,12 +62,14 @@ void setup() { // Serial.print(MAC[i], HEX); // Serial.print(' '); //} + } else Serial.println("SPI Flash Init FAIL! (is chip present?)"); } byte ackCount=0; +uint32_t packetCount = 0; void loop() { //process any serial input if (Serial.available() > 0) @@ -123,6 +127,9 @@ void loop() { if (radio.receiveDone()) { + Serial.print("#["); + Serial.print(++packetCount); + Serial.print(']'); Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); if (promiscuousMode) { diff --git a/Examples/Node/Node.ino b/Examples/Node/Node.ino index c040a76..028c84b 100644 --- a/Examples/Node/Node.ino +++ b/Examples/Node/Node.ino @@ -28,7 +28,7 @@ #define SERIAL_BAUD 115200 -int TRANSMITPERIOD = 300; //transmit a packet to gateway so often (in ms) +int TRANSMITPERIOD = 150; //transmit a packet to gateway so often (in ms) char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char buff[20]; byte sendSize=0; @@ -43,6 +43,7 @@ void setup() { radio.setHighPower(); //uncomment only for RFM69HW! #endif radio.encrypt(ENCRYPTKEY); + //radio.setFrequency(919000000); //set frequency to some custom frequency char buff[50]; sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); Serial.println(buff); @@ -125,33 +126,37 @@ void loop() { radio.sendACK(); Serial.print(" - ACK sent"); } - Blink(LED,5); + Blink(LED,3); Serial.println(); } - //send FLASH id - if(sendSize==0) - { - sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId()); - byte buffLen=strlen(buff); - radio.sendWithRetry(GATEWAYID, buff, buffLen); - sendSize = (sendSize + 1) % 31; - } - int currPeriod = millis()/TRANSMITPERIOD; if (currPeriod != lastPeriod) { lastPeriod=currPeriod; - 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..."); - + + //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,3); diff --git a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino index ab5faa8..bb842da 100644 --- a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino +++ b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino @@ -1,30 +1,49 @@ -/* - * Copyright (c) 2013 by Felix Rusu - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either the GNU General Public License version 2 - * or the GNU Lesser General Public License version 2.1, both as - * published by the Free Software Foundation. - */ - +// ********************************************************************************** // This sketch is an example of how wireless programming can be achieved with a Moteino -// that was loaded with a custom 1k Optiboot that is capable of loading a new sketch from -// an external SPI flash chip +// that was loaded with a custom 1k bootloader (DualOptiboot) that is capable of loading +// a new sketch from an external SPI flash chip // This is the GATEWAY node, it does not need a custom Optiboot nor any external FLASH memory chip // (ONLY the target node will need those) // The sketch includes logic to receive the new sketch from the serial port (from a host computer) and // transmit it wirelessly to the target node // The handshake protocol that receives the sketch from the serial port -// is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM12B library +// is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM69 library // These libraries and custom 1k Optiboot bootloader for the target node are at: http://github.com/lowpowerlab - -#include +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// 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. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// 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 //get it here: https://www.github.com/lowpowerlab/rfm69 #include -#include -#include +#include //get it here: https://www.github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming/tree/master/WirelessHEX69 -#define NETWORKID 250 //what network this node is on #define NODEID 254 //this node's ID, should be unique among nodes on this NETWORKID +#define NETWORKID 250 //what network this node is on //Match frequency to the hardware version of the radio on your Moteino (uncomment one): //#define FREQUENCY RF69_433MHZ //#define FREQUENCY RF69_868MHZ diff --git a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino index 80581c4..267c677 100644 --- a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino +++ b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino @@ -1,35 +1,54 @@ -/* - * Copyright (c) 2013 by Felix Rusu - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either the GNU General Public License version 2 - * or the GNU Lesser General Public License version 2.1, both as - * published by the Free Software Foundation. - */ - +// ********************************************************************************** // This sketch is an example of how wireless programming can be achieved with a Moteino -// that was loaded with a custom 1k Optiboot that is capable of loading a new sketch from -// an external SPI flash chip +// that was loaded with a custom 1k bootloader (DualOptiboot) that is capable of loading +// a new sketch from an external SPI flash chip // The sketch includes logic to receive the new sketch 'over-the-air' and store it in // the FLASH chip, then restart the Moteino so the bootloader can continue the job of // actually reflashing the internal flash memory from the external FLASH memory chip flash image // The handshake protocol that receives the sketch wirelessly by means of the RFM69 radio // is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM69 library // These libraries and custom 1k Optiboot bootloader are at: http://github.com/lowpowerlab - -#include +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// 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. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// 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 //get it here: https://www.github.com/lowpowerlab/rfm69 #include -#include +#include //get it here: https://www.github.com/lowpowerlab/spiflash #include -#include +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming/tree/master/WirelessHEX69 -#define MYID 55 // node ID used for this unit +#define NODEID 123 // node ID used for this unit #define NETWORKID 250 //Match frequency to the hardware version of the radio on your Moteino (uncomment one): //#define FREQUENCY RF69_433MHZ //#define FREQUENCY RF69_868MHZ #define FREQUENCY RF69_915MHZ -#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! #define SERIAL_BAUD 115200 #define ACK_TIME 30 // # of ms to wait for an ack #define ENCRYPTKEY "sampleEncryptKey" //(16 bytes of your choice - keep the same on all encrypted nodes) @@ -59,7 +78,7 @@ SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for windbond 4mbit flash void setup(){ pinMode(LED, OUTPUT); Serial.begin(SERIAL_BAUD); - radio.initialize(FREQUENCY,MYID,NETWORKID); + radio.initialize(FREQUENCY,NODEID,NETWORKID); radio.encrypt(ENCRYPTKEY); //OPTIONAL #ifdef IS_RFM69HW radio.setHighPower(); //only for RFM69HW! diff --git a/RFM69.cpp b/RFM69.cpp index 68f17d4..9b35371 100644 --- a/RFM69.cpp +++ b/RFM69.cpp @@ -118,6 +118,7 @@ uint32_t RFM69::getFrequency() //set the frequency (in Hz) void RFM69::setFrequency(uint32_t freqHz) { + //TODO: p38 hopping sequence may need to be followed in some cases freqHz /= RF69_FSTEP; //divide down by FSTEP to get FRF writeReg(REG_FRFMSB, freqHz >> 16); writeReg(REG_FRFMID, freqHz >> 8); @@ -192,7 +193,7 @@ bool RFM69::canSend() void RFM69::send(byte toAddress, const void* buffer, byte bufferSize, bool requestACK) { writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks - long now = millis(); + unsigned long now = millis(); while (!canSend() && millis()-now < RF69_CSMA_LIMIT_MS) receiveDone(); sendFrame(toAddress, buffer, bufferSize, requestACK, false); } @@ -204,7 +205,7 @@ void RFM69::send(byte toAddress, const void* buffer, byte bufferSize, bool reque // requires user action to read the received data and decide what to do with it // replies usually take only 5-8ms at 50kbps@915Mhz bool RFM69::sendWithRetry(byte toAddress, const void* buffer, byte bufferSize, byte retries, byte retryWaitTime) { - long sentTime; + unsigned long sentTime; for (byte i=0; i<=retries; i++) { send(toAddress, buffer, bufferSize, true); @@ -237,9 +238,12 @@ bool RFM69::ACKRequested() { /// Should be called immediately after reception in case sender wants ACK void RFM69::sendACK(const void* buffer, byte bufferSize) { byte sender = SENDERID; - long now = millis(); + int _RSSI = RSSI; //save payload received RSSI value + writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks + unsigned long now = millis(); while (!canSend() && millis()-now < RF69_CSMA_LIMIT_MS) receiveDone(); sendFrame(sender, buffer, bufferSize, false, true); + RSSI = _RSSI; //restore payload RSSI } void RFM69::sendFrame(byte toAddress, const void* buffer, byte bufferSize, bool requestACK, bool sendACK) @@ -269,7 +273,8 @@ void RFM69::sendFrame(byte toAddress, const void* buffer, byte bufferSize, bool /* no need to wait for transmit mode to be ready since its handled by the radio */ setMode(RF69_MODE_TX); - while (digitalRead(_interruptPin) == 0); //wait for DIO0 to turn HIGH signalling transmission finish + unsigned long txStart = millis(); + while (digitalRead(_interruptPin) == 0 && millis()-txStart < RF69_TX_LIMIT_MS); //wait for DIO0 to turn HIGH signalling transmission finish //while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // Wait for ModeReady setMode(RF69_MODE_STANDBY); } @@ -286,13 +291,16 @@ void RFM69::interruptHandler() { PAYLOADLEN = SPI.transfer(0); PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; //precaution TARGETID = SPI.transfer(0); - if(!(_promiscuousMode || TARGETID==_address || TARGETID==RF69_BROADCAST_ADDR)) //match this node's address, or broadcast address or anything in promiscuous mode + if(!(_promiscuousMode || TARGETID==_address || TARGETID==RF69_BROADCAST_ADDR) //match this node's address, or broadcast address or anything in promiscuous mode + || PAYLOADLEN < 3) //address situation could receive packets that are malformed and don't fit this libraries extra fields { PAYLOADLEN = 0; unselect(); + receiveBegin(); //digitalWrite(4, 0); return; } + DATALEN = PAYLOADLEN - 3; SENDERID = SPI.transfer(0); byte CTLbyte = SPI.transfer(0); diff --git a/RFM69.h b/RFM69.h index 4e3dff3..b1e5747 100644 --- a/RFM69.h +++ b/RFM69.h @@ -65,6 +65,7 @@ #define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value #define RF69_BROADCAST_ADDR 255 #define RF69_CSMA_LIMIT_MS 1000 +#define RF69_TX_LIMIT_MS 1000 #define RF69_FSTEP 61.03515625 // == FXOSC/2^19 = 32mhz/2^19 (p13 in DS) class RFM69 { diff --git a/keywords.txt b/keywords.txt index c8a14a7..14aff85 100644 --- a/keywords.txt +++ b/keywords.txt @@ -23,6 +23,7 @@ receiveDone KEYWORD2 ACKReceived KEYWORD2 sendACK KEYWORD2 setFrequency KEYWORD2 +getFrequency KEYWORD2 encrypt KEYWORD2 setCS KEYWORD2 readRSSI KEYWORD2 @@ -49,4 +50,5 @@ SENDERID LITERAL2 TARGETID LITERAL2 PAYLOADLEN LITERAL2 ACK_REQUESTED LITERAL2 -ACK_RECEIVED LITERAL2 \ No newline at end of file +ACK_RECEIVED LITERAL2 +RSSI LITERAL2 \ No newline at end of file