From 3370ac6265216ac90f4397f43ce90a4891bfe8c9 Mon Sep 17 00:00:00 2001 From: Felix Rusu Date: Sat, 13 Jul 2013 23:37:08 -0400 Subject: [PATCH] Add MoteinoR3(RFM69) wireless programming samples --- .../WirelessProgramming_gateway.ino | 78 +++++++++++ .../WirelessProgramming_node.ino | 131 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino create mode 100644 Examples/WirelessProgramming_node/WirelessProgramming_node.ino diff --git a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino new file mode 100644 index 0000000..c0bdeae --- /dev/null +++ b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino @@ -0,0 +1,78 @@ +/* + * 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 +// 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 +// These libraries and custom 1k Optiboot bootloader for the target node are at: http://github.com/lowpowerlab +#include +#include +#include +#include + +#define MYID 1 // node ID used for this unit +#define TARGET_ID 55 // ID of node being wirelessly reprogrammed +#define NETWORKID 250 +#define FREQUENCY RF69_915MHZ // Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define LED 9 +#define SERIAL_BAUD 115200 +#define ACK_TIME 50 // # of ms to wait for an ack +#define TIMEOUT 3000 +#define KEY "thisIsEncryptKey" + +RFM69 radio; +char c = 0; +char input[64]; //serial input buffer + +void setup(){ + Serial.begin(SERIAL_BAUD); + radio.initialize(FREQUENCY,MYID,NETWORKID); + //radio.encrypt(KEY); //OPTIONAL + Serial.print("Start wireless gateway..."); +} + +void loop(){ + byte inputLen = readSerialLine(input); + + if (inputLen == 4 && input[0]=='F' && input[1]=='L' && input[2]=='X' && input[3]=='?') { + CheckForSerialHEX((byte*)input, inputLen, radio, TARGET_ID, TIMEOUT, ACK_TIME, true); + } + else if (inputLen>0) { //just echo back + Serial.print("SERIAL IN > ");Serial.println(input); + } + + if (radio.receiveDone()) + { + for (byte i = 0; i < radio.DATALEN; i++) + Serial.print((char)radio.DATA[i]); + + if (radio.ACK_REQUESTED) + { + radio.sendACK(); + Serial.print(" - ACK sent"); + } + + Serial.println(); + } + Blink(LED,5); //heartbeat +} + +void Blink(byte PIN, int DELAY_MS) +{ + pinMode(PIN, OUTPUT); + digitalWrite(PIN,HIGH); + delay(DELAY_MS); + digitalWrite(PIN,LOW); +} diff --git a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino new file mode 100644 index 0000000..8b87946 --- /dev/null +++ b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino @@ -0,0 +1,131 @@ +/* + * 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 +// 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 +#include +#include +#include +#include + +#define MYID 55 // node ID used for this unit +#define NETWORKID 250 +#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define SERIAL_BAUD 115200 +#define ACK_TIME 50 // # of ms to wait for an ack +#define KEY "thisIsEncryptKey" + +RFM69 radio; +char input = 0; +long lastPeriod = -1; + +////////////////////////////////////////// +// flash(SPI_CS, MANUFACTURER_ID) +// SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) +// MANUFACTURER_ID - OPTIONAL, 0x1F44 for adesto(ex atmel) 4mbit flash +// 0xEF30 for windbond 4mbit flash +////////////////////////////////////////// +SPIFlash flash(8, 0xEF40); //EF30 for windbond 4mbit flash, EF40 for 16/64mbit + +void setup(){ + Serial.begin(SERIAL_BAUD); + radio.initialize(FREQUENCY,MYID,NETWORKID); + //radio.encrypt(KEY); //OPTIONAL + //radio.setHighPower(); //for RFM69HW only! + Serial.print("Start node..."); + + if (flash.initialize()) + Serial.println("SPI Flash Init OK!"); + else + Serial.println("SPI Flash Init FAIL!"); +} + +void loop(){ + // This part is optional, useful for some debugging. + // Handle serial input (to allow basic DEBUGGING of FLASH chip) + // ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc + if (Serial.available() > 0) { + input = Serial.read(); + if (input == 'd') //d=dump first page + { + Serial.println("Flash content:"); + int counter = 0; + + while(counter<=256){ + Serial.print(flash.readByte(counter++), HEX); + Serial.print('.'); + } + + Serial.println(); + } + else if (input == 'e') + { + Serial.print("Erasing Flash chip ... "); + flash.chipErase(); + while(flash.busy()); + Serial.println("DONE"); + } + else if (input == 'i') + { + Serial.print("DeviceID: "); + Serial.println(flash.readDeviceId(), HEX); + } + else if (input == 'r') + { + Serial.print("Rebooting"); + resetUsingWatchdog(true); + } + else if (input == 'R') + { + Serial.print("RFM69 registers:"); + radio.readAllRegs(); + } + else if (input >= 48 && input <= 57) //0-9 + { + Serial.print("\nWriteByte("); Serial.print(input); Serial.print(")"); + flash.writeByte(input-48, millis()%2 ? 0xaa : 0xbb); + } + } + + // Check for existing RF data, potentially for a new sketch wireless upload + // For this to work this check has to be done often enough to be + // picked up when a GATEWAY is trying hard to reach this node for a new sketch wireless upload + if (radio.receiveDone()) + { + Serial.print("Got ["); + Serial.print(radio.SENDERID); + Serial.print(':'); + Serial.print(radio.DATALEN); + Serial.print("] > "); + for (byte i = 0; i < radio.DATALEN; i++) + Serial.print((char)radio.DATA[i], HEX); + Serial.println(); + CheckForWirelessHEX(radio, flash, true); + Serial.println(); + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // Real sketch code here, let's blink the onboard LED every 0.5sec + if ((int)(millis()/500) > lastPeriod) + { + lastPeriod++; + pinMode(9, OUTPUT); + digitalWrite(9, lastPeriod%2); + } + //////////////////////////////////////////////////////////////////////////////////////////// +}