publish libraries to avoid users to have to download them one by one
This commit is contained in:
1 parent
93c075e880
commit
f0546fab8c
396 files changed
+536928
No files matched your search
@@ -0,0 +1,317 @@
|
||||
#**********************************************************************************
|
||||
# This script will handle the transmission of a compiled sketch in the
|
||||
# form of an INTEL HEX flash image to an attached gateway/master Moteino node,
|
||||
# for further wireless transmission to a target Moteino node that will receive it de-HEXified and
|
||||
# store it in external memory. Once received by the target (which is also loaded with a custom bootloader
|
||||
# capable of reading back that image) it will reset and reprogram itself with the new sketch
|
||||
#
|
||||
# EXAMPLE command line: python WirelessProgramming.py -f PathToFile.hex -s COM100 -t 123
|
||||
# where -t is the target ID of the Moteino you are programming
|
||||
# and -s is the serial port of the programmer Moteino (on linux/osx it is something like ttyAMA0)
|
||||
# To get the .hex file path go to Arduino>file>preferences and check the verbosity for compilation
|
||||
# then you will get the path in the debug status area once the sketch compiles
|
||||
#**********************************************************************************
|
||||
# Copyright Felix Rusu, LowPowerLab.com
|
||||
# Library and code by Felix Rusu - 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General
|
||||
# Public License along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# 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
|
||||
# **********************************************************************************
|
||||
import time, sys, serial
|
||||
import collections
|
||||
import re
|
||||
|
||||
### GENERAL SETTINGS ###
|
||||
SERIALPORT = "COM100" # the default com/serial port the receiver is connected to
|
||||
BAUDRATE = 115200 # default baud rate we talk to Moteino
|
||||
TARGET=0 # Node ID of the Target that is being OTA reflashed
|
||||
HEX = "flash.hex" # the HEX file containing the new program for the Target
|
||||
LINESPERPACKET = 3 # HEX lines to send per RF packet (1,2 or 3)
|
||||
retries = 2
|
||||
DEBUG = False
|
||||
|
||||
# Read command line arguments
|
||||
if (sys.argv and len(sys.argv) > 1):
|
||||
if len(sys.argv)==2 and (sys.argv[1] == "-h" or sys.argv[1] == "-help" or sys.argv[1] == "?"):
|
||||
#print " -d or -debug Turn debugging ON (verbose output)"
|
||||
print " -f or -file HEX file to upload (Default: ", HEX, ")"
|
||||
print " -t or -target {ID} Specify WirelessProgramming node target"
|
||||
print " -l or -lines {1,2,3} HEX lines per RF packet (Default: 3)"
|
||||
print " -s or -serial {port} Specify serial port of WirelessProgramming gateway (Default: ", SERIALPORT, ")"
|
||||
print " -b or -baud {baud} Specify serial port baud rate (Default: ", BAUDRATE, ")"
|
||||
print " -h or -help or ? Print this message"
|
||||
exit(0)
|
||||
|
||||
for i in range(len(sys.argv)):
|
||||
#{
|
||||
#if sys.argv[i] == "-d" or sys.argv[i] == "-debug":
|
||||
# DEBUG = True
|
||||
if (sys.argv[i] == "-s" or sys.argv[i] == "-serial") and len(sys.argv) >= i+2:
|
||||
SERIALPORT = sys.argv[i+1]
|
||||
if (sys.argv[i] == "-b" or sys.argv[i] == "-baud") and len(sys.argv) >= i+2:
|
||||
BAUD = sys.argv[i+1]
|
||||
if (sys.argv[i] == "-f" or sys.argv[i] == "-file") and len(sys.argv) >= i+2:
|
||||
HEX = sys.argv[i+1].strip()
|
||||
if (sys.argv[i] == "-t" or sys.argv[i] == "-target") and len(sys.argv) >= i+2:
|
||||
if sys.argv[i+1].isdigit() and int(sys.argv[i+1])>0 and int(sys.argv[i+1])<=255:
|
||||
TARGET = int(sys.argv[i+1])
|
||||
else:
|
||||
print "TARGET invalid (", sys.argv[i+1], "), must be 1-255."
|
||||
exit(1)
|
||||
if (sys.argv[i] == "-l" or sys.argv[i] == "-lines") and len(sys.argv) >= i+2:
|
||||
if sys.argv[i+1].isdigit() and int(sys.argv[i+1])>0 and int(sys.argv[i+1])<=3:
|
||||
LINESPERPACKET = int(sys.argv[i+1])
|
||||
else:
|
||||
print "LINESPERPACKET invalid (", sys.argv[i+1], "), must be 1-3."
|
||||
exit(1)
|
||||
#}
|
||||
|
||||
def millis():
|
||||
return int(round(time.time() * 1000))
|
||||
|
||||
def serWriteln(ser, msg):
|
||||
#ser.write(msg + '\n')
|
||||
ser.write(bytes((msg+'\n').encode('utf-8')))
|
||||
|
||||
HANDSHAKE_OK = 0
|
||||
HANDSHAKE_FAIL = 1
|
||||
HANDSHAKE_FAIL_TIMEOUT = 2
|
||||
HANDSHAKE_ERROR = 3
|
||||
|
||||
def waitForHandshake(isEOF=False):
|
||||
now = millis()
|
||||
while True:
|
||||
if millis()-now < 4000:
|
||||
#{
|
||||
if isEOF:
|
||||
serWriteln(ser, "FLX?EOF")
|
||||
else:
|
||||
serWriteln(ser, "FLX?")
|
||||
print "FLX?\n"
|
||||
ser.flush()
|
||||
rx = ser.readline().rstrip().upper()
|
||||
|
||||
if len(rx) > 0:
|
||||
#{
|
||||
print "Moteino: [" + rx + "]"
|
||||
if rx == "FLX?OK":
|
||||
print "HANDSHAKE OK!"
|
||||
return HANDSHAKE_OK
|
||||
elif rx == "FLX?NOK":
|
||||
print "HANDSHAKE FAIL [TIMEOUT]: " + rx
|
||||
return HANDSHAKE_FAIL
|
||||
elif (len(rx)>7 and rx.startswith("FLX?NOK") or rx.startswith("FLX?ERR")):
|
||||
print "HANDSHAKE FAIL [HEX IMG refused by target node], reason: " + rx
|
||||
return HANDSHAKE_FAIL_ERROR
|
||||
#}
|
||||
#}
|
||||
else: return HANDSHAKE_FAIL_TIMEOUT
|
||||
|
||||
def waitForTargetSet(targetNode):
|
||||
now = millis()
|
||||
to = "TO:" + str(TARGET)
|
||||
print to
|
||||
serWriteln(ser, to)
|
||||
ser.flush()
|
||||
while True:
|
||||
#{
|
||||
if millis()-now < 3000:
|
||||
#{
|
||||
rx = ser.readline().rstrip()
|
||||
if len(rx) > 0:
|
||||
#{
|
||||
print "Moteino: [" + rx + "]"
|
||||
if rx == to + ":OK":
|
||||
return True
|
||||
else: return False
|
||||
#}
|
||||
#}
|
||||
#}
|
||||
return False
|
||||
|
||||
# return 0:timeout, 1:OK!, 2:match but out of synch
|
||||
def waitForSEQ(seq):
|
||||
now = millis()
|
||||
while True:
|
||||
if millis()-now < 3000:
|
||||
rx = ser.readline().strip()
|
||||
|
||||
if (rx.upper().startswith("RFTX >") or rx.upper().startswith("RFACK >")):
|
||||
#{
|
||||
print "Moteino DEBUG: " + rx
|
||||
rx = ""
|
||||
continue
|
||||
#}
|
||||
|
||||
if len(rx) > 0:
|
||||
#{
|
||||
print "Moteino: " + rx
|
||||
result = re.match("FLX:([0-9]*):OK", rx)
|
||||
if result != None:
|
||||
if int(result.group(1)) == seq:
|
||||
return 1
|
||||
else: return 2
|
||||
#}
|
||||
else: return 0
|
||||
|
||||
# MAIN()
|
||||
#if __name__ == "__main__":
|
||||
try:
|
||||
start = millis();
|
||||
# open up the serial port to get data transmitted to Programmer Moteino
|
||||
ser = serial.Serial(SERIALPORT, BAUDRATE, timeout=1) #timeout=0 means nonblocking
|
||||
ser.setDTR(False)
|
||||
ser.setRTS(False)
|
||||
time.sleep(2) #wait for Programmer Moteino reset after port open and potential bootloader time (~1.6s)
|
||||
ser.flushInput();
|
||||
except IOError as e:
|
||||
print "COM Port [", SERIALPORT, "] not found, exiting..."
|
||||
exitNow(1)
|
||||
|
||||
try:
|
||||
if not 0<TARGET<= 255:
|
||||
print "TARGET not provided (use -h for help), now exiting..."
|
||||
exit(1)
|
||||
|
||||
#send target ID first
|
||||
if waitForTargetSet(TARGET):
|
||||
print "TARGET SET OK"
|
||||
else:
|
||||
print "TARGET SET FAIL, exiting..."
|
||||
exit(1)
|
||||
|
||||
with open(HEX) as f:
|
||||
print "File found, passing to Moteino..."
|
||||
|
||||
handshakeResponse = waitForHandshake()
|
||||
if (handshakeResponse == HANDSHAKE_OK):
|
||||
seq = 0
|
||||
packetCounter = 0
|
||||
content = f.readlines()
|
||||
|
||||
while seq < len(content):
|
||||
#{
|
||||
currentLine = content[seq].strip()
|
||||
isEOF = (content[seq].strip() == ":00000001FF") #this should be the last line in any valid intel HEX file
|
||||
result = -1
|
||||
bundledLines = 1
|
||||
|
||||
if isEOF==False:
|
||||
#{
|
||||
hexDataToSend = currentLine
|
||||
|
||||
#bundle 2 or 3 HEX lines in 1 RF packet (assuming: 1 HEX line has 16 bytes of data, following HEX lines also each being 16 bytes)
|
||||
if LINESPERPACKET > 1 and currentLine[1:3] == '10' and len(currentLine)==43:
|
||||
#{
|
||||
#check if next line != EOF, so we can bundle 2 lines
|
||||
nextLine = content[seq+1].strip()
|
||||
if nextLine != ":00000001FF" and nextLine[1:3] == "10" and len(nextLine) == 43:
|
||||
#{
|
||||
#need to sum: the 2 lines checksums + address bytes of nextLine (to arrive at a correct final checksum of combined 2 lines
|
||||
checksum = int(currentLine[41:43], 16) + int(nextLine[41:43], 16) + int(nextLine[3:5], 16) + int(nextLine[5:7], 16)
|
||||
|
||||
#check if a third line != EOF, so we can bundle 3 lines
|
||||
nextLine2 = content[seq+2].strip()
|
||||
if LINESPERPACKET==3 and nextLine2 != ":00000001FF" and nextLine2[1:3] == "10" and len(nextLine2) == 43:
|
||||
#{
|
||||
#need to sum: the previous checksum + address bytes of nextLine2 (to arrive at a correct final checksum of combined 3 lines
|
||||
checksum += int(nextLine2[41:43], 16) + int(nextLine2[3:5], 16) + int(nextLine2[5:7], 16)
|
||||
hexDataToSend = ":3" + hexDataToSend[2:(len(hexDataToSend)-2)] + nextLine[9:41] + nextLine2[9:41] + ('%0*X' % (2,checksum%256))
|
||||
bundledLines=3
|
||||
#}
|
||||
else:
|
||||
#{
|
||||
hexDataToSend = ":2" + hexDataToSend[2:(len(hexDataToSend)-2)] + nextLine[9:41] + ('%0*X' % (2,checksum%256))
|
||||
bundledLines=2;
|
||||
#}
|
||||
#}
|
||||
#}
|
||||
tx = "FLX:" + str(packetCounter) + hexDataToSend
|
||||
print "TX > " + tx
|
||||
serWriteln(ser, tx)
|
||||
result = waitForSEQ(packetCounter)
|
||||
#}
|
||||
elif waitForHandshake(True) == HANDSHAKE_OK:
|
||||
#{
|
||||
print "SUCCESS! (time elapsed: " + ("%.2f" % ((millis()-start)/1000.0)) + "s)"
|
||||
exit(0);
|
||||
#}
|
||||
else:
|
||||
#{
|
||||
print "FAIL, IMG REFUSED BY TARGET (size exceeded? verify target MCU matches compiled target)"
|
||||
exit(99)
|
||||
#}
|
||||
|
||||
if result == 1:
|
||||
#{
|
||||
seq+=bundledLines
|
||||
packetCounter+=1
|
||||
#}
|
||||
elif result == 2: # out of synch, retry
|
||||
#{
|
||||
if retries > 0:
|
||||
retries-=1
|
||||
print "OUT OF SYNC: retrying...\n"
|
||||
continue
|
||||
else:
|
||||
print "FAIL: out of sync (are you running the latest OTA libs/sources?)"
|
||||
exit(1)
|
||||
#}
|
||||
else:
|
||||
#{
|
||||
if retries > 0:
|
||||
retries-=1
|
||||
print "Timeout, retry...\n"
|
||||
continue
|
||||
else:
|
||||
#{
|
||||
print "FAIL: timeout (are you running the latest OTA libs/sources?)"
|
||||
exit(1)
|
||||
#}
|
||||
#}
|
||||
#}
|
||||
|
||||
while 1:
|
||||
#{
|
||||
rx = ser.readline()
|
||||
if (len(rx) > 0): print rx.strip()
|
||||
#}
|
||||
|
||||
elif (handshakeResponse == HANDSHAKE_FAIL_TIMEOUT):
|
||||
print "FAIL: No response from Moteino programmer, is it connected to " + port
|
||||
exit(1)
|
||||
elif (handshakeResponse == HANDSHAKE_FAIL_TIMEOUT):
|
||||
print "FAIL: No response from Moteino programmer, is it connected to " + port
|
||||
exit(1)
|
||||
else:
|
||||
print "FAIL: No response from Moteino Target, is Target listening on same Freq/NetworkID & OTA enabled?"
|
||||
exit(1)
|
||||
|
||||
except IOError:
|
||||
print "File [", HEX, "] not found, exiting..."
|
||||
exit(1)
|
||||
|
||||
finally:
|
||||
#print 'FINALLY' + '\n'
|
||||
ser.close()
|
||||
@@ -0,0 +1,164 @@
|
||||
// **********************************************************************************
|
||||
// This sketch is an example of how wireless programming can be achieved with a Moteino
|
||||
// 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 RFM69 library
|
||||
// These libraries and custom 1k Optiboot bootloader for the target node are at: http://github.com/lowpowerlab
|
||||
// **********************************************************************************
|
||||
// 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://www.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 254 //this node's ID, should be unique among nodes on this NETWORKID
|
||||
#define NETWORKID 100 //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
|
||||
#define FREQUENCY RF69_915MHZ
|
||||
#define FREQUENCY_EXACT 916000000
|
||||
#define ENCRYPTKEY "sampleEncryptKey" //(16 bytes of your choice - keep the same on all encrypted nodes)
|
||||
#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
|
||||
//*********************************************************************************************
|
||||
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL
|
||||
//*********************************************************************************************
|
||||
//#define BR_300KBPS //run radio at max rate of 300kbps!
|
||||
//*********************************************************************************************
|
||||
#define DEBUG_MODE false //set 'true' to see verbose output from programming sequence
|
||||
|
||||
#define SERIAL_BAUD 115200
|
||||
#define ACK_TIME 50 // # of ms to wait for an ack
|
||||
#define TIMEOUT 3000
|
||||
|
||||
#ifdef __AVR_ATmega1284P__
|
||||
#define LED 15 // MoteinoMEGA has LED on D15
|
||||
#else
|
||||
#define LED 9 // Moteino has LED on D9
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ATC
|
||||
RFM69_ATC radio;
|
||||
#else
|
||||
RFM69 radio;
|
||||
#endif
|
||||
|
||||
char c = 0;
|
||||
char input[64]; //serial input buffer
|
||||
byte targetID=0;
|
||||
|
||||
void setup(){
|
||||
Serial.begin(SERIAL_BAUD);
|
||||
radio.initialize(FREQUENCY,NODEID,NETWORKID);
|
||||
radio.encrypt(ENCRYPTKEY); //OPTIONAL
|
||||
|
||||
#ifdef FREQUENCY_EXACT
|
||||
radio.setFrequency(FREQUENCY_EXACT); //set frequency to some custom frequency
|
||||
#endif
|
||||
|
||||
#ifdef IS_RFM69HW_HCW
|
||||
radio.setHighPower(); //must include this only for RFM69HW/HCW!
|
||||
#endif
|
||||
Serial.println("Start wireless gateway...");
|
||||
|
||||
#ifdef BR_300KBPS
|
||||
radio.writeReg(0x03, 0x00); //REG_BITRATEMSB: 300kbps (0x006B, see DS p20)
|
||||
radio.writeReg(0x04, 0x6B); //REG_BITRATELSB: 300kbps (0x006B, see DS p20)
|
||||
radio.writeReg(0x19, 0x40); //REG_RXBW: 500kHz
|
||||
radio.writeReg(0x1A, 0x80); //REG_AFCBW: 500kHz
|
||||
radio.writeReg(0x05, 0x13); //REG_FDEVMSB: 300khz (0x1333)
|
||||
radio.writeReg(0x06, 0x33); //REG_FDEVLSB: 300khz (0x1333)
|
||||
radio.writeReg(0x29, 240); //set REG_RSSITHRESH to -120dBm
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop(){
|
||||
byte inputLen = readSerialLine(input, 10, 64, 100); //readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=1000);
|
||||
|
||||
if (inputLen==4 && input[0]=='F' && input[1]=='L' && input[2]=='X' && input[3]=='?') {
|
||||
if (targetID==0)
|
||||
Serial.println("TO?");
|
||||
else
|
||||
CheckForSerialHEX((byte*)input, inputLen, radio, targetID, TIMEOUT, ACK_TIME, DEBUG_MODE);
|
||||
}
|
||||
else if (inputLen>3 && inputLen<=6 && input[0]=='T' && input[1]=='O' && input[2]==':')
|
||||
{
|
||||
byte newTarget=0;
|
||||
for (byte i = 3; i<inputLen; i++) //up to 3 characters for target ID
|
||||
if (input[i] >=48 && input[i]<=57)
|
||||
newTarget = newTarget*10+input[i]-48;
|
||||
else
|
||||
{
|
||||
newTarget=0;
|
||||
break;
|
||||
}
|
||||
if (newTarget>0)
|
||||
{
|
||||
targetID = newTarget;
|
||||
Serial.print("TO:");
|
||||
Serial.print(newTarget);
|
||||
Serial.println(":OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(input);
|
||||
Serial.print(":INV");
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Wireless Programming for Moteinos
|
||||
|
||||
## How to use
|
||||
Since v1.5 you can now run this app in several ways:
|
||||
- natively via the WirelessProgramming.exe GUI app
|
||||
- the windows GUI can also invoke the OTA.py script via embedded IronPython engine (parameters from GUI pass to the OTA.py script)
|
||||
- cross platform straight from Python (2.7 runtime) by supplying parameters (run `python OTA.py -h` for details)
|
||||
<br/>
|
||||
Make sure to download the entire repo ZIP, not individual files.
|
||||
@@ -0,0 +1,198 @@
|
||||
// **********************************************************************************
|
||||
// This sketch is an example of how wireless programming can be achieved with a Moteino
|
||||
// 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/RFM69_OTA library, which also relies on the RFM69 library
|
||||
// These libraries and custom 1k Optiboot bootloader are at: http://github.com/lowpowerlab
|
||||
// **********************************************************************************
|
||||
// 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 install (www.arduino.cc)
|
||||
|
||||
//****************************************************************************************************************
|
||||
//**** IMPORTANT RADIO SETTINGS - YOU MUST CHANGE/CONFIGURE TO MATCH YOUR HARDWARE TRANSCEIVER CONFIGURATION! ****
|
||||
//****************************************************************************************************************
|
||||
#define NODEID 123 // node ID used for this unit
|
||||
#define NETWORKID 100
|
||||
//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 FREQUENCY_EXACT 916000000
|
||||
#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
|
||||
//*****************************************************************************************************************************
|
||||
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL
|
||||
#define ATC_RSSI -75
|
||||
//*****************************************************************************************************************************
|
||||
//#define BR_300KBPS //run radio at max rate of 300kbps!
|
||||
//*****************************************************************************************************************************
|
||||
#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)
|
||||
#define BLINKPERIOD 500
|
||||
|
||||
#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 hsave LEDs on D9
|
||||
#define FLASH_SS 8 // and FLASH SS on D8
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ATC
|
||||
RFM69_ATC radio;
|
||||
#else
|
||||
RFM69 radio;
|
||||
#endif
|
||||
|
||||
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
|
||||
// 0xEF40 for windbond 16/64mbit flash
|
||||
//*****************************************************************************************************************************
|
||||
SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for windbond 4mbit flash
|
||||
|
||||
void setup() {
|
||||
pinMode(LED, OUTPUT);
|
||||
Serial.begin(SERIAL_BAUD);
|
||||
radio.initialize(FREQUENCY,NODEID,NETWORKID);
|
||||
radio.encrypt(ENCRYPTKEY); //OPTIONAL
|
||||
|
||||
#ifdef FREQUENCY_EXACT
|
||||
radio.setFrequency(FREQUENCY_EXACT); //set frequency to some custom frequency
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ATC
|
||||
radio.enableAutoPower(ATC_RSSI);
|
||||
#endif
|
||||
|
||||
#ifdef IS_RFM69HW_HCW
|
||||
radio.setHighPower(); //must include this only for RFM69HW/HCW!
|
||||
#endif
|
||||
Serial.print("Start node...");
|
||||
Serial.print("Node ID = ");
|
||||
Serial.println(NODEID);
|
||||
|
||||
if (flash.initialize())
|
||||
Serial.println("SPI Flash Init OK!");
|
||||
else
|
||||
Serial.println("SPI Flash Init FAIL!");
|
||||
|
||||
#ifdef BR_300KBPS
|
||||
radio.writeReg(0x03, 0x00); //REG_BITRATEMSB: 300kbps (0x006B, see DS p20)
|
||||
radio.writeReg(0x04, 0x6B); //REG_BITRATELSB: 300kbps (0x006B, see DS p20)
|
||||
radio.writeReg(0x19, 0x40); //REG_RXBW: 500kHz
|
||||
radio.writeReg(0x1A, 0x80); //REG_AFCBW: 500kHz
|
||||
radio.writeReg(0x05, 0x13); //REG_FDEVMSB: 300khz (0x1333)
|
||||
radio.writeReg(0x06, 0x33); //REG_FDEVLSB: 300khz (0x1333)
|
||||
radio.writeReg(0x29, 240); //set REG_RSSITHRESH to -120dBm
|
||||
#endif
|
||||
}
|
||||
|
||||
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, false);
|
||||
Serial.println();
|
||||
}
|
||||
//else Serial.print('.');
|
||||
|
||||
//*****************************************************************************************************************************
|
||||
// Real sketch code here, let's blink the onboard LED
|
||||
if ((int)(millis()/BLINKPERIOD) > lastPeriod)
|
||||
{
|
||||
lastPeriod++;
|
||||
digitalWrite(LED, lastPeriod%2);
|
||||
}
|
||||
//*****************************************************************************************************************************
|
||||
}
|
||||
Binary file not shown.
Reference in new issue
Block a user