diff --git a/Data Logger/AdafruitDHT.py b/Data Logger/DHT Test/AdafruitDHT.py similarity index 100% rename from Data Logger/AdafruitDHT.py rename to Data Logger/DHT Test/AdafruitDHT.py diff --git a/Data Logger/DataLog.py b/Data Logger/DataLog.py index 9d1267e..79820e8 100644 --- a/Data Logger/DataLog.py +++ b/Data Logger/DataLog.py @@ -28,7 +28,7 @@ def getInfo(): a = str(a) total = a[0:22] + " Temperature: " + str(temperature)[0:4] + " Humidity: " + str(humidity)[0:4] + " $ data.write(total) - print total + print(total) sleep(1) diff --git a/Date Time/DT test.py b/Data Logger/Date Time Test/DT test.py similarity index 100% rename from Date Time/DT test.py rename to Data Logger/Date Time Test/DT test.py diff --git a/Text Parse/Output/alt.txt b/GPS Parse/Output/alt.txt similarity index 100% rename from Text Parse/Output/alt.txt rename to GPS Parse/Output/alt.txt diff --git a/Text Parse/Output/output.txt b/GPS Parse/Output/output.txt similarity index 100% rename from Text Parse/Output/output.txt rename to GPS Parse/Output/output.txt diff --git a/Text Parse/TEST.py b/GPS Parse/TEST.py similarity index 100% rename from Text Parse/TEST.py rename to GPS Parse/TEST.py diff --git a/Text Parse/Text Parse.py b/GPS Parse/Text Parse.py similarity index 100% rename from Text Parse/Text Parse.py rename to GPS Parse/Text Parse.py diff --git a/Text Parse/input.txt b/GPS Parse/input.txt similarity index 100% rename from Text Parse/input.txt rename to GPS Parse/input.txt diff --git a/LoRa/LoRaTracker/HAB2/Board/GPS Breakout 200917 PCB.pdf b/LoRa/LoRaTracker/HAB2/Board/GPS Breakout 200917 PCB.pdf new file mode 100644 index 0000000..2f54d9e Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Board/GPS Breakout 200917 PCB.pdf differ diff --git a/LoRa/LoRaTracker/HAB2/Board/HAB2 Tracker RFM9x PCB 090218.pdf b/LoRa/LoRaTracker/HAB2/Board/HAB2 Tracker RFM9x PCB 090218.pdf new file mode 100644 index 0000000..61bfd0d Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Board/HAB2 Tracker RFM9x PCB 090218.pdf differ diff --git a/LoRa/LoRaTracker/HAB2/Build/HAB2 Minimum Parts Tracker Build.pdf b/LoRa/LoRaTracker/HAB2/Build/HAB2 Minimum Parts Tracker Build.pdf new file mode 100644 index 0000000..affce1a Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Build/HAB2 Minimum Parts Tracker Build.pdf differ diff --git a/LoRa/LoRaTracker/HAB2/Build/Versatile GPS Breakout board.pdf b/LoRa/LoRaTracker/HAB2/Build/Versatile GPS Breakout board.pdf new file mode 100644 index 0000000..9380d05 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Build/Versatile GPS Breakout board.pdf differ diff --git a/LoRa/LoRaTracker/HAB2/Parts/HAB2.xls b/LoRa/LoRaTracker/HAB2/Parts/HAB2.xls new file mode 100644 index 0000000..bcfb507 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Parts/HAB2.xls differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/Breakout and BMP280.JPG b/LoRa/LoRaTracker/HAB2/Pictures/Breakout and BMP280.JPG new file mode 100644 index 0000000..9a01144 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/Breakout and BMP280.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/Breakout and TC74.JPG b/LoRa/LoRaTracker/HAB2/Pictures/Breakout and TC74.JPG new file mode 100644 index 0000000..80cb3bc Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/Breakout and TC74.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/GPS Breakout 200917.jpg b/LoRa/LoRaTracker/HAB2/Pictures/GPS Breakout 200917.jpg new file mode 100644 index 0000000..0885263 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/GPS Breakout 200917.jpg differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/HAB2 PCB.jpg b/LoRa/LoRaTracker/HAB2/Pictures/HAB2 PCB.jpg new file mode 100644 index 0000000..de65287 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/HAB2 PCB.jpg differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1916.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1916.JPG new file mode 100644 index 0000000..1548666 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1916.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1920.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1920.JPG new file mode 100644 index 0000000..002ad94 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1920.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1922.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1922.JPG new file mode 100644 index 0000000..70d159c Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1922.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1924.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1924.JPG new file mode 100644 index 0000000..d3b8d16 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1924.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1926.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1926.JPG new file mode 100644 index 0000000..18992a7 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1926.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1928.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1928.JPG new file mode 100644 index 0000000..aeb107e Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1928.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1930.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1930.JPG new file mode 100644 index 0000000..3f36901 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1930.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1931.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1931.JPG new file mode 100644 index 0000000..3a757b6 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1931.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1932.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1932.JPG new file mode 100644 index 0000000..a8fd0d6 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1932.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1935.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1935.JPG new file mode 100644 index 0000000..c3958a2 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1935.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1940.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1940.JPG new file mode 100644 index 0000000..62b87bf Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1940.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1943.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1943.JPG new file mode 100644 index 0000000..405e3d7 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1943.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1948.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1948.JPG new file mode 100644 index 0000000..ebdb27c Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1948.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1951.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1951.JPG new file mode 100644 index 0000000..688f162 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1951.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/IMG_1953.JPG b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1953.JPG new file mode 100644 index 0000000..6672759 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/IMG_1953.JPG differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/Inverted Pips.jpg b/LoRa/LoRaTracker/HAB2/Pictures/Inverted Pips.jpg new file mode 100644 index 0000000..faa9952 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/Inverted Pips.jpg differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/LoRaTracker HAB2 Parts.jpg b/LoRa/LoRaTracker/HAB2/Pictures/LoRaTracker HAB2 Parts.jpg new file mode 100644 index 0000000..d73b8ea Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/LoRaTracker HAB2 Parts.jpg differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/LoRaTracker_HAB2.jpg b/LoRa/LoRaTracker/HAB2/Pictures/LoRaTracker_HAB2.jpg new file mode 100644 index 0000000..1038667 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/LoRaTracker_HAB2.jpg differ diff --git a/LoRa/LoRaTracker/HAB2/Pictures/Normal Pips.jpg b/LoRa/LoRaTracker/HAB2/Pictures/Normal Pips.jpg new file mode 100644 index 0000000..c8977a8 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Pictures/Normal Pips.jpg differ diff --git a/LoRa/LoRaTracker/HAB2/Programs/Configuring the LoRaTracker HAB Program.doc b/LoRa/LoRaTracker/HAB2/Programs/Configuring the LoRaTracker HAB Program.doc new file mode 100644 index 0000000..2ab6a39 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Programs/Configuring the LoRaTracker HAB Program.doc differ diff --git a/LoRa/LoRaTracker/HAB2/Programs/HAB2_UBLOX_EchoGPS_I2C/HAB2_UBLOX_EchoGPS_I2C.ino b/LoRa/LoRaTracker/HAB2/Programs/HAB2_UBLOX_EchoGPS_I2C/HAB2_UBLOX_EchoGPS_I2C.ino new file mode 100644 index 0000000..75bcfc6 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/HAB2_UBLOX_EchoGPS_I2C/HAB2_UBLOX_EchoGPS_I2C.ino @@ -0,0 +1,117 @@ +#define programname "HAB2_UBLOX_EchoGPS_I2C" +#define programversion "V1.0" +#define dateproduced "011017" +#define aurthorname "Stuart Robinson" + + +/* +******************************************************************************************************************************* + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 1/10/17 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + This program reads the GPS via I2C. Stores the config settings for UBLOX GPS in Flash to save on RAM memory. + + To Do: + +******************************************************************************************************************************* +*/ + +/* +******************************************************************************************************************************* + The purpose of this program is to check that a UBLOX I2C GPS is working. Characters are read from the GPS + and sent to the Serial monitor at 115200 baud. + The program can is configured to send the commands for a UBLOX GPS that should configure it out of GLONASS mode. +******************************************************************************************************************************* +*/ + + +#include +#include + +#include "HAB2_Board_Definitions.h" //select board type here +//#include "Locator2_Board_Definitions.h" //select board type here + +#include "Program_Definitions.h" //definitions for programs + +const unsigned long GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const byte GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const byte GPS_Reply_Size = 12; //size of GPS reply buffer +boolean GPS_Config_Error; + +#define GPS_ALLOW_GPGSV //we want to see the GPGSV messages +#include "UBLOX_I2CGPS.h" + +void loop() +{ + byte i; + + Wire.beginTransmission(GPSI2CAddress); + Wire.write(0xFF); + + while (1) + { + Wire.requestFrom(GPSI2CAddress, 1); + i = Wire.read(); + if (i != 0xFF) + { + Serial.write(i); + } + } +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(GPSPOWER, OUTPUT); //setup pin for GPS Power Control + digitalWrite(GPSPOWER, LOW); + + Serial.begin(115200); //connect at 115200 so we can read the GPS fast enough and also spit it out + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + + pinMode(LED1, OUTPUT); + led_Flash(2, 500); + + Wire.begin(); + + GPS_On(DoGPSPowerSwitch); //this will power the GPSon + GPS_Setup(); + + if (!GPS_CheckNavigation()) //Check that UBLOX GPS is in Navigation model 6 + { + Serial.println(); + Serial.println(F("Warning GPS Error !")); + Serial.println(); + led_Flash(100, 25); + } + +} + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/HAB2_UBLOX_EchoGPS_Serial/HAB2_UBLOX_EchoGPS_Serial.ino b/LoRa/LoRaTracker/HAB2/Programs/HAB2_UBLOX_EchoGPS_Serial/HAB2_UBLOX_EchoGPS_Serial.ino new file mode 100644 index 0000000..116d645 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/HAB2_UBLOX_EchoGPS_Serial/HAB2_UBLOX_EchoGPS_Serial.ino @@ -0,0 +1,108 @@ +#define programname "HAB2_UBLOX_EchoGPS_Serial" +#define programversion "V1.0" +#define dateproduced "011017" +#define aurthorname "Stuart Robinson" + + +/* +******************************************************************************************************************************* +Easy Build LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson - 1/10/17 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission +of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and +free from errors. + +To Do: + +******************************************************************************************************************************* +*/ + +/* +******************************************************************************************************************************* + The purpose of this program is to check that a UBLOX Serial GPS is working. Characters are read from the GPS + and sent to the Serial monitor at 115200 baud. + The program can is configured to send the commands for a UBLOX GPS that should configure it out of GLONASS mode. +******************************************************************************************************************************* +*/ + + +#include +#include + +//#include "HAB2_Board_Definitions.h" //select board type here +//#include "PIHTracker3_Board_Definitions.h" //select board type here +#include "Locator2_Board_Definitions.h" //select board type here + +#include "Program_Definitions.h" //definitions for programs +const unsigned int GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent +const unsigned long GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const byte GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const byte GPS_Reply_Size = 12; //size of GPS reply buffer +const unsigned int GPSBaud = 9600; //baud rate of GPS +boolean GPS_Config_Error; + +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPSserial(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial + +#define GPS_ALLOW_GPGSV //we want to see the GPGSV messages +#include "UBLOX_SerialGPS2.h" + + +void loop() +{ + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(GPSPOWER, OUTPUT); //setup pin for GPS Power Control + digitalWrite(GPSPOWER, LOW); + + Serial.begin(115200); //connect at 115200 so we can read the GPS fast enough and also spit it out + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + + pinMode(LED1, OUTPUT); //for Watchdog pulse input + led_Flash(2, 500); + + pinMode(GPSPOWER, OUTPUT); //in case power switching components are fitted + GPS_On(DoGPSPowerSwitch); //this will power the GPSon + GPS_Setup(); + + if (!GPS_CheckNavigation()) //Check that UBLOX GPS is in Navigation model 6 + { + Serial.println(); + Serial.println(F("Warning GPS Error !")); + Serial.println(); + led_Flash(100, 25); + } + +} + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/I2C_Scanner/I2C_Scanner.h b/LoRa/LoRaTracker/HAB2/Programs/I2C_Scanner/I2C_Scanner.h new file mode 100644 index 0000000..022ab4f --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/I2C_Scanner/I2C_Scanner.h @@ -0,0 +1,74 @@ + // -------------------------------------- + // i2c_scanner + // + // Version 1 + // This program (or code that looks like it) + // can be found in many places. + // For example on the Arduino.cc forum. + // The original author is not know. + // Version 2, Juni 2012, Using Arduino 1.0.1 + // Adapted to be as simple as possible by Arduino.cc user Krodal + // Version 3, Feb 26 2013 + // V3 by louarnold + // Version 4, March 3, 2013, Using Arduino 1.0.3 + // by Arduino.cc user Krodal. + // Changes by louarnold removed. + // Scanning addresses changed from 0...127 to 1...119, + // according to the i2c scanner by Nick Gammon + // http://www.gammon.com.au/forum/?id=10896 + // Version 5, March 28, 2013 + // As version 4, but address scans now to 127. + // A sensor seems to use address 120. + // Version 6, November 27, 2015. + // Added waiting for the Leonardo serial communication. + // + // + // This sketch tests the standard 7-bit addresses + // Devices with higher bit address might not be seen properly. + // + + + + + void run_I2CScan() + { + byte error, address; + int nDevices; + + Serial.println("Scanning for I2C Devices..."); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found"); + else + Serial.println(); + + Wire.endTransmission(); + } + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/I2C_Scanner/I2C_Scanner.ino b/LoRa/LoRaTracker/HAB2/Programs/I2C_Scanner/I2C_Scanner.ino new file mode 100644 index 0000000..aa2aedb --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/I2C_Scanner/I2C_Scanner.ino @@ -0,0 +1,66 @@ +#define programname "I2C_Scanner" +#define dateproduced "2/10/2017" +#define aurthorname "Stuart Robinson" + +/* +******************************************************************************************************************************** + +Easy Build LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson - 2/10/2017 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission +of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and +free from errors. + +This program scans each address on the I2C bus and reports if a device was found, examples. + +UBLOX GPS 0x42 +TC74 Temperature Sensor 0x4c +MB85RC16PNF FRAM 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 +BME280 Sensor 0x76 + +******************************************************************************************************************************** +*/ + + +#include +#include +#include "I2C_Scanner.h" +#include "HAB2_Board_Definitions.h" +//#include "Locator2_Board_Definitions.h" + +unsigned int scancount; + +void loop() +{ + scancount++; + Serial.println(); + Serial.print(scancount); + Serial.print(" "); + run_I2CScan(); + delay(1000); +} + + + +void setup() +{ + Serial.begin(38400); //setup Serial console ouput + Serial.println(F(programname)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + Serial.println(); + Serial.flush(); + pinMode(GPSPOWER, OUTPUT); //in case Ublox GPS breakout is fitted + digitalWrite(GPSPOWER, LOW); + Wire.begin(); + } + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_GPSBeacon_Beta_101017/LoRaTracker_GPSBeacon_Beta_101017.ino b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_GPSBeacon_Beta_101017/LoRaTracker_GPSBeacon_Beta_101017.ino new file mode 100644 index 0000000..7cb9720 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_GPSBeacon_Beta_101017/LoRaTracker_GPSBeacon_Beta_101017.ino @@ -0,0 +1,1147 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the HAB2_Settings file not here ! +// +//************************************************************************************************** + +#define programname "LoRaTracker_GPSBeacon_Beta_101017" +#define aurthorname "Stuart Robinson" + +#include +#include + +#include "LoRaTracker_GPSBeacon_Settings.h" +#include Board_Definition +#include "Program_Definitions.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + This is a simple GPS locator beacon, the GPS is read and the current location sent the specified period. The beacon can + optionally transmit a ready to send command packet, so it would be possible the remote control the beacon. + + Changes: + +************************************************************************************************** +*/ + +char ramc_RemoteControlNode; +char ramc_ThisNode; + +int ramc_CalibrationOffset; + +unsigned long ramc_TrackerMode_Frequency; //frequencies, and other parameters, are copied from memory into RAM. +unsigned long ramc_CommandMode_Frequency; //copied into memory so that they survive reset. + +uint8_t ramc_TrackerMode_Bandwidth; +uint8_t ramc_TrackerMode_SpreadingFactor; +uint8_t ramc_TrackerMode_CodeRate; +uint8_t ramc_TrackerMode_Power; +uint8_t TRStatus = 0; //used to store current status flag bits + +uint8_t ramc_CommandMode_Bandwidth; +uint8_t ramc_CommandMode_SpreadingFactor; +uint8_t ramc_CommandMode_CodeRate; +uint8_t ramc_CommandMode_Power; + +uint8_t ramc_Current_TXconfig1; //sets the config of whats transmitted etc +uint8_t ramc_Cmd_WaitSecs; +uint8_t stripvalue; +uint8_t sats; //either sats in view from GPGSV or sats from NMEA fix sentence +int internal_temperature; + +boolean GPS_Config_Error; +uint16_t ramc_Sleepsecs; //seconds for sleep at end of TX routine +uint16_t ramc_WaitGPSFixSeconds; //in flight mode, default time to wait for a fix + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +uint16_t TRAlt; + +uint8_t ramc_promiscuous_Mode; +uint8_t ramc_key0; +uint8_t ramc_key1; +uint8_t ramc_key2; +uint8_t ramc_key3; +uint8_t keypress; + + +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include //https://github.com/rocketscream/Low-Power + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object +TinyGPSCustom GNGGAFIXQ(gps, "GNGGA", 5); //custom sentences used to detect possible switch to GLONASS mode + +#ifdef USE_SOFTSERIAL_GPS +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPSserial(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial +#endif + +#include GPS_Library //include previously defined GPS Library + +#include "Voltage_Temperature.h" +#include "LoRa4.h" +#include "Binary2.h" + + + +void loop() +{ + Serial.println(); + Serial.println(); + + +#ifndef DEBUGNoGPS + gpsWaitFix(ramc_WaitGPSFixSeconds, SwitchOn, LeaveOn); +#endif + +#ifdef Use_Test_Location + TRLat = TestLatitude; + TRLon = TestLongitude; + TRAlt = TestAltitude; +#endif + + do_Transmissions(); + + sleepSecs(1); + + #ifdef Accept_Commands + wait_Command(); //wait for incoming command + #endif + + digitalWrite(lora_NSS, HIGH); //take NSS line high, makes sure LoRa device is off + sleepSecs(ramc_Sleepsecs); //this sleep is used to set overall transmission cycle time +} + + +void wait_Command() +{ + uint8_t index; + pulseWDI(); + lora_Setup(); //resets then sets up LoRa device + Setup_LoRaCommandMode(); //commands can be sent in any mode, make sure this is sent using the right frequency etc + send_Command(ClearToSendCommand); //indicate ready for command + + lora_RXPacketType = 0; //use as flag to tell if anything received during listen + Listen(Cmd_WaitSecs); //wait for command packet + + if (lora_RXPacketType > 0) + { + do + { + //there was activity during previous listen + lora_RXPacketType = 0; + + for (index = 1; index <= Command_Loops; index++) + { + Setup_LoRaCommandMode(); //commands can be sent in any mode, make sure this is sent using the right frequency etc + send_Command(ClearToSendCommand); + Listen(Cmd_WaitSecs); + } + + } while (lora_RXPacketType > 0); //wait until the extended listen exits with no packet received + + } + else + { + Serial.println(F("No RX")); + } +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + + pulseWDI(); + lora_Setup(); //resets then sets up LoRa device + Setup_LoRaTrackerMode(); + send_LocationBinary(TRLat, TRLon, TRAlt); +} + + +void send_LocationBinary(float Lat, float Lon, uint16_t Alt) +{ + Write_Float(0, Lat, lora_TXBUFF); + Write_Float(4, Lon, lora_TXBUFF); + Write_Int(8, Alt, lora_TXBUFF); + Write_Byte(10, TRStatus, lora_TXBUFF); + + digitalWrite(LED1, HIGH); + Serial.println(F("Send Binary Location")); + lora_Send(0, 10, LocationBinaryPacket, Broadcast, ramc_ThisNode, 10, lora_Power, 0); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd + digitalWrite(LED1, LOW); +} + + + +void Listen(uint16_t seconds) +{ + //listen (in seconds) for an incoming packet using the current frequency and LoRa modem settings + unsigned long tilltime; + tilltime = (millis() + (seconds * 1000)); + Serial.print(F("Listen ")); + Serial.println(seconds); + + lora_RXONLoRa(); + + while (millis() < tilltime) + { + checkForPacket(); + } + lora_RXOFF(); //as we have finished listening +} + + +void checkForPacket() +{ + //check LoRa device to see if a command packet has arrived + uint8_t lora_Ltemp; + + lora_Ltemp = lora_readRXready(); + + if (lora_Ltemp > 0) + { + + Serial.print(F("RX ")); + + if (lora_Ltemp == 64) + { + //packet has arrived + lora_ReadPacket(); + + Serial.write(lora_RXPacketType); + Serial.write(lora_RXDestination); + Serial.write(lora_RXSource); + Serial.println(); + } + else + { + //packet arrived with error + Serial.println(F("Error")); + lora_RXOFF(); + lora_RXONLoRa(); + } + + if (promiscuous_Mode) //can we accept packet from any source + { + processPacket(); + lora_RXONLoRa(); + } + + if (!promiscuous_Mode) //can we only accepts packet from known node + { + if (lora_RXSource == ramc_RemoteControlNode) + { + processPacket(); + lora_RXONLoRa(); //ready for next and clear flags + } + else + { + Serial.println(F("Rejected")); + lora_RXOFF(); + Setup_LoRaCommandMode(); + send_Command(NACK); + lora_RXONLoRa(); + } + } + } +} + + +void processPacket() +{ + //we have a packet so lets decide what to do with it + uint8_t i, j; + + if (lora_RXPacketType == Test) + { + if (lora_RXBUFF[0] == '0') + { + Serial.println(F("Pkt Test")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + delay(inter_Packet_delay); + sendTest(); + } + } + + if (lora_RXPacketType == LinkReport) + { + send_Command(ACK); + delay(inter_Packet_delay); + Serial.println(F("Link Report")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(Info); + } + + + if (lora_RXPacketType == Config0) //is it a change config uint8_t request ? + { + Serial.println(F("Prog Cfgbyte")); + + i = ((lora_RXBUFF[0] - 48)); //config uint8_t requests come in as ASCCI, '1' for 1 etc + j = ((lora_RXBUFF[1] - 48)); + setConfigByte(i, j); + lora_RXBuffPrint(0); //print packet contents as ASCII + Serial.println(); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); //send the ack + + } + + if (lora_RXPacketType == ResetTracker) //is it a reset ? + { + Serial.println(F("Reset ?")); + lora_RXBuffPrint(0); //print packet contents as ASCII + Serial.println(); + + if ( isKeyValid() ) + { + Serial.println(F("Valid")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + Serial.flush(); + sleepSecs(2); + softReset(); + } + else + { + Serial.println(F("Invalid")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(NACK); + } + } + + if (lora_RXPacketType == WritePacketMemory) + { + Serial.println(F("Write Memory")); + writePacketMemory(); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + } + + if (lora_RXPacketType == INCFreq) + { + Serial.println(F("IncOffset 1KHZ")); + ramc_CalibrationOffset = ramc_CalibrationOffset + 1000; + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + } + + if (lora_RXPacketType == DECFreq) + { + Serial.println(F("DecOffset 1KHZ")); + ramc_CalibrationOffset = ramc_CalibrationOffset - 1000; + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + } + +} + + + + +void printMemoryFrequencies() +{ + //a useful check to see if memory is configured correctly + unsigned long tempULong; + tempULong = Memory_ReadULong(addr_TrackerMode_Frequency); + Serial.print(F("Memory Tracker Freq ")); + Serial.println(tempULong); + + tempULong = Memory_ReadULong(addr_CommandMode_Frequency); + Serial.print(F("Memory Command Freq ")); + Serial.println(tempULong); +} + + +boolean isKeyValid() +{ + if ( (lora_RXBUFF[0] == key0) && (lora_RXBUFF[1] == key1) && (lora_RXBUFF[2] == key2) && (lora_RXBUFF[3] == key3) ) + { + return true; + } + else + { + return false; + } +} + + +void softReset() +{ + asm volatile (" jmp 0"); +} + + +void send_Command(char cmd) +{ + uint16_t volts; + volts = read_SupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + Write_Byte(0, lora_PacketSNR, lora_TXBUFF); //so that receiver alwsys knows last received SNR + Write_Byte(1, lora_PacketRSSI, lora_TXBUFF); //so that receiver alwsys knows last received RSSI + Write_UInt(2, volts, lora_TXBUFF); + Write_Byte(4, TRStatus, lora_TXBUFF); + digitalWrite(LED1, HIGH); + lora_Send(0, 4, cmd, Broadcast, ramc_ThisNode, 10, lora_Power, 0); + digitalWrite(LED1, LOW); +} + + +void sendTest() +{ + uint8_t power; + for (power = 10; power >= 2; power--) + { + Setup_LoRaTrackerMode(); + lora_TXBUFF[0] = '0'; + lora_TXBUFF[1] = power + 48; + lora_TXEnd = 1; + + if (power == 10) + { + lora_TXBUFF[0] = '1'; + lora_TXBUFF[1] = '0'; + lora_TXEnd = 2; + } + + Serial.print(F("Send ")); + Serial.print(power); + Serial.println(F("dBm")); + + lora_Send(0, 1, Test, Broadcast, ramc_ThisNode, 10, power, 0); //send the test packet + sleepSecs(2); + } +} + +void sleepSecs(uint16_t LNumberSleeps) +{ + uint16_t i; + + Serial.print(F("zz ")); + Serial.println(LNumberSleeps); + Serial.flush(); //let print complete +#ifdef USING_SERIALGPS + GPSserial.end(); //we dont want GPS input interfering with sleep, make sure its off +#endif + digitalWrite(lora_NSS, HIGH); //ensure LoRa Device is off + + for (i = 1; i <= LNumberSleeps; i++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep 1 second + pulseWDI(); + } +} + + +void incMemoryULong(uint16_t laddress) +{ + unsigned long val; + val = Memory_ReadULong(laddress); + val++; + Memory_WriteULong(laddress, val); +} + + +uint8_t readConfigByte(uint8_t bitnum) +{ + return bitRead(ramc_Current_TXconfig1, bitnum); +} + + +void setConfigByte(uint8_t bitnum, uint8_t bitval) +{ + //program the config byte + + if (bitval == 0) + { + bitClear(ramc_Current_TXconfig1, bitnum); + } + else + { + bitSet(ramc_Current_TXconfig1, bitnum); + } + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } + +} + + +void pulseWDI() +{ + //if the watchdog is fitted it needs a regular pulse top prevent reset + //togle the WDI pin twice + digitalWrite(WDI, !digitalRead(WDI)); + delayMicroseconds(1); + digitalWrite(WDI, !digitalRead(WDI)); +} + + +boolean gpsWaitFix(unsigned long waitSecs, uint8_t StartState, uint8_t LeaveState) +{ + //waits a specified number of seconds for a fix, returns true for good fix + //StartState when set to 1 will turn GPS on at routine start + //LeaveState when set to 0 will turn GPS off at routine end, used perhaps when there is no fix + + uint32_t endwaitmS, millistowait, currentmillis; + pulseWDI(); + uint8_t GPSByte; + //ong temp; + + if (StartState == 1) + { + GPS_On(DoGPSPowerSwitch); + } + else + { + GPS_On(NoGPSPowerSwitch); + } + + Serial.print(F("Wait Fix ")); + Serial.print(waitSecs); + Serial.println(F(" Secs")); + + currentmillis = millis(); + millistowait = waitSecs * 1000; + endwaitmS = currentmillis + millistowait; + + while (millis() < endwaitmS) + { + + do + { + GPSByte = GPS_GetByte(); + if (GPSByte != 0xFF) + { + gps.encode(GPSByte); + } + } + while (GPSByte != 0xFF); + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + Serial.println(F("GPS Fix")); + TRLat = gps.location.lat(); + TRLon = gps.location.lng(); + TRAlt = (uint16_t) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TRAlt > 60000) + { + TRAlt = 0; + } + + if (readConfigByte(GPSHotFix)) + { + GPS_Off(DoGPSPowerSwitch); + } + else + { + GPS_Off(NoGPSPowerSwitch); + } + + setStatusByte(GPSFix, 1); + pulseWDI(); + return true; + } + +#ifdef UBLOX + if (GNGGAFIXQ.age() < 2000) //check to see if GLONASS has gone active + { + Serial.println(F("GLONASS !")); + setStatusByte(GLONASSisoutput, 1); + GPS_SetGPMode(); + GPS_SetCyclicMode(); + sleepSecs(1); + } + else + { + setStatusByte(GLONASSisoutput, 0); //GLONASS not detected + } +#endif + + + + } + + //if here then there has been no fix and a timeout + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(F("No Fix")); + + if (LeaveState == 0) + { + //no fix and gpsWaitFix called with gpspower to be turned off on exit + GPS_Off(DoGPSPowerSwitch); + } + else + { + //no fix but gpsWaitFix called with gpspower to be left on at exit + GPS_Off(NoGPSPowerSwitch); + } + + pulseWDI(); + return false; +} + + +void readSettingsDefaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Config Defaults")); + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_TrackerMode_Bandwidth = TrackerMode_Bandwidth; + ramc_TrackerMode_SpreadingFactor = TrackerMode_SpreadingFactor; + ramc_TrackerMode_CodeRate = TrackerMode_CodeRate; + ramc_TrackerMode_Power = TrackerMode_Power; + + ramc_CommandMode_Frequency = CommandMode_Frequency; + ramc_CommandMode_Bandwidth = CommandMode_Bandwidth; + ramc_CommandMode_SpreadingFactor = CommandMode_SpreadingFactor; + ramc_CommandMode_CodeRate = CommandMode_CodeRate; + ramc_CommandMode_Power = CommandMode_Power; + + ramc_ThisNode = ThisNode; + ramc_RemoteControlNode = RemoteControlNode; + + ramc_Current_TXconfig1 = Default_config1; + ramc_Cmd_WaitSecs = Cmd_WaitSecs; + ramc_WaitGPSFixSeconds = WaitGPSFixSeconds; + ramc_Sleepsecs = Loop_Sleepsecs; + ramc_promiscuous_Mode = promiscuous_Mode; + + ramc_key0 = key0; + ramc_key1 = key1; + ramc_key2 = key2; + ramc_key3 = key3; + + ramc_CalibrationOffset = CalibrationOffset; +} + + +void readSettingsMemory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Config from Memory")); + + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_TrackerMode_Bandwidth = Memory_ReadByte(addr_TrackerMode_Bandwidth); + ramc_TrackerMode_SpreadingFactor = Memory_ReadByte(addr_TrackerMode_SpreadingFactor); + ramc_TrackerMode_CodeRate = Memory_ReadByte(addr_TrackerMode_CodeRate); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + + ramc_CommandMode_Frequency = Memory_ReadULong(addr_CommandMode_Frequency); + ramc_CommandMode_Bandwidth = Memory_ReadByte(addr_CommandMode_Bandwidth); + ramc_CommandMode_SpreadingFactor = Memory_ReadByte(addr_CommandMode_SpreadingFactor); + ramc_CommandMode_CodeRate = Memory_ReadByte(addr_CommandMode_CodeRate); + ramc_CommandMode_Power = Memory_ReadByte(addr_CommandMode_Power); + + ramc_ThisNode = Memory_ReadByte(addr_ThisNode);; + ramc_RemoteControlNode = Memory_ReadByte(addr_RemoteControlNode);; + + ramc_Current_TXconfig1 = Memory_ReadByte(addr_Default_config1); + ramc_Cmd_WaitSecs = Memory_ReadByte(addr_Cmd_WaitSecs); + ramc_WaitGPSFixSeconds = Memory_ReadUInt(addr_WaitGPSFixSeconds); + ramc_Sleepsecs = Memory_ReadUInt(addr_Sleepsecs); + ramc_promiscuous_Mode = Memory_ReadByte(addr_promiscuous_Mode); + + ramc_key0 = Memory_ReadByte(addr_key0); + ramc_key1 = Memory_ReadByte(addr_key1); + ramc_key2 = Memory_ReadByte(addr_key2); + ramc_key3 = Memory_ReadByte(addr_key3); + + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + +} + + +void writeSettingsMemory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) + + Serial.println(F("Write RAM Settings to Memory")); + + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //fill config area with 0 + + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Bandwidth, ramc_TrackerMode_Bandwidth); + Memory_WriteByte(addr_TrackerMode_SpreadingFactor, ramc_TrackerMode_SpreadingFactor); + Memory_WriteByte(addr_TrackerMode_CodeRate, ramc_TrackerMode_CodeRate); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + + Memory_WriteULong(addr_CommandMode_Frequency, ramc_CommandMode_Frequency); + Memory_WriteByte(addr_CommandMode_Bandwidth, ramc_CommandMode_Bandwidth); + Memory_WriteByte(addr_CommandMode_SpreadingFactor, ramc_CommandMode_SpreadingFactor); + Memory_WriteByte(addr_CommandMode_CodeRate, ramc_CommandMode_CodeRate); + Memory_WriteByte(addr_CommandMode_Power, ramc_CommandMode_Power); + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + Memory_WriteByte(addr_RemoteControlNode, ramc_RemoteControlNode); + + Memory_WriteByte(addr_ThisNode, ramc_ThisNode); + Memory_WriteByte(addr_RemoteControlNode, ramc_RemoteControlNode); + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + Memory_WriteByte(addr_Cmd_WaitSecs, ramc_Cmd_WaitSecs); + Memory_WriteUInt(addr_WaitGPSFixSeconds, ramc_WaitGPSFixSeconds); + Memory_WriteUInt(addr_Sleepsecs, ramc_Sleepsecs); + Memory_WriteByte(addr_promiscuous_Mode, ramc_promiscuous_Mode); + + Memory_WriteByte(addr_key0, ramc_key0); + Memory_WriteByte(addr_key1, ramc_key1); + Memory_WriteByte(addr_key2, ramc_key2); + Memory_WriteByte(addr_key3, ramc_key3); + + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); +} + + +void saveKeyin_buffer() +{ + lora_TXBUFF[0] = key0; //key used in sme packets to reduce chances of a change being applied by accident + lora_TXBUFF[1] = key1; + lora_TXBUFF[2] = key2; + lora_TXBUFF[3] = key3; +} + + +void printMemoryChange(uint8_t number) +{ + uint8_t index, j; + Serial.print(F("Memory Change")); + for (index = 0; index <= number; index++) + { + j = lora_RXBUFF[index]; + Serial.print(F(" ")); + Serial.print(j, HEX); + } + Serial.println(); +} + + +void writePacketMemory() +{ + //there is an incoming packet which is a request to write bytes to Memory. + //the effect is to change stored program definitions and constants + uint8_t i, j, k, ptr; + //uint8_t i, j, k, ptr, low, high; + uint16_t addr_Memory; + //float tempfloat; + + //packet format is key0, key1, key2, key3, number of bytes to write, address to write to, bytes to write + //terminate list with 0 bytes to write. + + if (isKeyValid()) + { + Serial.print(F("Not Valid")); + return; + } + + i = lora_RXPacketL - 4; //end of packet will be length - 1 for 0 offset and -3 for adddress bytes + + printMemoryChange(i); + + ptr = 4; + + j = lora_RXBUFF[ptr++]; + + addr_Memory = Read_Int(5, lora_RXBUFF); //read address for frequency offset into buffer + + ptr++; + ptr++; + + Serial.println(F("Write memory ")); + + for (i = 1; i <= j; i++) + { + Memory_WriteByte(addr_Memory, lora_RXBUFF[ptr]); + k = lora_RXBUFF[ptr]; + Serial.print(k, HEX); + Serial.print(F(" ")); + addr_Memory++; + ptr++; + } + readSettingsMemory(); + Setup_LoRaTrackerMode(); //dummy change so we can see if offset chnages +} + + + +void sendTrackerBind() +{ + uint16_t i, j; + uint8_t msb_CRC, lsb_CRC; + uint16_t bindCRC; + + saveKeyin_buffer(); //loads key in bytes 0,1,2,3 of TX buffer + + lora_TXEnd = 4; //this is where the bind data starts + + for (i = addr_StartBindData; i <= addr_EndBindData; i++) + { + j = Memory_ReadByte(i); + lora_TXBUFF[lora_TXEnd++] = j; + } + + bindCRC = Print_CRC_Bind_Memory(); + msb_CRC = highByte(bindCRC); + lsb_CRC = lowByte(bindCRC); + lora_TXBUFF[lora_TXEnd++] = lsb_CRC; + lora_TXBUFF[lora_TXEnd] = msb_CRC; + + Serial.print(F("Bind PacketLen ")); + Serial.println(lora_TXEnd + 4); //allow for 3 addressing bytes in length, plus 1 for packet starting at [0] + + lora_Send(0, lora_TXEnd, Bind, ramc_RemoteControlNode, ramc_ThisNode, 10, BindMode_Power, 0); + +} + + +void printNodes() +{ + Serial.print(F("ThisNode ")); + Serial.print(ramc_ThisNode); + Serial.print(F(" RemoteNode ")); + Serial.println(ramc_RemoteControlNode); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_TrackerMode_Bandwidth, ramc_TrackerMode_SpreadingFactor, ramc_TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters for tracker mode + lora_Power = ramc_TrackerMode_Power; +} + + +void Setup_LoRaCommandMode() +{ + lora_SetFreq(ramc_CommandMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_CommandMode_Bandwidth, ramc_CommandMode_SpreadingFactor, ramc_CommandMode_CodeRate, Explicit); //Setup the LoRa modem parameters for command mode + lora_Power = ramc_CommandMode_Power; +} + + +void Setup_LoRaBindMode() +{ + lora_SetFreq(BindMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(BindMode_Bandwidth, BindMode_SpreadingFactor, BindMode_CodeRate, Explicit); //Setup the LoRa modem parameters for bind mode + lora_Power = BindMode_Power; +} + + +void display_current_frequency() +{ + float freq_temp; + freq_temp = lora_GetFreq(); + Serial.print(F("Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + +void do_ClearSavedData() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear Saved Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear All Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void Print_Config_Memory() +{ + //prints the memory used for storing configuration settings + uint8_t memory_LLoopv1; + uint8_t memory_LLoopv2; + uint16_t memory_Laddr = 0; + uint8_t memory_Ldata; + //uint16_t CRC; + Serial.println(F("Config Memory")); + Serial.print(F("Lcn 0 1 2 3 4 5 6 7 8 9 A B C D E F")); + Serial.println(); + + for (memory_LLoopv1 = 0; memory_LLoopv1 <= 15; memory_LLoopv1++) + { + Serial.print(F("0x")); + Serial.print(memory_LLoopv1, HEX); //print the register number + Serial.print(F("0 ")); + for (memory_LLoopv2 = 0; memory_LLoopv2 <= 15; memory_LLoopv2++) + { + memory_Ldata = Memory_ReadByte(memory_Laddr); + if (memory_Ldata < 0x10) { + Serial.print(F("0")); + } + Serial.print(memory_Ldata, HEX); //print the register number + Serial.print(F(" ")); + memory_Laddr++; + } + Serial.println(); + } +} + + +void Print_CRC_Config_Memory() +{ + uint16_t returnedCRC = Memory_CRC(addr_StartConfigData, addr_EndConfigData); + Serial.print(F("CRC_Config ")); + Serial.println(returnedCRC, HEX); +} + + +uint16_t Print_CRC_Bind_Memory() +{ + uint16_t returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("Local BindCRC ")); + Serial.println(returnedCRC, HEX); + return returnedCRC; +} + + +void setup() +{ + uint16_t j; + + pinMode(LED1, OUTPUT); //for PCB LED + pinMode(WDI, OUTPUT); //for Watchdog pulse input + + led_Flash(2, 500); + + Serial.begin(38400); //Setup Serial console ouput + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); +#endif + + + Serial.println(F(programname)); + Serial.println(F(aurthorname)); + + pinMode(GPSPOWER, OUTPUT); //in case power switching components are fitted + GPS_On(DoGPSPowerSwitch); //this will power the GPSon + +#ifdef USING_SERIALGPS + GPSserial.end(); //but we dont want soft serial running for now, it interferes with the LoRa device +#endif + + pinMode(lora_NReset, OUTPUT); //LoRa device reset line + digitalWrite(lora_NReset, HIGH); + + pinMode (lora_NSS, OUTPUT); //set the slave select pin as an output: + digitalWrite(lora_NSS, HIGH); + + SPI.begin(); //initialize SPI + SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); + + +#ifdef ClearSavedData + do_ClearSavedData(); +#endif + + Serial.print(F("Default_Config1 ")); + Serial.println(Default_config1, BIN); + + j = Memory_ReadUInt(addr_ResetCount); + j++; + Memory_WriteUInt(addr_ResetCount, j); + Serial.print(F("Resets ")); + Serial.println(j); + +#ifdef ConfigureDefaults + readSettingsDefaults(); + writeSettingsMemory(); +#endif + + +#ifdef ConfigureFromMemory + readSettingsMemory(); +#endif + + Print_CRC_Config_Memory(); + + ramc_ThisNode = ThisNode; + + printNodes(); + + lora_Setup(); + + if (!lora_CheckDevice()) + { + led_Flash(100, 50); //long medium speed flash for Lora device error + Serial.println(F("LoRa Error!")); + } + + display_current_frequency(); + + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); //get calibration offset for this tracker + Serial.print(F("Cal Offset ")); + Serial.println(ramc_CalibrationOffset); + + lora_Print(); + + Serial.println(); + print_SupplyVoltage(); + print_Temperature(); + Serial.println(); + + j = read_SupplyVoltage(); //get supply mV + Write_Int(0, j, lora_TXBUFF); //write to first two bytes of buffer + Write_Byte(2, ramc_Current_TXconfig1, lora_TXBUFF); //add the current config byte + + Setup_LoRaTrackerMode(); + send_Command(PowerUp); //send power up command, includes supply mV and config, on tracker settings + sleepSecs(1); + +#ifdef SendBind + if (readConfigByte(TXEnable)) //is TX enabled ? + { + Setup_LoRaBindMode(); + sendTrackerBind(); + } +#endif + + Setup_LoRaTrackerMode(); //so that check tone is at correct frequency + + GPS_Config_Error = false; //make sure GPS error flag is cleared + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); //GPS should have been on for a while by now, so this is just to start soft serial + GPS_Setup(); //GPS should have had plenty of time to initialise by now + + if (GPS_Config_Error) + { + Serial.println(F("GPS Error !")); + Serial.println(); + send_Command(NoGPS); //make sure receiver knows about GPS error + led_Flash(100, 25); //long very rapid flash for GPS error + } + else + { +#ifdef CheckTone + if (readConfigByte(TXEnable)) //is TX enabled - needed because of fence limits + { + Serial.println(F("Check Tone")); //check tone indicates navigation model 6 set (if checktone enabled!) + lora_Tone(1000, 3000, 5); //Transmit an FM tone, 1000hz, 3000ms, 5dBm + } +#endif + } + + digitalWrite(LED1, HIGH); + setStatusByte(NoGPSTestMode, 0); + while (!gpsWaitFix(5, DontSwitch, LeaveOn)) //wait for the initial GPS fix, this could take a while, leave GPS powered on + { + + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + + + } +#endif + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled +#endif + + lora_Tone(500, 500, 2); //Transmit an FM tone, 500hz, 500ms, 2dBm + digitalWrite(LED1, LOW); + sleepSecs(2); //wait for GPS to shut down + +#ifdef DEBUGNoGPS + setStatusByte(NoGPSTestMode, 1); +#endif + +} + + + + + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_GPSBeacon_Beta_101017/LoRaTracker_GPSBeacon_Settings.h b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_GPSBeacon_Beta_101017/LoRaTracker_GPSBeacon_Settings.h new file mode 100644 index 0000000..c4496fd --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_GPSBeacon_Beta_101017/LoRaTracker_GPSBeacon_Settings.h @@ -0,0 +1,209 @@ +//LoRaTracker_GPSBeacon_Settings.h +/* +****************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 16/10/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To Do: + + Changes: + 101017 Removed unused board definitions + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +#define CPU_VoltageRead +//#define External_VoltageRead + +#define CPU_TemperatureRead +//#define External_TemperatureRead +const int Temperature_Adjust = 0; //to allow calibration of external temperature sensor + +#define Board_Definition "HAB2_Board_Definitions.h" //define the board to use here + + + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + + +#define ConfigureDefaults //Configure settings from default program constants, save in memory and copy to RAM, need to do this once only +//#define ClearAllMemory //Clears from start memory to end memory, normally 1kbyte, needs to be folloowed by ConfigureDefaults +//#define ClearSavedData //zero the saved data, resets, sequence, Mahr +//#define ConfigureFromMemory //Read settings from attached memory + +#define CheckTone //comment in to have a calibrate tone at startup, also indicates navigation model 6 set + +//#define DEBUG //if defined, prints additional debug information to terminal + + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const uint32_t TrackerMode_Frequency = 434400000; + +//Command mode +const uint32_t CommandMode_Frequency = 434400000; + +//Bind mode - Change this with great care !!!!! +const uint32_t BindMode_Frequency = 434100000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 0; + + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +//Tracker mode +#define TrackerMode_Bandwidth BW62500 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 +#define TrackerMode_Power 10 + +//Command mode +#define CommandMode_Bandwidth BW62500 +#define CommandMode_SpreadingFactor SF8 +#define CommandMode_CodeRate CR45 +#define CommandMode_Power 10 + +//Bind mode +#define BindMode_Bandwidth BW500000 +#define BindMode_SpreadingFactor SF8 +#define BindMode_CodeRate CR45 +#define BindMode_Power 2 + +#define SendBind //at startup tracker transmitter will send a bind packet +//#define LORADEBUG //displays extra debug messages when using LoRa +#define Accept_Commands //define this if you want to be able to remote control beacon + + +const uint8_t Deviation = 0x52; //typical deviation for tones +const uint8_t lora_RXBUFF_Size = 128; +const uint8_t lora_TXBUFF_Size = 32; + +const uint16_t inter_Packet_delay = 500; //allows time for receiver to be ready to see a possible reply, in mS + + +const uint8_t Cmd_WaitSecs = 5; //number of seconds to stay in waiting for command mode +const uint8_t Command_Loops = 3; //if one command is received wait for this number of loops to keep control channel open + +//Key Definition +const char key0 = 'L'; //Used to restrict access to some commands +const char key1 = 'o'; +const char key2 = 'R'; +const char key3 = 'a'; + +//************************************************************************************************** +// 5) GPS Options +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +#define GPS_Library "UBLOX_SerialGPS2.h" //define the GPS library routines to use here, this is a version2 of the serial program, does not use Flash5 library +//#define GPS_Library "UBLOX_I2CGPS.h" //define for using a UBLOX GPS with I2C interface + +//#define DEBUGNoGPS //test mode, does not use GPS +//#define Use_Test_Location //to use test location for transmissions include this define + +//#define GPS_ALLOW_GPGSV //define this so that GPGSV senetences are not turned off + +#define GPSBaud 9600 //GPS Baud rate +#define WhenNoGPSFix LeaveOn //What to do with GPS power when there is no fix at ends of wait period (LeaveOn or LeaveOff) +#define WaitGPSFixSeconds 30 //in flight mode time to wait for a new GPS fix +//#define Remove_GPS_Power //Some tracker boards can remove the power from the GPS, if so define this to use it +#define Use_GPS_SoftwareBackup //some GPSs do not support this mode, Ubloxes do, used for GPS Hotfix option + +const uint32_t fixisoldmS = 10000; //if location has not updated in this number of mS, assume GPS has lost fix +const uint32_t GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const uint8_t GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const uint8_t GPS_Reply_Size = 12; //size of GPS reply buffer +const unsigned int GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent + +//Centre of Cardiff Castle keep +#define TestLatitude 51.48230 +#define TestLongitude -3.18136 +#define TestAltitude 48 + + +/* + Passive GPS station: Swanbridge - C1ST1667 + https://www.ordnancesurvey.co.uk/gps/legacy-control-information/C1ST1667 + N 51 23'59.105955", W 3 11',47.413031 + 51.399751654166664, -3.196503619722222 + + #define TestLatitude 51.399752 + #define TestLongitude -3.196504 + #define TestAltitude 0 +*/ + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +//#define Memory_Library "EEPROM_Memory.h" //define this file if the internal EEPROM is in use +#define Memory_Library "I2CFRAM_MB85RC16PNF.h" //define this file if the I2C FRAM is in use + + +//**************************************************************************************************** +// 11) Program Default Option settings +// This section determines which options are on or off by default, this is the Default_config1 byte +// Take care here.......... +//************************************************************************************************** + +#define OptionOff 0 +#define OptionOn 1 + +const char option_TXEnable = OptionOn; +const char option_AddressStrip = OptionOff; +const char option_GPSHotFix = OptionOff; + +#define option_TXEnable_SUM (option_TXEnable*2) +#define option_AddressStrip_SUM (option_AddressStrip*64) +#define option_GPSHotFix_SUM (option_GPSHotFix*128) + + +const uint8_t Default_config1 = (option_TXEnable_SUM + option_AddressStrip_SUM + option_GPSHotFix_SUM); +//const uint16_t Default_config1 = 2; //Phew, the default config can always be set manually ............. + + +//************************************************************************************************** +// 13) Unique calibration settings for each Board +// These settings are not part of a bind operation +//************************************************************************************************** + +const float kelvin_offset = 325; //not used in this application but causes a complie error if missing +const float temp_conversion_slope = 1.0; //not used in this application but causes a complie error if missing +uint32_t adc_constant = 1200000; //if processor self read of its supply voltage reports high reduce this number + +//************************************************************************************************** +// 15) Beacon settings +//************************************************************************************************** + + +const uint16_t Loop_Sleepsecs = 10; //sleep time in seconds between transmissions +const boolean promiscuous_Mode = true; //if set to True remote control packets from any node accepted + +#define RemoteControlNode 'G' //normally used by tracker transmitter in promiscuous_Mode +#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +#define ThisNode ControlledNode + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_101017/LoRaTracker_HAB2_101017.ino b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_101017/LoRaTracker_HAB2_101017.ino new file mode 100644 index 0000000..455e47d --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_101017/LoRaTracker_HAB2_101017.ino @@ -0,0 +1,1698 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the HAB2_Settings file not here ! +// +//************************************************************************************************** + +#define programname "LoRaTracker_HAB2_101017" +#define aurthorname "Stuart Robinson" + +#include +#include + +#include "LoRaTracker_HAB2_Settings.h" +#include Board_Definition +#include "Program_Definitions.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + Location payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Sats,SupplyVolts,Temperature,Resets,Config0byte,StatusByte,RunmAhr,hertzoffset,GPSFixTime,Checksum + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + + To Do: + Change test packet routine to allow for 17dBm packets + + Changes: + +************************************************************************************************** +*/ + +char ramc_RemoteControlNode; +char ramc_ThisNode; + +int ramc_CalibrationOffset; + +unsigned long ramc_TrackerMode_Frequency; //frequencies, and other parameters, are copied from memory into RAM. +unsigned long ramc_SearchMode_Frequency; //this is so that these parameters can be changed in flight and then +unsigned long ramc_CommandMode_Frequency; //copied into memory so that they survive reset. + +byte ramc_TrackerMode_Bandwidth; +byte ramc_TrackerMode_SpreadingFactor; +byte ramc_TrackerMode_CodeRate; +byte ramc_TrackerMode_Power; +byte TRStatus = 0; //used to store current status flag bits + +byte ramc_SearchMode_Bandwidth; +byte ramc_SearchMode_SpreadingFactor; +byte ramc_SearchMode_CodeRate; +byte ramc_SearchMode_Power; + +byte ramc_CommandMode_Bandwidth; +byte ramc_CommandMode_SpreadingFactor; +byte ramc_CommandMode_CodeRate; +byte ramc_CommandMode_Power; + +byte ramc_Current_TXconfig1; //sets the config of whats transmitted etc +byte ramc_Cmd_WaitSecs; +byte stripvalue; +byte sats; //either sats in view from GPGSV or sats from NMEA fix sentence +int internal_temperature; + + +unsigned int ramc_Sleepsecs; //seconds for sleep at end of TX routine +unsigned int ramc_WaitGPSFixSeconds; //in flight mode, default time to wait for a fix +unsigned int ramc_FSKRTTYbaudDelay; //dealy used in FSKRTTY routine to give chosen baud rate + +unsigned long UPTime = 0; +unsigned long UPStart = 0; +unsigned long current_mASecs = 0; //running total of mAseconds used +unsigned long current_Sleepsecs = 0; + +float Fence_Check_Lon; //used for fence check + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; + +byte ramc_promiscuous_Mode; +byte ramc_FSKRTTYRegshift; +byte ramc_FSKRTTYpips; +unsigned int ramc_FSKRTTYleadin; +byte ramc_key0; +byte ramc_key1; +byte ramc_key2; +byte ramc_key3; +byte keypress; + +unsigned long GPSonTime; +unsigned long GPSFixTime; +boolean GPS_Config_Error; + + +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include //https://github.com/rocketscream/Low-Power + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object +TinyGPSCustom GNGGAFIXQ(gps, "GNGGA", 5); //custom sentences used to detect possible switch to GLONASS mode + +#ifdef USE_SOFTSERIAL_GPS +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPSserial(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial +#endif + +#include GPS_Library //include previously defined GPS Library + +#include "Voltage_Temperature.h" +#include "LoRa3.h" +#include "FSK_RTTY2.h" +#include "Binary2.h" + + + +void loop() +{ + UPStart = millis(); //set the start time for UPtime + Serial.println(); + Serial.println(); + lora_TXTime = 0; + lora_RXTime = 0; + UPTime = 0; + GPSFixTime = 0; + printTimes(); + internal_temperature = (int) read_Temperature(); //read temp just after sleep, when CPU is closest to ambient + + GPSonTime = millis(); + +#ifndef DEBUGNoGPS + gpsWaitFix(ramc_WaitGPSFixSeconds, SwitchOn, LeaveOn); +#endif + +#ifdef Use_Test_Location + TRLat = TestLatitude; + TRLon = TestLongitude; + TRAlt = TestAltitude; +#endif + + wait_Command(); //wait for incoming command + + if (readConfigByte(DozeEnable)) + { + Serial.println(F("Doze")); + updatemAUsed(); + printTimes(); + sleepSecs(DozeSleepSecs); //tracker has doze made enabled, so just doze awhile and do not send transmissions + return; + } + + if (readConfigByte(CheckFence) && (!doFenceCheck())) //if fence check is enabled and tracker is outside fence + { + action_outside_fence(); + } + else //either fence check is disabled or tracker is within it + { + if (readConfigByte(TXEnable)) //is TX enabled ? + { + do_Transmissions(); //yes, so do transmissions + } + else + { + Serial.println(F("TX off")); + inside_fence_no_transmit(); //no, TX is disabled + } + } + + updatemAUsed(); + printTimes(); + digitalWrite(lora_NSS, HIGH); //take NSS line high, makes sure LoRa device is off + sleepSecs(ramc_Sleepsecs); //this sleep is used to set overall transmission cycle time + +} + + +void wait_Command() +{ + byte index; + pulseWDI(); + lora_Setup(); //resets then sets up LoRa device + Setup_LoRaCommandMode(); //commands can be sent in any mode, make sure this is sent using the right frequency etc + send_Command(ClearToSendCommand); //indicate ready for command + + lora_RXPacketType = 0; //use as flag to tell if anything received during listen + Listen(Cmd_WaitSecs); //wait for command packet + + if (lora_RXPacketType > 0) + { + do + { + //there was activity during previous listen + lora_RXPacketType = 0; + + for (index = 1; index <= Command_Loops; index++) + { + Setup_LoRaCommandMode(); //commands can be sent in any mode, make sure this is sent using the right frequency etc + send_Command(ClearToSendCommand); + Listen(Cmd_WaitSecs); + } + + } while (lora_RXPacketType > 0); //wait until the extended listen exits with no packet received + + } + else + { + Serial.println(F("No RX")); + } +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + byte index, Count; + + pulseWDI(); + lora_Setup(); //resets then sets up LoRa device + + Setup_LoRaTrackerMode(); + + incMemoryULong(addr_SequenceNum); //increment sequence number + Count = buildHABPacket(); + stripvalue = readConfigByte(AddressStrip); + Serial.println(F("Send HAB Pkt")); + printPayload(Count); + Serial.println(); + digitalWrite(LED1, HIGH); + lora_Send(0, Count, HABPacket, Broadcast, ramc_ThisNode, 10, lora_Power, stripvalue); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd + digitalWrite(LED1, LOW); + + sleepSecs(delayforAFSKuploadSecs); //allow time for receiver AFSK upload + + sleepSecs(delayforRelaysecs); //wait for relay to operate + + if (readConfigByte(FSKRTTYEnable)) + { + + Serial.println(F("Send FSKRTTY")); + + lora_DirectSetup(); //set for direct mode + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + Start_FSKRTTY(FSKRTTYRegshift, FSKRTTYleadin, FSKRTTYpips); + + for (index = 1; index <= sync_chars; index++) + { + Send_FSKRTTY('$', FSKRTTYbaudDelay); + } + + for (index = 0; index <= Count; index++) + { + Send_FSKRTTY(lora_TXBUFF[index], FSKRTTYbaudDelay); + } + Send_FSKRTTY(13, FSKRTTYbaudDelay); //finish RTTY with carriage return + Send_FSKRTTY(10, FSKRTTYbaudDelay); //and line feed + digitalWrite(LED1, LOW); //make sure LED off + lora_TXOFF(); //to ensure TXTime updated correctly + } + + if (readConfigByte(SearchEnable)) + { + Setup_LoRaSearchMode(); //setup is here so that any mode can be used to TX binary packet + send_LocationBinary(TRLat, TRLon, TRAlt); + } + +} + + +byte buildHABPacket() //expects a char buffer, so this routine will not work without the -permissive setting +{ + //build the long tracker payload + unsigned int index, j, CRC, resets, runmAhr; + int volts; + byte Count,len; + char LatArray[12], LonArray[12]; + + //unsigned long fixtime; + unsigned long sequence; + + sequence = Memory_ReadULong(addr_SequenceNum); //sequence number is kept in non-volatile memory so it survives resets + resets = Memory_ReadUInt(addr_ResetCount); //reset count is kept in non-volatile memory so it survives resets + + Serial.print("Resets "); + Serial.println(resets); + Serial.print("Temperature "); + Serial.println(internal_temperature); + + runmAhr = (current_mASecs / 3600); + + volts = read_SupplyVoltage(); + + if (!readConfigByte(GPSHotFix)) + { + GPSFixTime = 0; //if GPS power save is off (no GPSHotFix), ensure GPS fix time is set to zero + Serial.println("GPSFixTime set to 0"); + } + + sats = gps.satellites.value(); + dtostrf(TRLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TRLon, 7, 5, LonArray); //converts float to character array + len = sizeof(lora_TXBUFF); + memset(lora_TXBUFF, 0, len); //clear array to 0s + + Count = snprintf((char*) lora_TXBUFF, + Output_len_max, + "$$$$%s,%lu,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%lu", + Flight_ID, + sequence, + gps.time.hour(), + gps.time.minute(), + gps.time.second(), + LatArray, + LonArray, + TRAlt, + sats, + volts, + internal_temperature, + resets, + ramc_Current_TXconfig1, + TRStatus, + runmAhr, + ramc_CalibrationOffset, + GPSFixTime + ); + + //Count = strlen(lora_TXBUFF); //how long is the array ? + + CRC = 0xffff; //start value for CRC16 + + for (index = 4; index < Count; index++) //element 4 is first character after $$ at start + { + CRC ^= (((unsigned int)lora_TXBUFF[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + lora_TXBUFF[Count++] = '*'; + lora_TXBUFF[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + lora_TXBUFF[Count++] = Hex((CRC >> 8) & 15); + lora_TXBUFF[Count++] = Hex((CRC >> 4) & 15); + lora_TXBUFF[Count] = Hex(CRC & 15); + return Count; +} + +char Hex(byte lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + + +void send_LocationBinary(float Lat, float Lon, unsigned int Alt) +{ + Write_Float(0, Lat, lora_TXBUFF); + Write_Float(4, Lon, lora_TXBUFF); + Write_Int(8, Alt, lora_TXBUFF); + Write_Byte(10, TRStatus, lora_TXBUFF); + + digitalWrite(LED1, HIGH); + Serial.println(F("Send Binary Location")); + lora_Send(0, 10, LocationBinaryPacket, Broadcast, ramc_ThisNode, 10, lora_Power, 0); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd + digitalWrite(LED1, LOW); +} + + +void inside_fence_no_transmit() +{ + Setup_LoRaCommandMode(); //commands can be sent in any mode, make sure this is sent using the right frequency etc + Listen(ramc_Cmd_WaitSecs); //wait for command packet} +} + + +void action_outside_fence() +{ + sleepSecs(outside_fence_Sleep_seconds); //goto sleep for a long time + lora_Setup(); + Setup_LoRaCommandMode(); + Listen(Cmd_WaitSecs); + Listen(Cmd_WaitSecs); +} + + +byte doFenceCheck() //checks to see if GPS location is within an Western and Eastern limit +{ + //there has been a fix, so check fence limits + Fence_Check_Lon = gps.location.lng(); + +#ifdef DEBUGNoGPS + Fence_Check_Lon = TestLongitude; +#endif + +#ifdef DEBUG + Serial.print(Fence_Check_Lon, 6); + Serial.print(F(" ")); +#endif + + if ((Fence_Check_Lon > west_fence) && (Fence_Check_Lon < east_fence)) //approximate to the limits for region 1 ISM band + { + Serial.println(F("Inside Fence")); + return 1; //within the fence + } + else + { + Serial.println(F("Outside Fence")); + return 0; + } + //outside the fence +} + + +void printPayload(byte lCount) +{ + byte index; + for (index = 0; index <= lCount; index++) + { + Serial.write(lora_TXBUFF[index]); + } +} + + +void updatemAUsed() +{ + unsigned long i; + Serial.println(F("Update mA")); + addmASecs(TXmA, lora_TXTime, 1); //add TXTime current consumed current to total + addmASecs(RXmA, lora_RXTime, 2); //add RXTime current consumed current to total + + if (readConfigByte(GPSHotFix)) + { + addmASecs(GPSmA, (GPSFixTime + GPSShutdownTimemS), 3); //add GPS consumed current to total only if power save (GPSHotFix) enabled + } + + UPTime = (millis() - UPStart); + addmASecs(runmA, UPTime, 4); //add run current consumed current to total + i = current_Sleepsecs * 1000; //convert total Sleepsecs this loop into mS + addmASecs(SleepmA, i, 5); + Memory_WriteULong(addr_mASecs, current_mASecs); //save running mASecs into memory + current_Sleepsecs = 0; +} + + +void addmASecs(float lmAamp, unsigned long lmillis, byte number) +{ + //adds to the running total of current_mASecs, i.e 10mA for 2000mS = 20mAmS + //for a long unsigned int max Count = 4294967296 or 4294967 mAMins or 71582 maHr + unsigned long i; + i = (unsigned long) ((lmillis * lmAamp) / 1000) ; //calculate the mASecs, divide the time by 1000 + current_mASecs = current_mASecs + i; + Serial.print(number); + Serial.print(F(" mASecs ")); + Serial.println(current_mASecs); +} + + +void printTimes() +{ + //print the times used to calculate mAhr used + Serial.print(F("TXTime ")); + Serial.print(lora_TXTime); + Serial.println(F("mS")); + Serial.print(F("RXTime ")); + Serial.print(lora_RXTime); + Serial.println(F("mS")); + Serial.print(F("UPTime ")); + Serial.print((millis() - UPStart)); + Serial.println(F("mS")); + Serial.print(F("mASecs ")); + Serial.println(current_mASecs); + Serial.print(F("mAHour ")); + Serial.println((current_mASecs) / 3600); +} + + +void Listen(unsigned int seconds) +{ + //listen (in seconds) for an incoming packet using the current frequency and LoRa modem settings + unsigned long tilltime; + tilltime = (millis() + (seconds * 1000)); + Serial.print(F("Listen ")); + Serial.println(seconds); + + lora_RXONLoRa(); + + while (millis() < tilltime) + { + checkForPacket(); + } + lora_RXOFF(); //as we have finished listening +} + + +void checkForPacket() +{ + //check LoRa device to see if a command packet has arrived + byte lora_Ltemp; + + lora_Ltemp = lora_readRXready(); + + if (lora_Ltemp > 0) + { + + Serial.print(F("RX ")); + + if (lora_Ltemp == 64) + { + //packet has arrived + lora_ReadPacket(); + +#ifdef DEBUG + Serial.write(lora_RXPacketType); + Serial.write(lora_RXDestination); + Serial.write(lora_RXSource); + Serial.println(); +#endif + } + else + { + //packet arrived with error + Serial.println(F("Error")); + lora_RXOFF(); + lora_RXONLoRa(); + } + + if (promiscuous_Mode) //can we accept packet from any source + { + processPacket(); + lora_RXONLoRa(); + } + + if (!promiscuous_Mode) //can we only accepts packet from known node + { + if (lora_RXSource == ramc_RemoteControlNode) + { + processPacket(); + lora_RXONLoRa(); //ready for next and clear flags + } + else + { + Serial.println(F("Rejected")); + lora_RXOFF(); + Setup_LoRaCommandMode(); + send_Command(NACK); + lora_RXONLoRa(); + } + } + } +} + + +void processPacket() +{ + //we have a packet so lets decide what to do with it + byte j, ptr; + unsigned int i; + + if (lora_RXPacketType == Test) + { + if (lora_RXBUFF[0] == '0') + { + Serial.println(F("Pkt Test")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + delay(inter_Packet_delay); + sendTest(); + } + + if (lora_RXBUFF[0] == '1') + { + Serial.println(F("FSKRTTY Test")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + delay(inter_Packet_delay); + Send_FSKRTTYTest(); + } + + } + + if (lora_RXPacketType == LinkReport) + { + send_Command(ACK); + delay(inter_Packet_delay); + Serial.println(F("Link Report")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(Info); + } + + + if (lora_RXPacketType == Config0) //is it a change config byte request ? + { + Serial.println(F("Prog Cfgbyte")); + + i = ((lora_RXBUFF[0] - 48)); //config byte requests come in as ASCCI, '1' for 1 etc + j = ((lora_RXBUFF[1] - 48)); + setConfigByte(i, j); + lora_RXBuffPrint(0); //print packet contents as ASCII + Serial.println(); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); //send the ack + + } + + if (lora_RXPacketType == ResetTracker) //is it a reset ? + { + Serial.println(F("Reset ?")); + lora_RXBuffPrint(0); //print packet contents as ASCII + Serial.println(); + + if ( isKeyValid() ) + { + Serial.println(F("Valid")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + Serial.flush(); + sleepSecs(2); + softReset(); + } + else + { + Serial.println(F("Invalid")); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(NACK); + } + } + + if (lora_RXPacketType == WritePacketMemory) + { + Serial.println(F("Write Memory")); + writePacketMemory(); + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + } + + if (lora_RXPacketType == INCFreq) + { + Serial.println(F("IncOffset 1KHZ")); + ramc_CalibrationOffset = ramc_CalibrationOffset + 1000; + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + printRAMFrequencies(); + } + + if (lora_RXPacketType == DECFreq) + { + Serial.println(F("DecOffset 1KHZ")); + ramc_CalibrationOffset = ramc_CalibrationOffset - 1000; + delay(inter_Packet_delay); + Setup_LoRaCommandMode(); + send_Command(ACK); + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + printRAMFrequencies(); + } + + if (lora_RXPacketType == Bind) + { + + if (isKeyValid()) //only accept bind request when key is valid + { + + ptr = 4; //bind packet has 4 bytes of key + Serial.println(F("Bind RX")); + + for (i = addr_StartBindData; i <= addr_EndBindData; i++) + { + j = lora_RXBUFF[ptr++]; + Memory_WriteByte(i, j); + } + + readSettingsMemory(); + +#ifdef DEBUG + printMemoryFrequencies(); + printRAMFrequencies(); + Print_Config_Memory(); + Print_CRC_Config_Memory(); +#endif + + delay(inter_Packet_delay); + send_Command(ACK); + } + else + { + Serial.println(F("Key not valid")); + } + + } +} + + +void printMemoryFrequencies() +{ + //a useful check to see if memory is configured correctly + unsigned long tempULong; + tempULong = Memory_ReadULong(addr_TrackerMode_Frequency); + Serial.print(F("Memory Tracker Freq ")); + Serial.println(tempULong); + + tempULong = Memory_ReadULong(addr_SearchMode_Frequency); + Serial.print(F("Memory Search Freq ")); + Serial.println(tempULong); + + tempULong = Memory_ReadULong(addr_CommandMode_Frequency); + Serial.print(F("Memory Command Freq ")); + Serial.println(tempULong); +} + + +void printRAMFrequencies() +{ + Serial.print(F("RAM Tracker Freq ")); + Serial.println(ramc_TrackerMode_Frequency); + + Serial.print(F("RAM Search Freq ")); + Serial.println(ramc_SearchMode_Frequency); + + Serial.print(F("RAM Command Freq ")); + Serial.println(ramc_CommandMode_Frequency); + + Serial.print(F("RAM Calibration Offset ")); + Serial.println(ramc_CalibrationOffset); +} + + +boolean isKeyValid() +{ + if ( (lora_RXBUFF[0] == key0) && (lora_RXBUFF[1] == key1) && (lora_RXBUFF[2] == key2) && (lora_RXBUFF[3] == key3) ) + { + return true; + } + else + { + return false; + } +} + + +void softReset() +{ + asm volatile (" jmp 0"); +} + + +void send_Command(char cmd) +{ + unsigned int volts; + volts = read_SupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + Write_Byte(0, lora_PacketSNR, lora_TXBUFF); //so that receiver alwsys knows last received SNR + Write_Byte(1, lora_PacketRSSI, lora_TXBUFF); //so that receiver alwsys knows last received RSSI + Write_UInt(2, volts, lora_TXBUFF); + Write_Byte(4, TRStatus, lora_TXBUFF); + digitalWrite(LED1, HIGH); + lora_Send(0, 4, cmd, Broadcast, ramc_ThisNode, 10, lora_Power, 0); + digitalWrite(LED1, LOW); +} + + +void sendTest() +{ + byte power; + for (power = 10; power >= 2; power--) + { + Setup_LoRaTrackerMode(); + lora_TXBUFF[0] = '0'; + lora_TXBUFF[1] = power + 48; + lora_TXEnd = 1; + + if (power == 10) + { + lora_TXBUFF[0] = '1'; + lora_TXBUFF[1] = '0'; + lora_TXEnd = 2; + } + + Serial.print(F("Send ")); + Serial.print(power); + Serial.println(F("dBm")); + + lora_Send(0, 1, Test, Broadcast, ramc_ThisNode, 10, power, 0); //send the test packet + sleepSecs(2); + } +} + + +void Send_FSKRTTYTest() +{ + byte power; + + Start_FSKRTTY(FSKRTTYRegshift, FSKRTTYleadin, FSKRTTYpips); + Send_FSKRTTY(13, FSKRTTYbaudDelay); + Send_FSKRTTY(10, FSKRTTYbaudDelay); + + for (power = 10; power >= 2; power--) + { + lora_TXONDirect(power); + delay(200); + Send_FSKRTTY(' ', FSKRTTYbaudDelay); + + + if (power == 10) + { + Send_FSKRTTY('1', FSKRTTYbaudDelay); + Send_FSKRTTY('0', FSKRTTYbaudDelay); + } + else + { + Send_FSKRTTY('0', FSKRTTYbaudDelay); + Send_FSKRTTY(power + 48, FSKRTTYbaudDelay); + } + delay(200); + } + Send_FSKRTTY(13, FSKRTTYbaudDelay); + Send_FSKRTTY(10, FSKRTTYbaudDelay); + lora_Setup(); +} + + +void sleepSecs(unsigned int LNumberSleeps) +{ + unsigned int i; + + Serial.print(F("zz ")); + Serial.println(LNumberSleeps); + Serial.flush(); //let print complete +#ifdef USING_SERIALGPS + GPSserial.end(); //we dont want GPS input interfering with sleep, make sure its off +#endif + digitalWrite(lora_NSS, HIGH); //ensure LoRa Device is off + + for (i = 1; i <= LNumberSleeps; i++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep 1 second + pulseWDI(); + } + current_Sleepsecs = current_Sleepsecs + LNumberSleeps; +} + + +void incMemoryULong(unsigned int laddress) +{ + unsigned long val; + val = Memory_ReadULong(laddress); + val++; + Memory_WriteULong(laddress, val); +} + + +byte readConfigByte(byte bitnum) +{ + return bitRead(ramc_Current_TXconfig1, bitnum); +} + + +void setConfigByte(byte bitnum, byte bitval) +{ + //program the config byte + + if (bitval == 0) + { + bitClear(ramc_Current_TXconfig1, bitnum); + } + else + { + bitSet(ramc_Current_TXconfig1, bitnum); + } + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + +#ifdef DEBUG + if (bitval) + { + Serial.print(F("Set Config Bit ")); + } + else + { + Serial.print(F("Clear Config Bit ")); + } + Serial.println(bitnum); + +#endif +} + + +void setStatusByte(byte bitnum, byte bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } + +#ifdef DEBUG + if (bitval) + { + Serial.print(F("Set Status Bit ")); + } + else + { + Serial.print(F("Clear Status Bit ")); + } + + Serial.println(bitnum); +#endif +} + + +void pulseWDI() +{ + //if the watchdog is fitted it needs a regular pulse top prevent reset + //togle the WDI pin twice + digitalWrite(WDI, !digitalRead(WDI)); + delayMicroseconds(1); + digitalWrite(WDI, !digitalRead(WDI)); +} + + +boolean gpsWaitFix(unsigned long waitSecs, byte StartState, byte LeaveState) +{ + //waits a specified number of seconds for a fix, returns true for good fix + //StartState when set to 1 will turn GPS on at routine start + //LeaveState when set to 0 will turn GPS off at routine end, used perhaps when there is no fix + + unsigned long endwaitmS, millistowait, currentmillis; + pulseWDI(); + byte GPSByte; + //ong temp; + + if (StartState == 1) + { + GPS_On(DoGPSPowerSwitch); + GPSonTime = millis(); + } + else + { + GPS_On(NoGPSPowerSwitch); + } + +#ifdef Check_GPS_Navigation_Model_OK + Serial.println(F("Check GPSNavigation Model")); + if (!GPS_CheckNavigation()) + { + //something wrong with GPS, navigation mode not set so reconfigure the GPS + Serial.println(F("GPS Configuration Error !!!!")); + GPS_Setup(); + } +#endif + + + Serial.print(F("Wait Fix ")); + Serial.print(waitSecs); + Serial.println(F(" Secs")); + + currentmillis = millis(); + millistowait = waitSecs * 1000; + endwaitmS = currentmillis + millistowait; + + while (millis() < endwaitmS) + { + + do + { + GPSByte = GPS_GetByte(); + if (GPSByte != 0xFF) + { + gps.encode(GPSByte); + } + } + while (GPSByte != 0xFF); + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + Serial.println(F("GPS Fix")); + TRLat = gps.location.lat(); + TRLon = gps.location.lng(); + TRAlt = (unsigned int) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TRAlt > 60000) + { + TRAlt = 0; + } + + if (readConfigByte(GPSHotFix)) + { + GPS_Off(DoGPSPowerSwitch); + GPSFixTime = (millis() - GPSonTime); + //GPSoffTime = millis(); + Serial.print(F("GPS FixTime ")); + Serial.print(GPSFixTime); + Serial.println(F("mS")); + } + else + { + GPS_Off(NoGPSPowerSwitch); + } + + setStatusByte(GPSFix, 1); + pulseWDI(); + return true; + } + +#ifdef UBLOX + if (GNGGAFIXQ.age() < 2000) //check to see if GLONASS has gone active + { + Serial.println(F("GLONASS !")); + setStatusByte(GLONASSisoutput, 1); + GPS_SetGPMode(); + GPS_SetCyclicMode(); + sleepSecs(1); + } + else + { + setStatusByte(GLONASSisoutput, 0); //GLONASS not detected + } +#endif + + + + } + + //if here then there has been no fix and a timeout + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(F("No Fix")); + + if (LeaveState == 0) + { + //no fix and gpsWaitFix called with gpspower to be turned off on exit + GPS_Off(DoGPSPowerSwitch); + } + else + { + //no fix but gpsWaitFix called with gpspower to be left on at exit + GPS_Off(NoGPSPowerSwitch); + } + + pulseWDI(); + return false; +} + + +void readSettingsDefaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Config Defaults")); + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_TrackerMode_Bandwidth = TrackerMode_Bandwidth; + ramc_TrackerMode_SpreadingFactor = TrackerMode_SpreadingFactor; + ramc_TrackerMode_CodeRate = TrackerMode_CodeRate; + ramc_TrackerMode_Power = TrackerMode_Power; + + ramc_SearchMode_Frequency = SearchMode_Frequency; + ramc_SearchMode_Bandwidth = SearchMode_Bandwidth; + ramc_SearchMode_SpreadingFactor = SearchMode_SpreadingFactor; + ramc_SearchMode_CodeRate = SearchMode_CodeRate; + ramc_SearchMode_Power = SearchMode_Power; + + ramc_CommandMode_Frequency = CommandMode_Frequency; + ramc_CommandMode_Bandwidth = CommandMode_Bandwidth; + ramc_CommandMode_SpreadingFactor = CommandMode_SpreadingFactor; + ramc_CommandMode_CodeRate = CommandMode_CodeRate; + ramc_CommandMode_Power = CommandMode_Power; + + ramc_ThisNode = ThisNode; + ramc_RemoteControlNode = RemoteControlNode; + + ramc_Current_TXconfig1 = Default_config1; + ramc_Cmd_WaitSecs = Cmd_WaitSecs; + ramc_WaitGPSFixSeconds = WaitGPSFixSeconds; + ramc_Sleepsecs = Loop_Sleepsecs; + ramc_promiscuous_Mode = promiscuous_Mode; + + ramc_FSKRTTYbaudDelay = FSKRTTYbaudDelay; + ramc_FSKRTTYRegshift = FSKRTTYRegshift; + ramc_FSKRTTYpips = FSKRTTYpips; + ramc_FSKRTTYleadin = FSKRTTYleadin; + + ramc_key0 = key0; + ramc_key1 = key1; + ramc_key2 = key2; + ramc_key3 = key3; + + ramc_CalibrationOffset = CalibrationOffset; +} + + +void readSettingsMemory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Config from Memory")); + + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_TrackerMode_Bandwidth = Memory_ReadByte(addr_TrackerMode_Bandwidth); + ramc_TrackerMode_SpreadingFactor = Memory_ReadByte(addr_TrackerMode_SpreadingFactor); + ramc_TrackerMode_CodeRate = Memory_ReadByte(addr_TrackerMode_CodeRate); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + + ramc_SearchMode_Frequency = Memory_ReadULong(addr_SearchMode_Frequency); + ramc_SearchMode_Bandwidth = Memory_ReadByte(addr_SearchMode_Bandwidth); + ramc_SearchMode_SpreadingFactor = Memory_ReadByte(addr_SearchMode_SpreadingFactor); + ramc_SearchMode_CodeRate = Memory_ReadByte(addr_SearchMode_CodeRate); + ramc_SearchMode_Power = Memory_ReadByte(addr_SearchMode_Power); + + ramc_CommandMode_Frequency = Memory_ReadULong(addr_CommandMode_Frequency); + ramc_CommandMode_Bandwidth = Memory_ReadByte(addr_CommandMode_Bandwidth); + ramc_CommandMode_SpreadingFactor = Memory_ReadByte(addr_CommandMode_SpreadingFactor); + ramc_CommandMode_CodeRate = Memory_ReadByte(addr_CommandMode_CodeRate); + ramc_CommandMode_Power = Memory_ReadByte(addr_CommandMode_Power); + + ramc_ThisNode = Memory_ReadByte(addr_ThisNode);; + ramc_RemoteControlNode = Memory_ReadByte(addr_RemoteControlNode);; + + ramc_Current_TXconfig1 = Memory_ReadByte(addr_Default_config1); + ramc_Cmd_WaitSecs = Memory_ReadByte(addr_Cmd_WaitSecs); + ramc_WaitGPSFixSeconds = Memory_ReadUInt(addr_WaitGPSFixSeconds); + ramc_Sleepsecs = Memory_ReadUInt(addr_Sleepsecs); + ramc_promiscuous_Mode = Memory_ReadByte(addr_promiscuous_Mode); + + ramc_FSKRTTYbaudDelay = Memory_ReadUInt(addr_FSKRTTYbaudDelay); + ramc_FSKRTTYRegshift = Memory_ReadByte(addr_FSKRTTYRegshift); + ramc_FSKRTTYpips = Memory_ReadByte(addr_FSKRTTYpips); + ramc_FSKRTTYleadin = Memory_ReadUInt(addr_FSKRTTYleadin); + ramc_key0 = Memory_ReadByte(addr_key0); + ramc_key1 = Memory_ReadByte(addr_key1); + ramc_key2 = Memory_ReadByte(addr_key2); + ramc_key3 = Memory_ReadByte(addr_key3); + + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + + readIDMemory(); +} + + +void writeSettingsMemory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) + + Serial.println(F("Write RAM Settings to Memory")); + + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //fill config area with 0 + writeIDMemory(); + + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Bandwidth, ramc_TrackerMode_Bandwidth); + Memory_WriteByte(addr_TrackerMode_SpreadingFactor, ramc_TrackerMode_SpreadingFactor); + Memory_WriteByte(addr_TrackerMode_CodeRate, ramc_TrackerMode_CodeRate); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + + Memory_WriteULong(addr_SearchMode_Frequency, ramc_SearchMode_Frequency); + Memory_WriteByte(addr_SearchMode_Bandwidth, ramc_SearchMode_Bandwidth); + Memory_WriteByte(addr_SearchMode_SpreadingFactor, ramc_SearchMode_SpreadingFactor); + Memory_WriteByte(addr_SearchMode_CodeRate, ramc_SearchMode_CodeRate); + Memory_WriteByte(addr_SearchMode_Power, ramc_SearchMode_Power); + + Memory_WriteULong(addr_CommandMode_Frequency, ramc_CommandMode_Frequency); + Memory_WriteByte(addr_CommandMode_Bandwidth, ramc_CommandMode_Bandwidth); + Memory_WriteByte(addr_CommandMode_SpreadingFactor, ramc_CommandMode_SpreadingFactor); + Memory_WriteByte(addr_CommandMode_CodeRate, ramc_CommandMode_CodeRate); + Memory_WriteByte(addr_CommandMode_Power, ramc_CommandMode_Power); + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + Memory_WriteByte(addr_RemoteControlNode, ramc_RemoteControlNode); + + Memory_WriteByte(addr_ThisNode, ramc_ThisNode); + Memory_WriteByte(addr_RemoteControlNode, ramc_RemoteControlNode); + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + Memory_WriteByte(addr_Cmd_WaitSecs, ramc_Cmd_WaitSecs); + Memory_WriteUInt(addr_WaitGPSFixSeconds, ramc_WaitGPSFixSeconds); + Memory_WriteUInt(addr_Sleepsecs, ramc_Sleepsecs); + Memory_WriteByte(addr_promiscuous_Mode, ramc_promiscuous_Mode); + + Memory_WriteUInt(addr_FSKRTTYbaudDelay, ramc_FSKRTTYbaudDelay); + Memory_WriteByte(addr_FSKRTTYRegshift, ramc_FSKRTTYRegshift); + Memory_WriteByte(addr_FSKRTTYpips, ramc_FSKRTTYpips); + Memory_WriteUInt(addr_FSKRTTYleadin, ramc_FSKRTTYleadin); + Memory_WriteByte(addr_key0, ramc_key0); + Memory_WriteByte(addr_key1, ramc_key1); + Memory_WriteByte(addr_key2, ramc_key2); + Memory_WriteByte(addr_key3, ramc_key3); + + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); +} + + +void writeIDMemory() +{ + unsigned int i, addr; + byte j; + j = sizeof(Flight_ID); + j--; + addr = addr_FlightID; + for (i = 0; i <= j; i++) + { + Memory_WriteByte(addr, Flight_ID[i]); + addr++; + } +} + +void readIDMemory() +{ + unsigned int addr; + byte i; + byte j = 0; + + addr = addr_FlightID; + do + { + i = Memory_ReadByte(addr); + Flight_ID[j++] = i; + addr++; + } + while (i != 0) ; +} + + +void saveKeyin_buffer() +{ + lora_TXBUFF[0] = key0; //key used in sme packets to reduce chances of a change being applied by accident + lora_TXBUFF[1] = key1; + lora_TXBUFF[2] = key2; + lora_TXBUFF[3] = key3; +} + + +void printMemoryChange(byte number) +{ +#ifdef DEBUG + byte index, j; + Serial.print(F("Memory Change")); + for (index = 0; index <= number; index++) + { + j = lora_RXBUFF[index]; + Serial.print(F(" ")); + Serial.print(j, HEX); + } + Serial.println(); +#endif +} + + +void writePacketMemory() +{ + //there is an incoming packet which is a request to write bytes to Memory. + //the effect is to change stored program definitions and constants + byte i, j, k, ptr; + //byte i, j, k, ptr, low, high; + unsigned int addr_Memory; + //float tempfloat; + + //packet format is key0, key1, key2, key3, number of bytes to write, address to write to, bytes to write + //terminate list with 0 bytes to write. + + if (isKeyValid()) + { + Serial.print(F("Not Valid")); + return; + } + + i = lora_RXPacketL - 4; //end of packet will be length - 1 for 0 offset and -3 for adddress bytes + + printMemoryChange(i); + + ptr = 4; + + j = lora_RXBUFF[ptr++]; + + addr_Memory = Read_Int(5, lora_RXBUFF); //read address for frequency offset into buffer + + ptr++; + ptr++; + + Serial.println(F("Write memory ")); + + for (i = 1; i <= j; i++) + { + Memory_WriteByte(addr_Memory, lora_RXBUFF[ptr]); + k = lora_RXBUFF[ptr]; + Serial.print(k, HEX); + Serial.print(F(" ")); + addr_Memory++; + ptr++; + } + readSettingsMemory(); + Setup_LoRaTrackerMode(); //dummy change so we can see if offset chnages +} + + + +void sendTrackerBind() +{ + unsigned int i, j; + byte msb_CRC, lsb_CRC; + unsigned int bindCRC; + + saveKeyin_buffer(); //loads key in bytes 0,1,2,3 of TX buffer + + lora_TXEnd = 4; //this is where the bind data starts + + for (i = addr_StartBindData; i <= addr_EndBindData; i++) + { + j = Memory_ReadByte(i); + lora_TXBUFF[lora_TXEnd++] = j; + } + + bindCRC = Print_CRC_Bind_Memory(); + msb_CRC = highByte(bindCRC); + lsb_CRC = lowByte(bindCRC); + lora_TXBUFF[lora_TXEnd++] = lsb_CRC; + lora_TXBUFF[lora_TXEnd] = msb_CRC; + +#ifdef DEBUG + Serial.print(F("Bind PacketLen ")); + Serial.println(lora_TXEnd + 4); //allow for 3 addressing bytes in length, plus 1 for packet starting at [0] +#endif + + lora_Send(0, lora_TXEnd, Bind, ramc_RemoteControlNode, ramc_ThisNode, 10, BindMode_Power, 0); + +} + + +void printNodes() +{ + Serial.print(F("ThisNode ")); + Serial.print(ramc_ThisNode); + Serial.print(F(" RemoteNode ")); + Serial.println(ramc_RemoteControlNode); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_TrackerMode_Bandwidth, ramc_TrackerMode_SpreadingFactor, ramc_TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters for tracker mode + lora_Power = ramc_TrackerMode_Power; +} + + +void Setup_LoRaSearchMode() +{ + lora_SetFreq(ramc_SearchMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_SearchMode_Bandwidth, ramc_SearchMode_SpreadingFactor, ramc_SearchMode_CodeRate, Explicit); //Setup the LoRa modem parameters for search mode +} + + +void Setup_LoRaCommandMode() +{ + lora_SetFreq(ramc_CommandMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_CommandMode_Bandwidth, ramc_CommandMode_SpreadingFactor, ramc_CommandMode_CodeRate, Explicit); //Setup the LoRa modem parameters for command mode + lora_Power = ramc_CommandMode_Power; +} + + +void Setup_LoRaBindMode() +{ + lora_SetFreq(BindMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(BindMode_Bandwidth, BindMode_SpreadingFactor, BindMode_CodeRate, Explicit); //Setup the LoRa modem parameters for bind mode + lora_Power = BindMode_Power; +} + + +void display_current_frequency() +{ + float freq_temp; + freq_temp = lora_GetFreq(); + Serial.print(F("Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + +void do_ClearSavedData() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear Saved Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear All Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void Print_Config_Memory() +{ + //prints the memory used for storing configuration settings + byte memory_LLoopv1; + byte memory_LLoopv2; + unsigned int memory_Laddr = 0; + byte memory_Ldata; + //unsigned int CRC; + Serial.println(F("Config Memory")); + Serial.print(F("Lcn 0 1 2 3 4 5 6 7 8 9 A B C D E F")); + Serial.println(); + + for (memory_LLoopv1 = 0; memory_LLoopv1 <= 15; memory_LLoopv1++) + { + Serial.print(F("0x")); + Serial.print(memory_LLoopv1, HEX); //print the register number + Serial.print(F("0 ")); + for (memory_LLoopv2 = 0; memory_LLoopv2 <= 15; memory_LLoopv2++) + { + memory_Ldata = Memory_ReadByte(memory_Laddr); + if (memory_Ldata < 0x10) { + Serial.print(F("0")); + } + Serial.print(memory_Ldata, HEX); //print the register number + Serial.print(F(" ")); + memory_Laddr++; + } + Serial.println(); + } +} + + +void Print_CRC_Config_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartConfigData, addr_EndConfigData); + Serial.print(F("CRC_Config ")); + Serial.println(returnedCRC, HEX); +} + + +unsigned int Print_CRC_Bind_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("Local BindCRC ")); + Serial.println(returnedCRC, HEX); + return returnedCRC; +} + + +void setup() +{ + unsigned long int i; + unsigned int j; + + pinMode(LED1, OUTPUT); //for PCB LED + pinMode(WDI, OUTPUT); //for Watchdog pulse input + + led_Flash(2, 500); + + Serial.begin(38400); //Setup Serial console ouput + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); +#endif + + + Serial.println(F(programname)); + Serial.println(F(aurthorname)); + + pinMode(GPSPOWER, OUTPUT); //in case power switching components are fitted + GPS_On(DoGPSPowerSwitch); //this will power the GPSon + GPSonTime = millis(); + +#ifdef USING_SERIALGPS + GPSserial.end(); //but we dont want soft serial running for now, it interferes with the LoRa device +#endif + + pinMode(lora_NReset, OUTPUT); //LoRa device reset line + digitalWrite(lora_NReset, HIGH); + + pinMode (lora_NSS, OUTPUT); //set the slave select pin as an output: + digitalWrite(lora_NSS, HIGH); + + SPI.begin(); //initialize SPI + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + + +#ifdef ClearSavedData + do_ClearSavedData(); +#endif + + Serial.print(F("Default_Config1 ")); + Serial.println(Default_config1, BIN); + current_mASecs = Memory_ReadULong(addr_mASecs); + + Serial.print(F("mASecs ")); + Serial.println(current_mASecs); + + j = Memory_ReadUInt(addr_ResetCount); + j++; + Memory_WriteUInt(addr_ResetCount, j); + Serial.print(F("Resets ")); + Serial.println(j); + Serial.print(F("Sequence ")); + i = Memory_ReadULong(addr_SequenceNum); + Serial.println(i); + + +#ifdef ConfigureDefaults + readSettingsDefaults(); + writeSettingsMemory(); +#endif + + +#ifdef ConfigureFromMemory + readSettingsMemory(); +#endif + + Print_CRC_Config_Memory(); + + ramc_ThisNode = ThisNode; + +#ifdef DEBUG + printNodes(); +#endif + + lora_Setup(); + + if (!lora_CheckDevice()) + { + led_Flash(100, 50); //long medium speed flash for Lora device error + Serial.println(F("LoRa Error!")); + } + +#ifdef DEBUG + display_current_frequency(); +#endif + + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); //get calibration offset for this tracker + Serial.print(F("Cal Offset ")); + Serial.println(ramc_CalibrationOffset); + +#ifdef DEBUG + lora_Print(); +#endif + + Serial.println(); + print_SupplyVoltage(); + print_Temperature(); + Serial.println(); + + j = read_SupplyVoltage(); //get supply mV + Write_Int(0, j, lora_TXBUFF); //write to first two bytes of buffer + Write_Byte(2, ramc_Current_TXconfig1, lora_TXBUFF); //add the current config byte + + Setup_LoRaTrackerMode(); + send_Command(PowerUp); //send power up command, includes supply mV and config, on tracker settings + sleepSecs(1); + +#ifdef SendBind + if (readConfigByte(TXEnable)) //is TX enabled ? + { + Setup_LoRaBindMode(); + sendTrackerBind(); + } +#endif + + Setup_LoRaTrackerMode(); //so that check tone is at correct frequency + + GPS_Config_Error = false; //make sure GPS error flag is cleared + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); //GPS should have been on for a while by now, so this is just to start soft serial + GPSonTime = millis(); + GPS_Setup(); //GPS should have had plenty of time to initialise by now + +#ifdef UBLOX + if (!GPS_CheckNavigation()) //Check that UBLOX GPS is in Navigation model 6 + { + Serial.println(); + GPS_Config_Error = true; + setStatusByte(GPSError, 1); + setStatusByte(UBLOXDynamicModel6Set, 0); + } + else + { + setStatusByte(UBLOXDynamicModel6Set, 1); + } +#endif + + if (GPS_Config_Error) + { + Serial.println(F("GPS Error !")); + Serial.println(); + send_Command(NoGPS); //make sure receiver knows about GPS error + led_Flash(100, 25); //long very rapid flash for GPS error + } + else + { +#ifdef CheckTone + if (readConfigByte(TXEnable)) //is TX enabled - needed because of fence limits + { + Serial.println(F("Check Tone")); //check tone indicates navigation model 6 set (if checktone enabled!) + lora_Tone(1000, 3000, 5); //Transmit an FM tone, 1000hz, 3000ms, 5dBm + } +#endif + } + + digitalWrite(LED1, HIGH); + setStatusByte(NoGPSTestMode, 0); + GPSonTime = millis(); + while (!gpsWaitFix(5, DontSwitch, LeaveOn)) //wait for the initial GPS fix, this could take a while, leave GPS powered on + { + + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + +#ifdef DEBUG + i = (millis() - GPSonTime) / 1000; + Serial.print(F("GPS OnTime ")); + Serial.print(i); + Serial.println(F(" Secs")); +#endif + } + addmASecs(GPSmA, (GPSFixTime + GPSShutdownTimemS), 3); //add GPS consumed current to total +#endif + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled +#endif + + lora_Tone(500, 500, 2); //Transmit an FM tone, 500hz, 500ms, 2dBm + digitalWrite(LED1, LOW); + sleepSecs(2); //wait for GPS to shut down + +#ifdef DEBUGNoGPS + setStatusByte(NoGPSTestMode, 1); +#endif + + setConfigByte(DozeEnable, Disabled); //ensure Doze mode disabled at reset +} diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_101017/LoRaTracker_HAB2_Settings.h b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_101017/LoRaTracker_HAB2_Settings.h new file mode 100644 index 0000000..8d39f36 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_101017/LoRaTracker_HAB2_Settings.h @@ -0,0 +1,273 @@ +//LoRaTracker_HAB2_Settings.h +/* +****************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 10/10/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To Do: + + Changes: + 101017 Removed unused board definitions + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +#define CPU_VoltageRead +//#define External_VoltageRead + +#define CPU_TemperatureRead +//#define External_TemperatureRead //assumes a TC74 is in use + +const int Temperature_Adjust = 0; //to allow calibration of external temperature sensor +#define TC74_Address 0x4c //init with TC74 address, can be 0x48 to 0x4F depending on specific type + +#define Board_Definition "HAB2_Board_Definitions.h" //define the board to use here + +const float runmA = 4; //processor run current +const float SleepmA = 0.22; //approx current in sleep, Ublox GPS consumes circa 200uA + + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + + +//#define ConfigureDefaults //Configure settings from default program constants, save in memory and copy to RAM, need to do this once only +//#define ClearAllMemory //Clears from start memory to end memory, normally 1kbyte, needs to be folloowed by ConfigureDefaults +//#define ClearSavedData //zero the saved data, resets, sequence, Mahr +#define ConfigureFromMemory //Read settings from attached memory + +const byte Output_len_max = 125; //maximum length for built payload +#define CheckTone //comment in to have a calibrate tone at startup, also indicates navigation model 6 set + +//#define DEBUG //if defined, prints additional debug information to terminal + +const int DozeSleepSecs = 180; //how many seconds to spend in doze (very low power mode), mode can only be enabled remotely + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 433400000; + +//Search mode +const unsigned long SearchMode_Frequency = 433300000; + +//Command mode +const unsigned long CommandMode_Frequency = 433500000; + +//Bind mode - Change this with great care !!!!! +const unsigned long BindMode_Frequency = 434100000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 31000; + + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +//Tracker mode +#define TrackerMode_Bandwidth BW62500 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 +#define TrackerMode_Power 10 + +//Search mode +#define SearchMode_Bandwidth BW62500 +#define SearchMode_SpreadingFactor SF12 +#define SearchMode_CodeRate CR45 +#define SearchMode_Power 10 + +//Command mode +#define CommandMode_Bandwidth BW62500 +#define CommandMode_SpreadingFactor SF10 +#define CommandMode_CodeRate CR45 +#define CommandMode_Power 10 + +//Bind mode +#define BindMode_Bandwidth BW500000 +#define BindMode_SpreadingFactor SF8 +#define BindMode_CodeRate CR45 +#define BindMode_Power 2 + +#define SendBind //at startup tracker transmitter will send a bind packet +//#define LORADEBUG //displays extra debug messages when using LoRa + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 128; +const byte lora_TXBUFF_Size = 128; + +const float RXmA = 11; //LoRa device receive current +const float TXmA = 40; //LoRa device transmit current @ 10dBm + +const int inter_Packet_delay = 500; //allows time for receiver to be ready to see a possible reply, in mS +const byte delayforRelaysecs = 2; //allows time for relay to re-transmit + +const byte Cmd_WaitSecs = 5; //number of seconds to stay in waiting for command mode +const byte Command_Loops = 3; //if one command is received wait for this number of loops to keep control channel open + +//Key Definition +const char key0 = 'B'; //Used to restrict access to some commands +const char key1 = 'A'; +const char key2 = 'R'; +const char key3 = 'T'; + +//************************************************************************************************** +// 5) GPS Options +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +#define GPS_Library "UBLOX_SerialGPS2.h" //define the GPS library routines to use here +//#define GPS_Library "UBLOX_I2CGPS.h" + +//#define DEBUGNoGPS //test mode, does not use GPS +//#define Use_Test_Location //to use test location for transmissions include this define + +//#define GPS_ALLOW_GPGSV //define this so that GPGSV senetences are not turned off + +#define GPSBaud 9600 //GPS Baud rate +#define WhenNoGPSFix LeaveOn //What to do with GPS power when there is no fix at ends of wait period (LeaveOn or LeaveOff) +#define WaitGPSFixSeconds 30 //in flight mode time to wait for a new GPS fix +//#define Remove_GPS_Power //Some tracker boards can remove the power from the GPS, if so define this to use it +#define Use_GPS_SoftwareBackup //some GPSs do not support this mode, Ubloxes do, used for GPS Hotfix option +//#define Check_GPS_Navigation_Model_OK //every time the GPS is checked for a fix we can ceck for correct navigation mode on UBLOX + +const unsigned long GPSShutdownTimemS = 1900; //Software backup mode takes around 1.9secs to power down, used in maHr calculation +const unsigned long fixisoldmS = 10000; //if location has not updated in this number of mS, assume GPS has lost fix +const unsigned long GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const unsigned int GPSFixs = 100; //number of GPS fixes between setting system clock from GPS +const byte GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const byte GPS_Reply_Size = 12; //size of GPS reply buffer +const float GPSmA = 24; //GPS average (UBLOX) current when aquiring fix +const unsigned int GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent + +//Centre of Cardiff Castle keep +#define TestLatitude 51.48230 +#define TestLongitude -3.18136 +#define TestAltitude 48 + + +/* + Passive GPS station: Swanbridge - C1ST1667 + https://www.ordnancesurvey.co.uk/gps/legacy-control-information/C1ST1667 + N 51 23'59.105955", W 3 11',47.413031 + 51.399751654166664, -3.196503619722222 + + #define TestLatitude 51.399752 + #define TestLongitude -3.196504 + #define TestAltitude 0 +*/ + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +//#define Memory_Library "EEPROM_Memory.h" //define this file if the internal EEPROM is in use +#define Memory_Library "I2CFRAM_MB85RC16PNF.h" //define this file if the I2C FRAM is in use + +//************************************************************************************************** +// 8) FSK RTTY Settings +//************************************************************************************************** + +const unsigned int FSKRTTYbaudDelay = 9845; //delay for baud rate for FSK RTTY, 19800 for 50baud, 9845 for 100baud, 4865 for 200baud +const byte FSKRTTYRegshift = 6; //number of frequency steps to use for shift +const byte FSKRTTYpips = 5; //number of FSK lead in pips +const int FSKRTTYleadin = 500; //number of ms for FSK constant lead in tone +const byte sync_chars = 3; //number of extra $ sync characters to send + + +//************************************************************************************************** +// 9) AFSK RTTY Options +//************************************************************************************************** + +const byte delayforAFSKuploadSecs = 4; //allows time for AFSK upload on receiver + + +//**************************************************************************************************** +// 11) Program Default Option settings +// This section determines which options are on or off by default, this is the Default_config1 byte +// Take care here.......... +//************************************************************************************************** + +#define OptionOff 0 +#define OptionOn 1 + +const char option_SearchEnable = OptionOn; +const char option_TXEnable = OptionOn; +const char option_FSKRTTYEnable = OptionOn; +const char option_CheckFence = OptionOff; +const char option_ShortPayloadEnable = OptionOff; +const char option_RepeatEnable = OptionOff; +const char option_AddressStrip = OptionOn; +const char option_GPSHotFix = OptionOff; + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_TXEnable_SUM (option_TXEnable*2) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) +#define option_CheckFence_SUM (option_CheckFence*8) +#define option_ShortPayloadEnable_SUM (option_ShortPayloadEnable*16) +#define option_RepeatEnable_SUM (option_RepeatEnable*32) +#define option_AddressStrip_SUM (option_AddressStrip*64) +#define option_GPSHotFix_SUM (option_GPSHotFix*128) + +//See Program_Definitions.h in the LoRaTracker library for details, the above options translate into Default_config1 byte of 1 + 2 + 4 + 64 = 71 + +const unsigned int Default_config1 = (option_SearchEnable_SUM + option_TXEnable_SUM + option_FSKRTTYEnable_SUM + option_CheckFence_SUM + option_ShortPayloadEnable_SUM + option_RepeatEnable_SUM + option_AddressStrip_SUM + option_GPSHotFix_SUM); +const unsigned int Default_config2 = 0; +const unsigned int Default_config3 = 0; +const unsigned int Default_config4 = 0; +//const unsigned int Default_config1 = 71; //Phew, the default config can always be set manually ............. + + +//************************************************************************************************** +// 12) Miscellaneous program settings +//************************************************************************************************** + + + + + +//************************************************************************************************** +// 13) Unique calibration settings for each Board +// These settings are not part of a bind operation +//************************************************************************************************** + +const float kelvin_offset = 326; //if processor self read of temperature reports high, increase this number +const float temp_conversion_slope = 1.058 ; //defines the rate of change between low and high temperatures +const unsigned long adc_constant = 1146679; //if processor self read of its supply voltage reports high reduce this number + + +//************************************************************************************************** +// 14) HAB2 settings +//************************************************************************************************** + +char Flight_ID[15] = "MyFlight1"; + +const float west_fence = -4; +const float east_fence = 45; + +const unsigned int Loop_Sleepsecs = 25; //sleep time in seconds after each TX loop +const unsigned int outside_fence_Sleep_seconds = 600; //approx 10 minutes +const boolean promiscuous_Mode = true; //if set to True remote control packets from any node accepted + +#define RemoteControlNode 'G' //normally used by tracker transmitter in promiscuous_Mode +#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +#define ThisNode ControlledNode diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_Bare_Bones_200518/LoRaTracker_HAB2_Bare_Bones_200518.ino b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_Bare_Bones_200518/LoRaTracker_HAB2_Bare_Bones_200518.ino new file mode 100644 index 0000000..90ab0f5 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_Bare_Bones_200518/LoRaTracker_HAB2_Bare_Bones_200518.ino @@ -0,0 +1,722 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the HAB2_Settings file not here ! +// +//************************************************************************************************** + +#define programname "LoRaTracker_HAB2_Bare_Bones_200518" +#define aurthorname "Stuart Robinson" + +#include +#include + +#include "LoRaTracker_HAB2_Settings.h" +#include Board_Definition +#include "Program_Definitions.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + Location payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Sats,SupplyVolts,Temperature,Resets,StatusByte,GPSFixTime,Checksum + 0 1 2 3 4 5 6 7 8 9 10 11 12 + + To Do: + + Changes: + + 220518 - Develop a version of the HAB2 software reduced to a minium + 220518 - Size with SoftwareSerial GPS 29996/1407, I2C GPS 28402/1290 + 220518 - Leave with I2C GPS + 220518 - Remove battery use calculation 27440/1286 + 220518 - Remove CPU_VoltageRead option + 220518 - Remove memory storage of config, use system defaults + 220518 - Remove receiver options, fence check 20942/1091 + 220518 - Switch to UBLOX_I2CGPS2.h 20388/1009 + 220518 - Remove unecessary commands and byte definitions 20050/949 + 220518 - Allow removal of detecting GNSS mode, should not be needed for latest TinyGPS++ 19928/905 + +************************************************************************************************** +*/ + +byte TRStatus = 0; //used to store current status flag bits + +byte stripvalue; +byte sats; //either sats in view from GPGSV or sats from NMEA fix sentence +int temperature; + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; + +byte keypress; + +unsigned long GPSonTime; +unsigned long GPSFixTime; +boolean GPS_Config_Error; + +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include //https://github.com/rocketscream/Low-Power + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef Checkfor_GNNS_Mode +TinyGPSCustom GNGGAFIXQ(gps, "GNGGA", 5); //custom sentences used to detect possible switch to GNSS mode +#endif + + +#ifdef USE_SOFTSERIAL_GPS +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPSserial(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial +#endif + +#include GPS_Library //include previously defined GPS Library + +#include "Voltage_Temperature.h" +#include "LoRa3.h" +#include "FSK_RTTY2.h" +#include "Binary2.h" + + +void loop() +{ + Serial.println(); + + GPSFixTime = 0; + temperature = (int) read_Temperature(); //read temp just after sleep, when CPU is closest to ambient + GPSonTime = millis(); + +#ifndef DEBUGNoGPS + gpsWaitFix(WaitGPSFixSeconds, SwitchOn, LeaveOn); +#endif + +#ifdef Use_Test_Location + TRLat = TestLatitude; + TRLon = TestLongitude; + TRAlt = TestAltitude; +#endif + + do_Transmissions(); //do the transmissions + + digitalWrite(lora_NSS, HIGH); //take NSS line high, makes sure LoRa device is off + sleepSecs(Loop_Sleepsecs); //this sleep is used to set overall transmission cycle time + +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + byte index, Count; + + pulseWDI(); + lora_Setup(); //resets then sets up LoRa device + + Setup_LoRaTrackerMode(); + + incMemoryULong(addr_SequenceNum); //increment sequence number + Count = buildHABPacket(); + stripvalue = readConfigByte(AddressStrip); + Serial.println(F("HAB Pkt")); + printPayload(Count); + Serial.println(); + digitalWrite(LED1, HIGH); + lora_Send(0, Count, HABPacket, Broadcast, ThisNode, 10, lora_Power, stripvalue); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd + digitalWrite(LED1, LOW); + + sleepSecs(delayforAFSKuploadSecs); //allow time for receiver AFSK upload + + sleepSecs(delayforRelaysecs); //wait for relay to operate + + if (readConfigByte(FSKRTTYEnable)) + { + + Serial.println(F("FSKRTTY")); + + lora_DirectSetup(); //set for direct mode + lora_SetFreq(TrackerMode_Frequency, CalibrationOffset); + Start_FSKRTTY(FSKRTTYRegshift, FSKRTTYleadin, FSKRTTYpips); + + for (index = 1; index <= sync_chars; index++) + { + Send_FSKRTTY('$', FSKRTTYbaudDelay); + } + + for (index = 0; index <= Count; index++) + { + Send_FSKRTTY(lora_TXBUFF[index], FSKRTTYbaudDelay); + } + Send_FSKRTTY(13, FSKRTTYbaudDelay); //finish RTTY with carriage return + Send_FSKRTTY(10, FSKRTTYbaudDelay); //and line feed + digitalWrite(LED1, LOW); //make sure LED off + lora_TXOFF(); //to ensure TXTime updated correctly + } + + if (readConfigByte(SearchEnable)) + { + Setup_LoRaSearchMode(); //setup is here so that any mode can be used to TX binary packet + send_LocationBinary(TRLat, TRLon, TRAlt); + } +} + + +byte buildHABPacket() //expects a char buffer, so this routine will not work without the -permissive setting +{ + //build the long tracker payload + unsigned int index, j, CRC, resets; + int volts; + byte Count,len; + char LatArray[12], LonArray[12]; + unsigned long sequence; + + sequence = Memory_ReadULong(addr_SequenceNum); //sequence number is kept in non-volatile memory so it survives resets + resets = Memory_ReadUInt(addr_ResetCount); //reset count is kept in non-volatile memory so it survives resets + + volts = read_SupplyVoltage(); + + if (!readConfigByte(GPSHotFix)) + { + GPSFixTime = 0; //if GPS power save is off (no GPSHotFix), ensure GPS fix time is set to zero + } + + sats = gps.satellites.value(); + dtostrf(TRLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TRLon, 7, 5, LonArray); //converts float to character array + len = sizeof(lora_TXBUFF); + memset(lora_TXBUFF, 0, len); //clear array to 0s + + Count = snprintf((char*) lora_TXBUFF, + Output_len_max, + "$$$$%s,%lu,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%d,%d,%lu", + Flight_ID, + sequence, + gps.time.hour(), + gps.time.minute(), + gps.time.second(), + LatArray, + LonArray, + TRAlt, + sats, + volts, + temperature, + resets, + TRStatus, + GPSFixTime + ); + + CRC = 0xffff; //start value for CRC16 + + for (index = 4; index < Count; index++) //element 4 is first character after $$ at start + { + CRC ^= (((unsigned int)lora_TXBUFF[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + lora_TXBUFF[Count++] = '*'; + lora_TXBUFF[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + lora_TXBUFF[Count++] = Hex((CRC >> 8) & 15); + lora_TXBUFF[Count++] = Hex((CRC >> 4) & 15); + lora_TXBUFF[Count] = Hex(CRC & 15); + return Count; +} + + +char Hex(byte lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + + +void send_LocationBinary(float Lat, float Lon, unsigned int Alt) +{ + Write_Float(0, Lat, lora_TXBUFF); + Write_Float(4, Lon, lora_TXBUFF); + Write_Int(8, Alt, lora_TXBUFF); + Write_Byte(10, TRStatus, lora_TXBUFF); + + digitalWrite(LED1, HIGH); + Serial.println(F("Binary Location")); + lora_Send(0, 10, LocationBinaryPacket, Broadcast, ThisNode, 10, lora_Power, 0); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd + digitalWrite(LED1, LOW); +} + + +void printPayload(byte lCount) +{ + byte index; + for (index = 0; index <= lCount; index++) + { + Serial.write(lora_TXBUFF[index]); + } +} + + +void sleepSecs(unsigned int LNumberSleeps) +{ + unsigned int i; + + Serial.print(F("zz ")); + Serial.println(LNumberSleeps); + Serial.flush(); //let print complete +#ifdef USING_SERIALGPS + GPSserial.end(); //we dont want GPS input interfering with sleep, make sure its off +#endif + digitalWrite(lora_NSS, HIGH); //ensure LoRa Device is off + + for (i = 1; i <= LNumberSleeps; i++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep 1 second + pulseWDI(); + } + +} + + +void incMemoryULong(unsigned int laddress) +{ + unsigned long val; + val = Memory_ReadULong(laddress); + val++; + Memory_WriteULong(laddress, val); +} + + +void setStatusByte(byte bitnum, byte bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } + +#ifdef DEBUG + if (bitval) + { + Serial.print(F("Set Status Bit ")); + } + else + { + Serial.print(F("Clear Status Bit ")); + } + + Serial.println(bitnum); +#endif +} + + +byte readConfigByte(byte bitnum) +{ + return bitRead(Default_config1, bitnum); +} + + +void pulseWDI() +{ + //if the watchdog is fitted it needs a regular pulse top prevent reset + //togle the WDI pin twice + digitalWrite(WDI, !digitalRead(WDI)); + delayMicroseconds(1); + digitalWrite(WDI, !digitalRead(WDI)); +} + + +boolean gpsWaitFix(unsigned long waitSecs, byte StartState, byte LeaveState) +{ + //waits a specified number of seconds for a fix, returns true for good fix + //StartState when set to 1 will turn GPS on at routine start + //LeaveState when set to 0 will turn GPS off at routine end, used perhaps when there is no fix + + unsigned long endwaitmS, millistowait, currentmillis; + pulseWDI(); + byte GPSByte; + + if (StartState == 1) + { + GPS_On(DoGPSPowerSwitch); + GPSonTime = millis(); + } + else + { + GPS_On(NoGPSPowerSwitch); + } + +#ifdef Check_GPS_Navigation_Model_OK + Serial.println(F("Check GPSNavigation Model")); + if (!GPS_CheckNavigation()) + { + //something wrong with GPS, navigation mode not set so reconfigure the GPS + Serial.println(F("GPS Config Error !!!!")); + GPS_Setup(); + } +#endif + + + Serial.print(F("Wait Fix ")); + Serial.print(waitSecs); + Serial.println(F(" Secs")); + + currentmillis = millis(); + millistowait = waitSecs * 1000; + endwaitmS = currentmillis + millistowait; + + while (millis() < endwaitmS) + { + + do + { + GPSByte = GPS_GetByte(); + if (GPSByte != 0xFF) + { + gps.encode(GPSByte); + } + } + while (GPSByte != 0xFF); + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + Serial.println(F("GPS Fix")); + TRLat = gps.location.lat(); + TRLon = gps.location.lng(); + TRAlt = (unsigned int) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TRAlt > 60000) + { + TRAlt = 0; + } + + if (readConfigByte(GPSHotFix)) + { + GPS_Off(DoGPSPowerSwitch); + GPSFixTime = (millis() - GPSonTime); + Serial.print(F("FixTime ")); + Serial.print(GPSFixTime); + Serial.println(F("mS")); + } + else + { + GPS_Off(NoGPSPowerSwitch); + } + + setStatusByte(GPSFix, 1); + pulseWDI(); + return true; + } + +#ifdef UBLOX +#ifdef Checkfor_GNNS_Mode + if (GNGGAFIXQ.age() < 2000) //check to see if GNSS mode has gone active + { + Serial.println(F("GNSS !")); + setStatusByte(GLONASSisoutput, 1); + GPS_SetGPMode(); + GPS_SetCyclicMode(); + sleepSecs(1); + } + else + { + setStatusByte(GLONASSisoutput, 0); //GNSS mode not detected + } +#endif +#endif + + + + } + + //if here then there has been no fix and a timeout + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(F("No Fix")); + + if (LeaveState == 0) + { + //no fix and gpsWaitFix called with gpspower to be turned off on exit + GPS_Off(DoGPSPowerSwitch); + } + else + { + //no fix but gpsWaitFix called with gpspower to be left on at exit + GPS_Off(NoGPSPowerSwitch); + } + + pulseWDI(); + return false; +} + + + +void printNodes() +{ + Serial.print(F("ThisNode ")); + Serial.print(ThisNode); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + lora_SetFreq(TrackerMode_Frequency, CalibrationOffset); + lora_SetModem2(TrackerMode_Bandwidth, TrackerMode_SpreadingFactor, TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters for tracker mode + lora_Power = TrackerMode_Power; +} + + +void Setup_LoRaSearchMode() +{ + lora_SetFreq(SearchMode_Frequency, CalibrationOffset); + lora_SetModem2(SearchMode_Bandwidth, SearchMode_SpreadingFactor, SearchMode_CodeRate, Explicit); //Setup the LoRa modem parameters for search mode + lora_Power = SearchMode_Power; +} + + +void send_Command(char cmd) +{ + unsigned int volts; + volts = read_SupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + Write_Byte(0, lora_PacketSNR, lora_TXBUFF); //so that receiver alwsys knows last received SNR + Write_Byte(1, lora_PacketRSSI, lora_TXBUFF); //so that receiver alwsys knows last received RSSI + Write_UInt(2, volts, lora_TXBUFF); + Write_Byte(4, TRStatus, lora_TXBUFF); + digitalWrite(LED1, HIGH); + lora_Send(0, 4, cmd, Broadcast, ThisNode, 10, lora_Power, 0); + digitalWrite(LED1, LOW); +} + + +void display_current_frequency() +{ + float freq_temp = lora_GetFreq(); + Serial.print(F("Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void setup() +{ + unsigned long int i; + unsigned int j; + + pinMode(LED1, OUTPUT); //for PCB LED + pinMode(WDI, OUTPUT); //for Watchdog pulse input + + led_Flash(2, 500); + + Serial.begin(38400); //Setup Serial console ouput + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); +#endif + + Serial.println(F(programname)); + Serial.println(F(aurthorname)); + + pinMode(GPSPOWER, OUTPUT); //in case power switching components are fitted + GPS_On(DoGPSPowerSwitch); //this will power the GPSon + GPSonTime = millis(); + +#ifdef USING_SERIALGPS + GPSserial.end(); //but we dont want soft serial running for now, it interferes with the LoRa device +#endif + + pinMode(lora_NReset, OUTPUT); //LoRa device reset line + digitalWrite(lora_NReset, HIGH); + + pinMode (lora_NSS, OUTPUT); //set the slave select pin as an output: + digitalWrite(lora_NSS, HIGH); + + SPI.begin(); //initialize SPI + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + + +#ifdef ClearSavedData + do_ClearSavedData(); +#endif + + Serial.print(F("Default_Config1 ")); + Serial.println(Default_config1, BIN); + + j = Memory_ReadUInt(addr_ResetCount); + j++; + Memory_WriteUInt(addr_ResetCount, j); + Serial.print(F("Resets ")); + Serial.println(j); + Serial.print(F("Sequence ")); + i = Memory_ReadULong(addr_SequenceNum); + Serial.println(i); + +#ifdef DEBUG + printNodes(); +#endif + + lora_Setup(); + + if (!lora_CheckDevice()) + { + led_Flash(100, 50); //long medium speed flash for Lora device error + Serial.println(F("LoRa Error!")); + } + +#ifdef DEBUG + display_current_frequency(); +#endif + + Serial.print(F("Cal Offset ")); + Serial.println(CalibrationOffset); + +#ifdef DEBUG + lora_Print(); +#endif + + Serial.println(); + print_SupplyVoltage(); + print_Temperature(); + Serial.println(); + + j = read_SupplyVoltage(); //get supply mV + + Setup_LoRaTrackerMode(); + send_Command(PowerUp); //send power up command, includes supply mV and config, on tracker settings + sleepSecs(1); + + Setup_LoRaTrackerMode(); //so that check tone is at correct frequency + + GPS_Config_Error = false; //make sure GPS error flag is cleared + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); //GPS should have been on for a while by now, so this is just to start soft serial + GPSonTime = millis(); + GPS_Setup(); //GPS should have had plenty of time to initialise by now + +#ifdef UBLOX + if (!GPS_CheckNavigation()) //Check that UBLOX GPS is in Navigation model 6 + { + Serial.println(); + GPS_Config_Error = true; + setStatusByte(GPSError, 1); + setStatusByte(UBLOXDynamicModel6Set, 0); + } + else + { + setStatusByte(UBLOXDynamicModel6Set, 1); + } +#endif + + if (GPS_Config_Error) + { + Serial.println(F("GPS Error !")); + Serial.println(); + send_Command(NoGPS); //make sure receiver knows about GPS error + led_Flash(100, 25); //long very rapid flash for GPS error + } + else + { + +#ifdef CheckTone + digitalWrite(LED1, HIGH); + Serial.println(F("Check Tone")); //check tone indicates navigation model 6 set (if checktone enabled!) + lora_Tone(1000, 3000, 2); //Transmit an FM tone, 1000hz, 3000ms, 2dBm + digitalWrite(LED1, LOW); +#endif + } + + + setStatusByte(NoGPSTestMode, 0); + GPSonTime = millis(); + while (!gpsWaitFix(5, DontSwitch, LeaveOn)) //wait for the initial GPS fix, this could take a while, leave GPS powered on + { + + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + +#ifdef DEBUG + i = (millis() - GPSonTime) / 1000; + Serial.print(F("GPS OnTime ")); + Serial.print(i); + Serial.println(F(" Secs")); +#endif + } + +#endif + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled +#endif + + lora_Tone(500, 500, 2); //Transmit an FM tone, 500hz, 500ms, 2dBm + digitalWrite(LED1, LOW); + sleepSecs(2); //wait for GPS to shut down + +#ifdef DEBUGNoGPS + setStatusByte(NoGPSTestMode, 1); +#endif + +} + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_Bare_Bones_200518/LoRaTracker_HAB2_Settings.h b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_Bare_Bones_200518/LoRaTracker_HAB2_Settings.h new file mode 100644 index 0000000..e46b799 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_Bare_Bones_200518/LoRaTracker_HAB2_Settings.h @@ -0,0 +1,229 @@ +//LoRaTracker_HAB2_Settings.h +/* +****************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 20/05/2018 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To Do: + + Changes: + + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +#define External_VoltageRead + +#define External_TemperatureRead //assumes a TC74 is in use + +#define TC74_Address 0x4c //init with TC74 address, can be 0x48 to 0x4F depending on specific type + +const int Temperature_Adjust = 0; //to allow adjustment of external temperature sensor + +#define Board_Definition "HAB2_Board_Definitions.h" //define the board to use here + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + + +#define ConfigureDefaults //Configure settings from default program constants, save in memory and copy to RAM, need to do this once only +//#define ClearAllMemory //Clears from start memory to end memory, normally 1kbyte, needs to be followed by ConfigureDefaults + +const byte Output_len_max = 125; //maximum length for built payload +#define CheckTone //comment in to have a calibrate tone at startup, also indicates navigation model 6 set + +//#define DEBUG //if defined, prints additional debug information to terminal + + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 434400000; + +//Search mode +const unsigned long SearchMode_Frequency = 434300000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 0; + + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +//Tracker mode +#define TrackerMode_Bandwidth BW62500 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 +#define TrackerMode_Power 10 + +//Search mode +#define SearchMode_Bandwidth BW62500 +#define SearchMode_SpreadingFactor SF12 +#define SearchMode_CodeRate CR45 +#define SearchMode_Power 10 + +//#define LORADEBUG //displays extra debug messages when using LoRa + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 16; //RX mode is not used +const byte lora_TXBUFF_Size = 128; + +const byte delayforRelaysecs = 2; //allows time for relay to re-transmit + + + +//************************************************************************************************** +// 5) GPS Options +//************************************************************************************************** + +//#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +//#define GPS_Library "UBLOX_SerialGPS.h" //define the GPS library routines to use here +#define GPS_Library "UBLOX_I2CGPS2.h" + +//#define DEBUGNoGPS //test mode, does not use GPS +//#define Use_Test_Location //to use test location for transmissions include this define + +//#define GPS_ALLOW_GPGSV //define this so that GPGSV senetences are not turned off +//#define Checkfor_GNNS_Mode //define this if you want to check for GNNS sentences from GPS, not needed for latest TinyGPS++ + +#define GPSBaud 9600 //GPS Baud rate +#define WhenNoGPSFix LeaveOn //What to do with GPS power when there is no fix at ends of wait period (LeaveOn or LeaveOff) +const byte WaitGPSFixSeconds = 30; //in flight mode time to wait for a new GPS fix +//#define Remove_GPS_Power //Some tracker boards can remove the power from the GPS, if so define this to use it +#define Use_GPS_SoftwareBackup //some GPSs do not support this mode, Ubloxes do, used for GPS Hotfix option +//#define Check_GPS_Navigation_Model_OK //every time the GPS is checked for a fix we can ceck for correct navigation mode on UBLOX + +const unsigned long GPSShutdownTimemS = 1900; //Software backup mode takes around 1.9secs to power down, used in maHr calculation +const unsigned long fixisoldmS = 10000; //if location has not updated in this number of mS, assume GPS has lost fix +const unsigned long GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const unsigned int GPSFixs = 100; //number of GPS fixes between setting system clock from GPS +const byte GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const byte GPS_Reply_Size = 12; //size of GPS reply buffer +const unsigned int GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent + +//Centre of Cardiff Castle keep +#define TestLatitude 51.48230 +#define TestLongitude -3.18136 +#define TestAltitude 48 + + +/* + Passive GPS station: Swanbridge - C1ST1667 + https://www.ordnancesurvey.co.uk/gps/legacy-control-information/C1ST1667 + N 51 23'59.105955", W 3 11',47.413031 + 51.399751654166664, -3.196503619722222 + + #define TestLatitude 51.399752 + #define TestLongitude -3.196504 + #define TestAltitude 0 +*/ + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +#define Memory_Library "EEPROM_Memory.h" //define this file if the internal EEPROM is in use + +//************************************************************************************************** +// 8) FSK RTTY Settings +//************************************************************************************************** + +const unsigned int FSKRTTYbaudDelay = 9845; //delay for baud rate for FSK RTTY, 19800 for 50baud, 9845 for 100baud, 4865 for 200baud +const byte FSKRTTYRegshift = 6; //number of frequency steps to use for shift +const byte FSKRTTYpips = 5; //number of FSK lead in pips +const int FSKRTTYleadin = 500; //number of ms for FSK constant lead in tone +const byte sync_chars = 3; //number of extra $ sync characters to send + + +//************************************************************************************************** +// 9) AFSK RTTY Options +//************************************************************************************************** + +const byte delayforAFSKuploadSecs = 4; //allows time for AFSK upload on receiver + + +//**************************************************************************************************** +// 11) Program Default Option settings +// This section determines which options are on or off by default, this is the Default_config1 byte +// Take care here.......... +//************************************************************************************************** + +#define OptionOff 0 +#define OptionOn 1 + +const char option_SearchEnable = OptionOn; +const char option_TXEnable = OptionOn; +const char option_FSKRTTYEnable = OptionOn; +const char option_CheckFence = OptionOff; +const char option_ShortPayloadEnable = OptionOff; +const char option_RepeatEnable = OptionOff; +const char option_AddressStrip = OptionOn; +const char option_GPSHotFix = OptionOff; + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_TXEnable_SUM (option_TXEnable*2) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) +#define option_CheckFence_SUM (option_CheckFence*8) +#define option_ShortPayloadEnable_SUM (option_ShortPayloadEnable*16) +#define option_RepeatEnable_SUM (option_RepeatEnable*32) +#define option_AddressStrip_SUM (option_AddressStrip*64) +#define option_GPSHotFix_SUM (option_GPSHotFix*128) + +//See Program_Definitions.h in the LoRaTracker library for details, the above options translate into Default_config1 byte of 1 + 2 + 4 + 64 = 71 + +const unsigned int Default_config1 = (option_SearchEnable_SUM + option_TXEnable_SUM + option_FSKRTTYEnable_SUM + option_CheckFence_SUM + option_ShortPayloadEnable_SUM + option_RepeatEnable_SUM + option_AddressStrip_SUM + option_GPSHotFix_SUM); +const unsigned int Default_config2 = 0; +const unsigned int Default_config3 = 0; +const unsigned int Default_config4 = 0; +//const unsigned int Default_config1 = 71; //Phew, the default config can always be set manually ............. + + +//************************************************************************************************** +// 12) Miscellaneous program settings +//************************************************************************************************** + + + + + +//************************************************************************************************** +// 13) Unique calibration settings for each Board +// These settings are not part of a bind operation +//************************************************************************************************** + +const float kelvin_offset = 326; //if processor self read of temperature reports high, increase this number +const float temp_conversion_slope = 1.058 ; //defines the rate of change between low and high temperatures +const unsigned long adc_constant = 1146679; //if processor self read of its supply voltage reports high reduce this number + + +//************************************************************************************************** +// 14) HAB2 settings +//************************************************************************************************** + +char Flight_ID[15] = "MyFlight1"; + +const unsigned int Loop_Sleepsecs = 25; //sleep time in seconds after each TX loop + +const char ThisNode = '1'; + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_FSKRTTYONLY_101017/LoRaTracker_HAB2_FSKRTTYONLY_101017.ino b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_FSKRTTYONLY_101017/LoRaTracker_HAB2_FSKRTTYONLY_101017.ino new file mode 100644 index 0000000..5f262d5 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_FSKRTTYONLY_101017/LoRaTracker_HAB2_FSKRTTYONLY_101017.ino @@ -0,0 +1,986 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the HAB2_Settings file not here ! +// +//************************************************************************************************** + +#define programname "LoRaTracker_HAB2_FSKRTTYONLY_101017" +#define aurthorname "Stuart Robinson" + +#include +#include + +#include "LoRaTracker_HAB2_FSKRTTYONLY_Settings.h" +#include Board_Definition +#include "Program_Definitions.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + Location payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Sats,SupplyVolts,Temperature,Resets,Config0byte,StatusByte,RunmAhr,hertzoffset,GPSFixTime,Checksum + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + + To Do: + + Changes: + +************************************************************************************************** +*/ + +char ramc_RemoteControlNode; +char ramc_ThisNode; + +int ramc_CalibrationOffset; + +unsigned long ramc_TrackerMode_Frequency; //frequencies, and other parameters, are copied from memory into RAM. +byte ramc_TrackerMode_Power; +byte TRStatus = 0; //used to store current status flag bits + + +byte ramc_Current_TXconfig1; //sets the config of whats transmitted etc +byte stripvalue; +byte sats; //either sats in view from GPGSV or sats from NMEA fix sentence +int internal_temperature; + + +unsigned int ramc_Sleepsecs; //seconds for sleep at end of TX routine +unsigned int ramc_WaitGPSFixSeconds; //in flight mode, default time to wait for a fix +unsigned int ramc_FSKRTTYbaudDelay; //dealy used in FSKRTTY routine to give chosen baud rate + + +float Fence_Check_Lon; //used for fence check + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; + +byte ramc_FSKRTTYRegshift; +byte ramc_FSKRTTYpips; +unsigned int ramc_FSKRTTYleadin; +byte ramc_key0; +byte ramc_key1; +byte ramc_key2; +byte ramc_key3; +byte keypress; + +unsigned long GPSonTime; +unsigned long GPSFixTime; +boolean GPS_Config_Error; + + +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include //https://github.com/rocketscream/Low-Power + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object +TinyGPSCustom GNGGAFIXQ(gps, "GNGGA", 5); //custom sentences used to detect possible switch to GLONASS mode + +#ifdef USE_SOFTSERIAL_GPS +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPSserial(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial +#endif + +#include GPS_Library //include previously defined GPS Library + +#include "Voltage_Temperature.h" +#include "LoRa3.h" +#include "FSK_RTTY3.h" //this version of FSK_RTTY has inverted pips. +#include "Binary2.h" + + + +void loop() +{ + Serial.println(); + Serial.println(); + GPSFixTime = 0; + internal_temperature = (int) read_Temperature(); //read temp just after sleep, when CPU is closest to ambient + + GPSonTime = millis(); + gpsWaitFix(ramc_WaitGPSFixSeconds, SwitchOn, LeaveOn); + +#ifdef Use_Test_Location + TRLat = TestLatitude; + TRLon = TestLongitude; + TRAlt = TestAltitude; +#endif + + if (readConfigByte(CheckFence) && (!doFenceCheck())) //if fence check is enabled and tracker is outside fence + { + action_outside_fence(); + } + else //either fence check is disabled or tracker is within it + { + if (readConfigByte(TXEnable)) //is TX enabled ? + { + do_Transmissions(); //yes, so do transmissions + } + else + { + Serial.println(F("TX off")); + inside_fence_no_transmit(); //no, TX is disabled + } + } + + sleepSecs(ramc_Sleepsecs); //this sleep is used to set overall transmission cycle time + +} + + + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + byte index, Count; + + pulseWDI(); + lora_Setup(); //resets then sets up LoRa device + + Setup_LoRaTrackerMode(); + + incMemoryULong(addr_SequenceNum); //increment sequence number + Count = buildHABPacket(); + stripvalue = readConfigByte(AddressStrip); + + + if (readConfigByte(FSKRTTYEnable)) + { + + Serial.println(F("Send FSKRTTY")); + + lora_DirectSetup(); //set for direct mode + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + Start_FSKRTTY(FSKRTTYRegshift, FSKRTTYleadin, FSKRTTYpips); + + for (index = 1; index <= sync_chars; index++) + { + Send_FSKRTTY('$', FSKRTTYbaudDelay); + } + + for (index = 0; index <= Count; index++) + { + Send_FSKRTTY(lora_TXBUFF[index], FSKRTTYbaudDelay); + } + Send_FSKRTTY(13, FSKRTTYbaudDelay); //finish RTTY with carriage return + Send_FSKRTTY(10, FSKRTTYbaudDelay); //and line feed + digitalWrite(LED1, LOW); //make sure LED off + + #ifndef ConstantTX + lora_TXOFF(); //turns off transmit + #endif + + } +} + + +byte buildHABPacket() //expects a char buffer, so this routine will not work without the -permissive setting +{ + //build the long tracker payload + unsigned int index, j, CRC, resets, runmAhr; + int volts; + byte Count,len; + char LatArray[12], LonArray[12]; + + //unsigned long fixtime; + unsigned long sequence; + + sequence = Memory_ReadULong(addr_SequenceNum); //sequence number is kept in non-volatile memory so it survives resets + resets = Memory_ReadUInt(addr_ResetCount); //reset count is kept in non-volatile memory so it survives resets + + Serial.print("Resets "); + Serial.println(resets); + Serial.print("Temperature "); + Serial.println(internal_temperature); + + runmAhr = 0; + + volts = read_SupplyVoltage(); + + if (!readConfigByte(GPSHotFix)) + { + GPSFixTime = 0; //if GPS power save is off (no GPSHotFix), ensure GPS fix time is set to zero + Serial.println("GPSFixTime set to 0"); + } + + sats = gps.satellites.value(); + dtostrf(TRLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TRLon, 7, 5, LonArray); //converts float to character array + len = sizeof(lora_TXBUFF); + memset(lora_TXBUFF, 0, len); //clear array to 0s + + Count = snprintf((char*) lora_TXBUFF, + Output_len_max, + "$$$$%s,%lu,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%lu", + Flight_ID, + sequence, + gps.time.hour(), + gps.time.minute(), + gps.time.second(), + LatArray, + LonArray, + TRAlt, + sats, + volts, + internal_temperature, + resets, + ramc_Current_TXconfig1, + TRStatus, + runmAhr, + ramc_CalibrationOffset, + GPSFixTime + ); + + //Count = strlen(lora_TXBUFF); //how long is the array ? + + CRC = 0xffff; //start value for CRC16 + + for (index = 4; index < Count; index++) //element 4 is first character after $$ at start + { + CRC ^= (((unsigned int)lora_TXBUFF[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + lora_TXBUFF[Count++] = '*'; + lora_TXBUFF[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + lora_TXBUFF[Count++] = Hex((CRC >> 8) & 15); + lora_TXBUFF[Count++] = Hex((CRC >> 4) & 15); + lora_TXBUFF[Count] = Hex(CRC & 15); + return Count; +} + + +char Hex(byte lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + +void inside_fence_no_transmit() +{ +//null nothing to do +} + + +void action_outside_fence() +{ + sleepSecs(outside_fence_Sleep_seconds); //goto sleep for a long time + +} + + +byte doFenceCheck() //checks to see if GPS location is within an Western and Eastern limit +{ + //there has been a fix, so check fence limits + Fence_Check_Lon = gps.location.lng(); + +#ifdef DEBUGNoGPS + Fence_Check_Lon = TestLongitude; +#endif + +#ifdef DEBUG + Serial.print(Fence_Check_Lon, 6); + Serial.print(F(" ")); +#endif + + if ((Fence_Check_Lon > west_fence) && (Fence_Check_Lon < east_fence)) //approximate to the limits for region 1 ISM band + { + Serial.println(F("Inside Fence")); + return 1; //within the fence + } + else + { + Serial.println(F("Outside Fence")); + return 0; + } + //outside the fence +} + + +void printPayload(byte lCount) +{ + byte index; + for (index = 0; index <= lCount; index++) + { + Serial.write(lora_TXBUFF[index]); + } +} + + + +void printMemoryFrequencies() +{ + //a useful check to see if memory is configured correctly + unsigned long tempULong; + tempULong = Memory_ReadULong(addr_TrackerMode_Frequency); + Serial.print(F("Memory Tracker Frequency ")); + Serial.println(tempULong); + +} + + +void printRAMFrequencies() +{ + Serial.print(F("RAM Tracker Frequency ")); + Serial.println(ramc_TrackerMode_Frequency); + + Serial.print(F("RAM Calibration Offset ")); + Serial.println(ramc_CalibrationOffset); +} + + + +void sleepSecs(unsigned int LNumberSleeps) +{ + unsigned int i; + + Serial.print(F("zz ")); + Serial.println(LNumberSleeps); + Serial.flush(); //let print complete + + #ifdef USING_SERIALGPS + GPSserial.end(); //we dont want GPS input interfering with sleep + #endif + + digitalWrite(lora_NSS, HIGH); //ensure LoRa Device is off + + for (i = 1; i <= LNumberSleeps; i++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep 1 second + pulseWDI(); + } + +} + + +void incMemoryULong(unsigned int laddress) +{ + unsigned long val; + val = Memory_ReadULong(laddress); + val++; + Memory_WriteULong(laddress, val); +} + + +byte readConfigByte(byte bitnum) +{ + return bitRead(ramc_Current_TXconfig1, bitnum); +} + + + +void setStatusByte(byte bitnum, byte bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } + +#ifdef DEBUG + if (bitval) + { + Serial.print(F("Set Status Bit ")); + } + else + { + Serial.print(F("Clear Status Bit ")); + } + + Serial.println(bitnum); +#endif +} + + +void pulseWDI() +{ + //if the watchdog is fitted it needs a regular pulse top prevent reset + //togle the WDI pin twice + digitalWrite(WDI, !digitalRead(WDI)); + delayMicroseconds(1); + digitalWrite(WDI, !digitalRead(WDI)); +} + + +boolean gpsWaitFix(unsigned long waitSecs, byte StartState, byte LeaveState) +{ + //waits a specified number of seconds for a fix, returns true for good fix + //StartState when set to 1 will turn GPS on at routine start + //LeaveState when set to 0 will turn GPS off at routine end, used perhaps when there is no fix + + unsigned long endwaitmS, millistowait, currentmillis; + pulseWDI(); + byte GPSByte; + + + if (StartState == 1) + { + GPS_On(DoGPSPowerSwitch); + GPSonTime = millis(); + } + else + { + GPS_On(NoGPSPowerSwitch); + } + + #ifdef Check_GPS_Navigation_Model_OK + Serial.println(F("Checking Navigation Model")); + if (!GPS_CheckNavigation()) + { + //something wrong with GPS, navigation mode not set so reconfigure the GPS + Serial.println(F("GPS Configuration Error !!!!")); + GPS_Setup(); + } + #endif + + + Serial.print(F("Wait Fix ")); + Serial.print(waitSecs); + Serial.println(F(" Secs")); + + currentmillis = millis(); + millistowait = waitSecs * 1000; + endwaitmS = currentmillis + millistowait; + + while (millis() < endwaitmS) + { + + do + { + GPSByte = GPS_GetByte(); + if (GPSByte != 0xFF) + { + gps.encode(GPSByte); + } + } + while (GPSByte != 0xFF); + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + Serial.println(F("GPS Fix")); + TRLat = gps.location.lat(); + TRLon = gps.location.lng(); + TRAlt = (unsigned int) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TRAlt > 60000) + { + TRAlt = 0; + } + + if (readConfigByte(GPSHotFix)) + { + GPS_Off(DoGPSPowerSwitch); + GPSFixTime = (millis() - GPSonTime); + Serial.print(F("GPS Fix Time ")); + Serial.print(GPSFixTime); + Serial.println(F("mS")); + } + else + { + GPS_Off(NoGPSPowerSwitch); + } + + setStatusByte(GPSFix, 1); + pulseWDI(); + return true; + } + +#ifdef UBLOX + if (GNGGAFIXQ.age() < 2000) //check to see if GLONASS has gone active + { + Serial.println(F("GLONASS !")); + setStatusByte(GLONASSisoutput, 1); + GPS_SetGPMode(); + //GPS_SetCyclicMode(); + sleepSecs(1); + } + else + { + setStatusByte(GLONASSisoutput, 0); //GLONASS not detected + } +#endif + + + + } + + //if here then there has been no fix and a timeout + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(F("No Fix")); + + if (LeaveState == 0) + { + //no fix and gpsWaitFix called with gpspower to be turned off on exit + GPS_Off(DoGPSPowerSwitch); + } + else + { + //no fix but gpsWaitFix called with gpspower to be left on at exit + GPS_Off(NoGPSPowerSwitch); + } + + pulseWDI(); + return false; +} + + +void readSettingsDefaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Config Defaults")); + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_TrackerMode_Power = TrackerMode_Power; + + ramc_ThisNode = ThisNode; + + ramc_Current_TXconfig1 = Default_config1; + ramc_WaitGPSFixSeconds = WaitGPSFixSeconds; + ramc_Sleepsecs = Loop_Sleepsecs; + + ramc_FSKRTTYbaudDelay = FSKRTTYbaudDelay; + ramc_FSKRTTYRegshift = FSKRTTYRegshift; + ramc_FSKRTTYpips = FSKRTTYpips; + ramc_FSKRTTYleadin = FSKRTTYleadin; + + ramc_CalibrationOffset = CalibrationOffset; +} + + +void readSettingsMemory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Config from Memory")); + + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + + ramc_ThisNode = Memory_ReadByte(addr_ThisNode);; + + ramc_Current_TXconfig1 = Memory_ReadByte(addr_Default_config1); + ramc_WaitGPSFixSeconds = Memory_ReadUInt(addr_WaitGPSFixSeconds); + ramc_Sleepsecs = Memory_ReadUInt(addr_Sleepsecs); + + ramc_FSKRTTYbaudDelay = Memory_ReadUInt(addr_FSKRTTYbaudDelay); + ramc_FSKRTTYRegshift = Memory_ReadByte(addr_FSKRTTYRegshift); + ramc_FSKRTTYpips = Memory_ReadByte(addr_FSKRTTYpips); + ramc_FSKRTTYleadin = Memory_ReadUInt(addr_FSKRTTYleadin); + ramc_key0 = Memory_ReadByte(addr_key0); + ramc_key1 = Memory_ReadByte(addr_key1); + ramc_key2 = Memory_ReadByte(addr_key2); + ramc_key3 = Memory_ReadByte(addr_key3); + + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + + readIDMemory(); +} + + +void writeSettingsMemory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this program uses constants in RAM copied from Memory (EEPROM or FRAM) + + Serial.println(F("Writing RAM Settings to Memory")); + + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //fill config area with 0 + writeIDMemory(); + + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + + Memory_WriteByte(addr_ThisNode, ramc_ThisNode); + + Memory_WriteByte(addr_Default_config1, ramc_Current_TXconfig1); + Memory_WriteUInt(addr_WaitGPSFixSeconds, ramc_WaitGPSFixSeconds); + Memory_WriteUInt(addr_Sleepsecs, ramc_Sleepsecs); + + Memory_WriteUInt(addr_FSKRTTYbaudDelay, ramc_FSKRTTYbaudDelay); + Memory_WriteByte(addr_FSKRTTYRegshift, ramc_FSKRTTYRegshift); + Memory_WriteByte(addr_FSKRTTYpips, ramc_FSKRTTYpips); + Memory_WriteUInt(addr_FSKRTTYleadin, ramc_FSKRTTYleadin); + Memory_WriteByte(addr_key0, ramc_key0); + Memory_WriteByte(addr_key1, ramc_key1); + Memory_WriteByte(addr_key2, ramc_key2); + Memory_WriteByte(addr_key3, ramc_key3); + + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); +} + + +void writeIDMemory() +{ + unsigned int i, addr; + byte j; + j = sizeof(Flight_ID); + j--; + addr = addr_FlightID; + for (i = 0; i <= j; i++) + { + Memory_WriteByte(addr, Flight_ID[i]); + addr++; + } +} + +void readIDMemory() +{ + unsigned int addr; + byte i; + byte j = 0; + + addr = addr_FlightID; + do + { + i = Memory_ReadByte(addr); + Flight_ID[j++] = i; + addr++; + } + while (i != 0) ; +} + + +void printNodes() +{ + Serial.print(F("ThisNode ")); + Serial.print(ramc_ThisNode); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_Power = ramc_TrackerMode_Power; +} + + +void display_current_frequency() +{ + float freq_temp; + freq_temp = lora_GetFreq(); + Serial.print(F("Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + +void do_ClearSavedData() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear Saved Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.println(F("Clear All Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void Print_Config_Memory() +{ + //prints the memory used for storing configuration settings + byte memory_LLoopv1; + byte memory_LLoopv2; + unsigned int memory_Laddr = 0; + byte memory_Ldata; + //unsigned int CRC; + Serial.println(F("Config Memory")); + Serial.print(F("Lcn 0 1 2 3 4 5 6 7 8 9 A B C D E F")); + Serial.println(); + + for (memory_LLoopv1 = 0; memory_LLoopv1 <= 15; memory_LLoopv1++) + { + Serial.print(F("0x")); + Serial.print(memory_LLoopv1, HEX); //print the register number + Serial.print(F("0 ")); + for (memory_LLoopv2 = 0; memory_LLoopv2 <= 15; memory_LLoopv2++) + { + memory_Ldata = Memory_ReadByte(memory_Laddr); + if (memory_Ldata < 0x10) { + Serial.print(F("0")); + } + Serial.print(memory_Ldata, HEX); //print the register number + Serial.print(F(" ")); + memory_Laddr++; + } + Serial.println(); + } +} + + +void Print_CRC_Config_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartConfigData, addr_EndConfigData); + Serial.print(F("CRC Config ")); + Serial.println(returnedCRC, HEX); +} + + +unsigned int Print_CRC_Bind_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("Local Bind CRC ")); + Serial.println(returnedCRC, HEX); + return returnedCRC; +} + + + +//******************************************************************************************************* + + +void setup() +{ + unsigned long int i; + unsigned int j; + + pinMode(LED1, OUTPUT); //for PCB LED + pinMode(WDI, OUTPUT); //for Watchdog pulse input + + led_Flash(2, 500); + + Serial.begin(38400); //Setup Serial console ouput + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); +#endif + + + Serial.println(F(programname)); + Serial.println(F(aurthorname)); + + pinMode(GPSPOWER, OUTPUT); //in case power switching components are fitted + GPS_On(DoGPSPowerSwitch); //this will power the GPSon + GPSonTime = millis(); + +#ifdef USING_SERIALGPS + GPSserial.end(); //but we dont want soft serial running for now, it interferes with the LoRa device +#endif + + pinMode(lora_NReset, OUTPUT); //LoRa device reset line + digitalWrite(lora_NReset, HIGH); + + pinMode (lora_NSS, OUTPUT); //set the slave select pin as an output: + digitalWrite(lora_NSS, HIGH); + + SPI.begin(); //initialize SPI + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + + +#ifdef ClearSavedData + do_ClearSavedData(); +#endif + + Serial.print(F("Config1 ")); + Serial.println(Default_config1, BIN); + + j = Memory_ReadUInt(addr_ResetCount); + j++; + Memory_WriteUInt(addr_ResetCount, j); + Serial.print(F("Resets ")); + Serial.println(j); + Serial.print(F("Sequence ")); + i = Memory_ReadULong(addr_SequenceNum); + Serial.println(i); + + +#ifdef ConfigureDefaults + readSettingsDefaults(); + writeSettingsMemory(); +#endif + + +#ifdef ConfigureFromMemory + readSettingsMemory(); +#endif + + Print_CRC_Config_Memory(); + + ramc_ThisNode = ThisNode; + +#ifdef DEBUG + printNodes(); +#endif + + lora_Setup(); + + if (!lora_CheckDevice()) + { + led_Flash(100, 50); //long medium speed flash for Lora device error + Serial.println(F("LoRa Error!")); + } + +#ifdef DEBUG + display_current_frequency(); +#endif + + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); //get calibration offset for this tracker + Serial.print(F("Cal Offset ")); + Serial.println(ramc_CalibrationOffset); + +#ifdef DEBUG + lora_Print(); +#endif + + Serial.println(); + print_SupplyVoltage(); + print_Temperature(); + Serial.println(); + + j = read_SupplyVoltage(); //get supply mV + Write_Int(0, j, lora_TXBUFF); //write to first two bytes of buffer + Write_Byte(2, ramc_Current_TXconfig1, lora_TXBUFF); //add the current config byte + + Setup_LoRaTrackerMode(); + sleepSecs(1); + + Setup_LoRaTrackerMode(); //so that check tone is at correct frequency + + GPS_Config_Error = false; //make sure GPS error flag is cleared + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); //GPS should have been on for a while by now, so this is just to start soft serial + GPSonTime = millis(); + GPS_Setup(); //GPS should have had plenty of time to initialise by now + +#ifdef UBLOX + if (!GPS_CheckNavigation()) //Check that UBLOX GPS is in Navigation model 6 + { + Serial.println(); + GPS_Config_Error = true; + setStatusByte(GPSError, 1); + setStatusByte(UBLOXDynamicModel6Set, 0); + } + else + { + setStatusByte(UBLOXDynamicModel6Set, 1); + } +#endif + + if (GPS_Config_Error) + { + Serial.println(F("Warning GPS Error !")); + Serial.println(); + led_Flash(100, 25); //long very rapid flash for GPS error + } + else + { +#ifdef CheckTone + if (readConfigByte(TXEnable)) //is TX enabled - needed because of fence limits + { + Serial.println(F("Check Tone")); //check tone indicates navigation model 6 set (if checktone enabled!) + lora_Tone(1000, 3000, 5); //Transmit an FM tone, 1000hz, 3000ms, 5dBm + } +#endif + } + + digitalWrite(LED1, HIGH); + setStatusByte(NoGPSTestMode, 0); + GPSonTime = millis(); + while (!gpsWaitFix(5, DontSwitch, LeaveOn)) //while there is no fix + { + + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + +#ifdef DEBUG + i = (millis() - GPSonTime) / 1000; + Serial.print(F("GPS On Time ")); + Serial.print(i); + Serial.println(F(" Secs")); +#endif + } + +#endif + +#ifndef DEBUGNoGPS + GPS_On(DoGPSPowerSwitch); + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled +#endif + + + lora_Tone(500, 500, 2); //Transmit an FM tone, 500hz, 500ms, 2dBm + digitalWrite(LED1, LOW); + sleepSecs(2); //wait for GPS to shut down + +#ifdef DEBUGNoGPS + setStatusByte(NoGPSTestMode, 1); +#endif + +} + + + + + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_FSKRTTYONLY_101017/LoRaTracker_HAB2_FSKRTTYONLY_Settings.h b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_FSKRTTYONLY_101017/LoRaTracker_HAB2_FSKRTTYONLY_Settings.h new file mode 100644 index 0000000..f0d78fc --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRaTracker_HAB2_FSKRTTYONLY_101017/LoRaTracker_HAB2_FSKRTTYONLY_Settings.h @@ -0,0 +1,207 @@ +//LoRaTracker_HAB2_FSKRTTYONLY_Settings.h +/* +****************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 10/10/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To Do: + + Changes: + 101017 Removed unused board definitions + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +#define CPU_VoltageRead +//#define External_VoltageRead + +#define CPU_TemperatureRead +//#define External_TemperatureRead +const int Temperature_Adjust = 0; //to allow calibration of external temperature sensor + +#define Board_Definition "HAB2_Board_Definitions.h" //define the board to use here + + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + + +#define ConfigureDefaults //Configure settings from default program constants, save in memory and copy to RAM, need to do this once only +//#define ClearAllMemory //Clears from start memory to end memory, normally 1kbyte, needs to be folloowed by ConfigureDefaults +//#define ClearSavedData //zero the saved data, resets, sequence, Mahr +//#define ConfigureFromMemory //Read settings from attached memory + +const byte Output_len_max = 125; //maximum length for built payload +#define CheckTone //comment in to have a calibrate tone at startup, also indicates navigation model 6 set + +//#define DEBUG /if defined, prints additional debug information to terminal + + + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 434400000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 0; + + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +//Tracker mode +#define TrackerMode_Power 10 + +//#define LORADEBUG //displays extra debug messages when using LoRa + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 1; //RX buffer not in use, so set to 1 +const byte lora_TXBUFF_Size = 128; + + +//************************************************************************************************** +// 5) GPS Options +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +#define GPS_Library "UBLOX_SerialGPS.h" //define the GPS library routines to use here +//#define GPS_Library "UBLOX_I2CGPS.h" + +//#define DEBUGNoGPS //test mode, does not use GPS + +#define GPSBaud 9600 //GPS Baud rate +#define WhenNoGPSFix LeaveOn //What to do with GPS power when there is no fix at ends of wait period (LeaveOn or LeaveOff) +#define WaitGPSFixSeconds 30 //in flight mode time to wait for a new GPS fix +//#define Check_GPS_Navigation_Model_OK //every time the GPS is checked for a fix we can check for correct navigation mode on UBLOX + +const unsigned long fixisoldmS = 10000; //if location has not updated in this number of mS, assume GPS has lost fix +const unsigned long GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const unsigned int GPSFixs = 100; //number of GPS fixes between setting system clock from GPS +const byte GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const byte GPS_Reply_Size = 12; //size of GPS reply buffer + + +//#define Use_Test_Location //to use test location for transmissions include this define + +//Centre of Cardiff Castle keep +#define TestLatitude 51.48230 +#define TestLongitude -3.18136 +#define TestAltitude 48 + + +/* + Passive GPS station: Swanbridge - C1ST1667 + https://www.ordnancesurvey.co.uk/gps/legacy-control-information/C1ST1667 + N 51 23'59.105955", W 3 11',47.413031 + 51.399751654166664, -3.196503619722222 + + #define TestLatitude 51.399752 + #define TestLongitude -3.196504 + #define TestAltitude 0 +*/ + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +#define Memory_Library "EEPROM_Memory.h" + + +//************************************************************************************************** +// 8) FSK RTTY Settings +//************************************************************************************************** + +#define ConstantTX //define thid to leave TX running permanently +const unsigned int FSKRTTYbaudDelay = 9845; //delay for baud rate for FSK RTTY, 19800 for 50baud, 9845 for 100baud, 4865 for 200baud +const byte FSKRTTYRegshift = 6; //number of frequency steps to use for shift +const byte FSKRTTYpips = 5; //number of FSK lead in pips +const int FSKRTTYleadin = 500; //number of ms for FSK constant lead in tone +const byte sync_chars = 3; //number of extra $ sync characters to send + + +//**************************************************************************************************** +// 11) Program Default Option settings +// This section determins which options are on or off by default, this is the default_config1 byte +// Take care here.......... +//************************************************************************************************** + +#define OptionOff 0 +#define OptionOn 1 + +const char option_SearchEnable = OptionOn; +const char option_TXEnable = OptionOn; +const char option_FSKRTTYEnable = OptionOn; +const char option_CheckFence = OptionOff; +const char option_ShortPayloadEnable = OptionOff; +const char option_RepeatEnable = OptionOff; +const char option_AddressStrip = OptionOn; +const char option_GPSHotFix = OptionOff; + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_TXEnable_SUM (option_TXEnable*2) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) +#define option_CheckFence_SUM (option_CheckFence*8) +#define option_ShortPayloadEnable_SUM (option_ShortPayloadEnable*16) +#define option_RepeatEnable_SUM (option_RepeatEnable*32) +#define option_AddressStrip_SUM (option_AddressStrip*64) +#define option_GPSHotFix_SUM (option_GPSHotFix*128) + +//See Program_Definitions.h in the LoRaTracker library for details, the above options translate into Default_config1 byte of 1 + 2 + 4 + 64 = 71 + +const unsigned int Default_config1 = (option_SearchEnable_SUM + option_TXEnable_SUM + option_FSKRTTYEnable_SUM + option_CheckFence_SUM + option_ShortPayloadEnable_SUM + option_RepeatEnable_SUM + option_AddressStrip_SUM + option_GPSHotFix_SUM); +const unsigned int Default_config2 = 0; +const unsigned int Default_config3 = 0; +const unsigned int Default_config4 = 0; +//const unsigned int const_Default_config = 71; //Phew, the default config can always be set manually ............. + + +//************************************************************************************************** +// 13) Unique calibration settings for each Board +// These settings are not part of a bind operation +//************************************************************************************************** + +const float kelvin_offset = 326; //if processor self read of temperature reports high, increase this number +const float temp_conversion_slope = 1.058 ; //defines the rate of change between low and high temperatures +const unsigned long adc_constant = 1146679; //if processor self read of its supply voltage reports high reduce this number + + +//************************************************************************************************** +// 14) HAB2 settings +//************************************************************************************************** + +char Flight_ID[15] = "LoRaHAB2"; + +const float west_fence = -4; +const float east_fence = 45; + +const unsigned int Loop_Sleepsecs = 25; //sleep time in seconds after each TX loop +const unsigned int outside_fence_Sleep_seconds = 600; //approx 10 minutes + +#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +#define ThisNode ControlledNode + +const byte PayloadArraySize = 20; //Maximum number of fields when parsing long HAB payload + + + diff --git a/LoRa/LoRaTracker/HAB2/Programs/LoRa_Module_Test/LoRa_Module_Test.ino b/LoRa/LoRaTracker/HAB2/Programs/LoRa_Module_Test/LoRa_Module_Test.ino new file mode 100644 index 0000000..0d1bb64 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/LoRa_Module_Test/LoRa_Module_Test.ino @@ -0,0 +1,182 @@ +#define programname "LoRa_Module_Test" +#define programversion "V1.0" +#define dateproduced "26/11/2017" +#define aurthorname "Stuart Robinson" +#include +#include "Program_Definitions.h" //part of LoRaTracker library +#define LoRa_Device_in_MB1 //required if board is using Mikrobus sockets + +/* +***************************************************************************************************************************** +LoRaTracker Test Programs + +Copyright of the author Stuart Robinson - 26/11/2017 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission +of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and +free from errors. +***************************************************************************************************************************** +*/ + +/* +******************************************************************************************************************************** +Program operation + +This test program has been written to check that a connected LoRa module such as Dorji DRF127x or Hope RFM9x that it is funtional. +The LoRa device should transmit an FM audio tones at the frequency specified that can be heard on a UHF handheld FM receiver. +It might seem peverse to test a LoRa device by sending FM audio tones, but its the easiest way of checking that the LoRa device +is actually transmitting. + +A program start (power on and reset) there will be a short sequence of 5 LED flashes, then the LED should be constant on for around +2.5 seconds. At this time the LoRa device should be sending an FM tone on the defined frequency. The register contents of the LoRa +device will also be printed to the Arduino IDE serial monitor. A error detecting the LoRa device will result in a series of very +fast LED flashes lasting around 5 seconds. The test sequence will repeat. + +Do not forget to fit an antenna to the LoRa device, you can destroy it if you use it without and antenna +******************************************************************************************************************************** +*/ + +/* +******************************************************************************************************************************** +Connections + +The program uses the hardware SPI interface on the Arduino to connect to the LoRa device, so the SPI SCK, MOSI and MISO pins are +assumed to be connected. The test program needs a minimum of one extra pin connected to act as chip select. Other pins +may optionally be connected to the reset pin on the LoRa device and to DIO2 so that the LoRa device can transmit FM tones. +You can explicitly define the required pins below by removing the two // characters in front of the #defines +******************************************************************************************************************************** +*/ + +//#define lora_NSS 10 //Arduino pin number for device select on LoRa device +//#define lora_NReset 9 //Arduino pin number for reset pin on LoRa device, can be left not connected +//#define lora_TonePin 7 //Arduino pin number connceted to DIO2 pin on LoRa device, used for FM audio tone generation +//#define lora_DIO0 2 //Arduino pin number connceted to DIO0 pin on LoRa device, can be left not connected +//#define LED1 8 //Arduino pin number for LED, when high LED should be on. + +/* +*********************************************************************************************************************************************** +As an alternative to explicitly defining the Arduino pins required, there are pre-defined board definition files for the LoRaTracker boards +included in the LoRaTracker Library; + +https://github.com/LoRaTracker/LoRaTracker-Library + +Select (include) the board definition file you require by removing the // characters before the appropriate include line in the list below +*********************************************************************************************************************************************** +*/ + +#include "HAB2_Board_Definitions.h" +//#include "Locator2_Board_Definitions.h" +//#include "LCD_Receiver_Board_Definitions.h" +//#include "Relay1_Board_Definitions.h" +//#include "Receiver2_Board_Definitions.h" +//#include "Sensor1_Board_Definitions.h" +//#include "MicroRX_Board_Definitions.h" +//#include "PIHTracker2_Board_Definitions.h" +//#include "PIHTracker3_Board_Definitions.h" +//#include "RFM98_Shield_January2016_Board_Definitions.h" +//#include "MarkTwo_Board_Definitions.h" +//#include "MicroBit_Board_Definitions.h" + +#include + +const unsigned long Frequency = 434400000; //frequency of transmissions in hertz +const int CalibrationOffset = 0; //you can use this to adjust the output, in hertz, steps are 61hz +const byte Deviation = 0x52; //typical deviation for audio tones, approx 5khz + +const byte lora_RXBUFF_Size = 32; //needed for LoRa3 library +const byte lora_TXBUFF_Size = 64; //needed for LoRa3 library +byte keypress; //needed for LoRa3 library + +#include "LoRa4.h" //part of LoRaTracker library + +#define Serial_Monitor_Baud 38400 //this is baud rate used for the Arduino IDE Serial Monitor + +void loop() +{ + + Serial.println(F("LED Flash")); + Serial.println(); + led_Flash(5,100); + + SPI.begin(); + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + + Serial.println(F("Checking LoRa Device")); + Serial.println(); + Serial.print(F("Registers after reset - ")); + lora_ResetDev(); //ensure registers are in initial state + lora_Print(); //initial print of registers + + Serial.println(); + + if (lora_CheckDevice() == true) + { + Serial.println(F("Device Present")); + Serial.println(); + Serial.print(F("Registers after setup - ")); + lora_Setup(); //Do the initial LoRa Setup + lora_Print(); + lora_SetFreq(Frequency, CalibrationOffset); + Serial.print(F("Transmit FM Tone")); + digitalWrite(LED1, HIGH); + lora_Tone(1000, 3500, 2); //Transmit an FM tone, 1000hz, 2500ms, 2dBm + digitalWrite(LED1, LOW); + Serial.println(F(" - Done")); + Serial.println(); + lora_Print(); + } + else + { + Serial.println(F("Device Not Found")); + Serial.println(); + lora_Print(); + Serial.println(); + led_Flash(100,25); + } + + SPI.end(); + Serial.println(); + Serial.println(); + delay(1500); +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + + +void setup() +{ + pinMode(LED1, OUTPUT); //for PCB LED + pinMode(13, OUTPUT); //for Pro Mini LED, Pin13 + pinMode(lora_NReset, OUTPUT); //LoRa Device reset line + pinMode (lora_NSS, OUTPUT); //LoRa Device select line + digitalWrite(lora_NSS, HIGH); + digitalWrite(lora_NReset, HIGH); + + Serial.begin(Serial_Monitor_Baud); //setup Serial console ouput + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + Serial.println(); + +} diff --git a/LoRa/LoRaTracker/HAB2/Programs/README.md b/LoRa/LoRaTracker/HAB2/Programs/README.md new file mode 100644 index 0000000..e467280 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/README.md @@ -0,0 +1,36 @@ +This folder contains the current version of the LoRaTracker HAB2 programs. + +The programs requre the installation of the current LoRaTracker Library files see here; + +https://github.com/LoRaTracker/LoRaTracker-Library + +The programs in here are; + +LoRaTracker_HAB2_xxxxxx - The HAB tracker transmitter, supports two way LoRa control and tracking + +FSKRTTY_HAB2_FSKRTTYONLY_xxxxxx - A FSK RTTY only version of the HAB tracker + +HAB2_UBLOX_EchoGPS_I2C - A test program for the UBLOX GPS in I2C mode, checks that Navigation model 6 can be set + +HAB2_UBLOX_EchoGPS_Serial - A test program for the UBLOX GPS in serial mode, checks that Navigation model 6 can be set + +I2C_Scanner - a basic I2C scanner, reports any I2C devices found + +Various third party Libraries may need to be installed, if not already present in your installation; + +Flash-5 Library - https://github.com/mikalhart/Flash/releases +LowPower - https://github.com/rocketscream/Low-Power +TinyGPS++ - http://arduiniana.org/libraries/tinygpsplus/ +NeoSWSerial - https://github.com/SlashDevin/NeoSWSerial + +There is an issue with the Flash-5 library, changes to the Arduino IDE since the Library was published in 2014 +cause a compile error which is reported as ‘prog_char’ does not name a type. The solution to this is to edit the +Flash.h file in the Flash-5 Library. Add the following lines in Flash.h, just after the #include +i.e. around line 30 + +#if ARDUINO >= 150 +typedef char prog_char __attribute__((__progmem__)); +#endif + +If you have any problems with the programs do check that you are using the latest revision of the programs, the date +is included as part of the program name. \ No newline at end of file diff --git a/LoRa/LoRaTracker/HAB2/Programs/TC74_Temperature_Sensor_Test/TC74_Temperature_Sensor_Test.ino b/LoRa/LoRaTracker/HAB2/Programs/TC74_Temperature_Sensor_Test/TC74_Temperature_Sensor_Test.ino new file mode 100644 index 0000000..7502547 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/Programs/TC74_Temperature_Sensor_Test/TC74_Temperature_Sensor_Test.ino @@ -0,0 +1,81 @@ +//TC74_Test.ino +/* +******************************************************************************************************************************** + +Easy Build LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson - 22/11/2017 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission +of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and +free from errors. + +This program reads the temperature from a TC74 sensor. + +******************************************************************************************************************************** +*/ + + + +#include +#include //https://github.com/Mario-H/TC74_I2C/blob/master/LICENSE.md + +#include "HAB2_Board_Definitions.h" + + + +TC74_I2C TC74(0x4c); //init with TC74 address, can be 0x48 to 0x4F depending on specific type + +int temperature = 0; + +#define TC74powersave 0 //set to 1 for TC74 powersave mode + + + +void loop() { + + if (TC74powersave) + { + TC74.NoPowersave(); //turn off powesave mode + Serial.println("TC74 powersave off"); + } + + temperature = TC74.ReadTemp(); + + Serial.print ("Temperature = "); + if (temperature != 128) + { + Serial.print(temperature); + Serial.println("C"); + } + else + { + Serial.println(" TC74 Error"); //value of 128 degrees is an error + } + + if (TC74powersave) + { + TC74.Powersave(); //put TC74 in low current mode, approx 5uA + Serial.println("TC74 powersave on"); + } + + delay(3000); +} + + + +void setup() { + Serial.begin(38400); + Serial.println("Starting TC74 Temperature Sensor Test"); + Serial.println(); + pinMode(GPSPOWER, OUTPUT); //in case power switching components for GPS breakout are fitted + digitalWrite(GPSPOWER, LOW); + + TC74.Init(); +} diff --git a/LoRa/LoRaTracker/HAB2/Programs/Using the LoRaTracker Programs.doc b/LoRa/LoRaTracker/HAB2/Programs/Using the LoRaTracker Programs.doc new file mode 100644 index 0000000..03aa332 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Programs/Using the LoRaTracker Programs.doc differ diff --git a/LoRa/LoRaTracker/HAB2/README.md b/LoRa/LoRaTracker/HAB2/README.md new file mode 100644 index 0000000..4689103 --- /dev/null +++ b/LoRa/LoRaTracker/HAB2/README.md @@ -0,0 +1,30 @@ +The Programs for the HAB2 tracker need the LoRaTracker Library installed see here; + +https://github.com/LoRaTracker/LoRaTracker-Library + +The HAB2 tracker board is a minimal component count high altitude balloon tracker. + +The components required to build the tracker are described in the 'HAB2 Minimum Parts Tracker Build.pdf' file +that will be found in the \Build folder. + +The programs have been tested against version 1.8.5 of the Arduino IDE. Note that this +version of the IDE has the -permissive attribute set for the compiler, this allows the +complier to tolerate some functions that previous versions (that did not have the -permissive +attribute set as default) could not. As many as the complier warnings as possible have been +removed, but these warnings should not prevent the programs compliing on version 1.8.5 of the IDE. + +There is a complier warning against the Flash-5 Library, but it is only a warning and not an error. + +The programs may not compile on old versions of the complier due to space issues or other changes +that may have occured in the Arduino environment over time, it is not practical to test the +programs against each particular version of the Arduino IDE. If you have problems, you will need +to upgrade your Arduino IDE to a modern version. + +The user of these programs is expected to have had a reasonable level of experience in using the +Arduino environment. Using the programs does require the user to make configuration changes so +they will need to be able to cope with complier errors due to issues that they may create. + +Stuart Robinson +www.LoRaTracker.uk + + \ No newline at end of file diff --git a/LoRa/LoRaTracker/HAB2/Schematic/GPS Breakout 200917 Schematic.pdf b/LoRa/LoRaTracker/HAB2/Schematic/GPS Breakout 200917 Schematic.pdf new file mode 100644 index 0000000..0ac0cff Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Schematic/GPS Breakout 200917 Schematic.pdf differ diff --git a/LoRa/LoRaTracker/HAB2/Schematic/HAB2 Tracker DRF1278F 070618 Schematic.pdf b/LoRa/LoRaTracker/HAB2/Schematic/HAB2 Tracker DRF1278F 070618 Schematic.pdf new file mode 100644 index 0000000..2b60013 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Schematic/HAB2 Tracker DRF1278F 070618 Schematic.pdf differ diff --git a/LoRa/LoRaTracker/HAB2/Schematic/HAB2 Tracker RFM9x 090218 Schematic.pdf b/LoRa/LoRaTracker/HAB2/Schematic/HAB2 Tracker RFM9x 090218 Schematic.pdf new file mode 100644 index 0000000..58fba04 Binary files /dev/null and b/LoRa/LoRaTracker/HAB2/Schematic/HAB2 Tracker RFM9x 090218 Schematic.pdf differ diff --git a/LoRa/LoRaTracker/Readme.md b/LoRa/LoRaTracker/Readme.md new file mode 100644 index 0000000..6fc0dca --- /dev/null +++ b/LoRa/LoRaTracker/Readme.md @@ -0,0 +1,2 @@ +This folder contains all the code for building, testing and running the LoRa Tracker boards from [LoRaTracker.uk](https://loratracker.uk) +Thank you to [Stuart Robinson](https://github.com/LoRaTracker) for the Code and Boards. \ No newline at end of file diff --git a/LoRa/LoRaTracker/Receiver1/Board/LCD Receiver3 110818 PCB.pdf b/LoRa/LoRaTracker/Receiver1/Board/LCD Receiver3 110818 PCB.pdf new file mode 100644 index 0000000..135accd Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Board/LCD Receiver3 110818 PCB.pdf differ diff --git a/LoRa/LoRaTracker/Receiver1/LCD Receiver Build2.doc b/LoRa/LoRaTracker/Receiver1/LCD Receiver Build2.doc new file mode 100644 index 0000000..adbd07d Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/LCD Receiver Build2.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/LoRaTracker Receivers.doc b/LoRa/LoRaTracker/Receiver1/LoRaTracker Receivers.doc new file mode 100644 index 0000000..0348429 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/LoRaTracker Receivers.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Kitting List.xls b/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Kitting List.xls new file mode 100644 index 0000000..43f5be4 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Kitting List.xls differ diff --git a/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Parts list.pdf b/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Parts list.pdf new file mode 100644 index 0000000..78d00f6 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Parts list.pdf differ diff --git a/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Parts list.xls b/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Parts list.xls new file mode 100644 index 0000000..ec5585e Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Parts/LCD Receiver Parts list.xls differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0985.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0985.JPG new file mode 100644 index 0000000..7c2c2ba Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0985.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0990.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0990.JPG new file mode 100644 index 0000000..947ce5b Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0990.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0993.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0993.JPG new file mode 100644 index 0000000..72fc2a6 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/IMG_0993.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/DRF1278F.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/DRF1278F.jpg new file mode 100644 index 0000000..59ad9d9 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/DRF1278F.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/GlobalTop GPS.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/GlobalTop GPS.jpg new file mode 100644 index 0000000..fef2ff5 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/GlobalTop GPS.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1256.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1256.JPG new file mode 100644 index 0000000..8bca444 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1256.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1257.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1257.JPG new file mode 100644 index 0000000..b06922e Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1257.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1260.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1260.JPG new file mode 100644 index 0000000..7cd8e61 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1260.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1262.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1262.JPG new file mode 100644 index 0000000..63059de Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1262.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1266.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1266.JPG new file mode 100644 index 0000000..daafc2d Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1266.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1272.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1272.JPG new file mode 100644 index 0000000..da250e1 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1272.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1273.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1273.JPG new file mode 100644 index 0000000..27a4ebf Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1273.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1278.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1278.JPG new file mode 100644 index 0000000..517490a Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1278.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1280.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1280.JPG new file mode 100644 index 0000000..0210b18 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1280.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1282.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1282.JPG new file mode 100644 index 0000000..c51f2a9 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1282.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1287.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1287.JPG new file mode 100644 index 0000000..0ad21db Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1287.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1289.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1289.JPG new file mode 100644 index 0000000..6d76127 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1289.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1290.JPG b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1290.JPG new file mode 100644 index 0000000..38b2e75 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/IMG_1290.JPG differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/LCD Receiver.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/LCD Receiver.jpg new file mode 100644 index 0000000..26fed27 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/LCD Receiver.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/LCD_Receiver_PCB2.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/LCD_Receiver_PCB2.jpg new file mode 100644 index 0000000..09eb490 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/LCD_Receiver_PCB2.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/MicroSD Positions.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/MicroSD Positions.jpg new file mode 100644 index 0000000..e23adee Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/MicroSD Positions.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/RFM98.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/RFM98.jpg new file mode 100644 index 0000000..b0d859b Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/LCD Receiver/RFM98.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Pictures/lcd_20x4.jpg b/LoRa/LoRaTracker/Receiver1/Pictures/lcd_20x4.jpg new file mode 100644 index 0000000..e139201 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Pictures/lcd_20x4.jpg differ diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic Receiver Portable Program Notes.doc b/LoRa/LoRaTracker/Receiver1/Programs/Basic Receiver Portable Program Notes.doc new file mode 100644 index 0000000..330c95f Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Programs/Basic Receiver Portable Program Notes.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic Receiver Terminal Program Notes.doc b/LoRa/LoRaTracker/Receiver1/Programs/Basic Receiver Terminal Program Notes.doc new file mode 100644 index 0000000..6fb22d7 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Programs/Basic Receiver Terminal Program Notes.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Logger_061017/Basic_Receiver_Logger_061017.ino b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Logger_061017/Basic_Receiver_Logger_061017.ino new file mode 100644 index 0000000..6dcb74f --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Logger_061017/Basic_Receiver_Logger_061017.ino @@ -0,0 +1,1727 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the Basic_Receiver_Logger_Settings file not here ! +// +//************************************************************************************************** + +#define programname "Basic_Receiver_Logger_061017" +#define programversion "V2.1" +#define aurthorname "Stuart Robinson - www.LoRaTracker.uk" + +#include +#include + +#include "Program_Definitions.h" +#include "Basic_Receiver_Logger_Settings.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To do: + + + ****************************************************************************************************** +*/ + + +//Program Variables +int ramc_CalibrationOffset; //adjustment for frequency in Hertz + +unsigned long ramc_TrackerMode_Frequency; //Initial default for FlightFrequency +byte ramc_TrackerMode_Bandwidth; //used to keep Tracker mode settings +byte ramc_TrackerMode_SpreadingFactor; +byte ramc_TrackerMode_CodeRate; +byte ramc_TrackerMode_Power; + +unsigned long ramc_SearchMode_Frequency; //Initial default for FlightFrequency +byte ramc_SearchMode_Bandwidth; //used to keep Searc mode settings +byte ramc_SearchMode_SpreadingFactor; +byte ramc_SearchMode_CodeRate; +byte ramc_SearchMode_Power; + +unsigned long ramc_CommandMode_Frequency; //Initial default for command and reporting frequency +byte ramc_CommandMode_Bandwidth; //used to keep Command mode settings +byte ramc_CommandMode_SpreadingFactor; +byte ramc_CommandMode_CodeRate; +byte ramc_CommandMode_Power; + + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; +unsigned int TResets; //keeps the count of remote tracker resets +byte TRStatus; //Status byte from tracker binary payload +byte TRSats; //last received number of GPS satellites from tracker +boolean Remote_GPS_Fix = false; //set if we have received a location from the remote tracker + +char keypress; //records the keypress from serial terminal +byte modenumber; //records which set of LoRa settings in use, 1 = tracker, 2 = search, 3 = command, 4=bind +byte Function_Number = 0; + +boolean SD_Found = false; //set if SD card found at program startup + +unsigned long TrackerMode_Packets; //running count of trackermode packets received +unsigned int SearchMode_Packets; //running count of searchmode packets received +unsigned int TestMode_Packets; //running count of searchmode packets received +unsigned long NoFix_Packets; //running count of No GPS fix packets received + +unsigned int SupplyVolts; + +char Flight_ID[15]; + +//File Includes +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include +#include "LoRa3.h" + +#ifdef UseSD +#include //https://github.com/greiman/SdFat +SdFat SD; +File logFile; +#endif + + +#ifdef USE_AFSK_RTTY_Upload +#include "AFSK_RTTY.h" +#endif + +#ifdef USE_SendOnlySoftwareSerial +#include //https://github.com/disq/i2c-gps-nav/blob/master/I2C_GPS_NAV/SendOnlySoftwareSerial.h +SendOnlySoftwareSerial Bluetooth_Serial (Bluetooth_TX); +#endif + +#ifdef USE_HardwareSerial +#define Bluetooth_Serial Hardware_Bluetooth_Port +#endif + +#ifdef Use_NMEA_Bluetooth_Uplink +#include "Generate_NMEA2.h" +#endif + +#include "Binary2.h" +#include "PinChangeInterrupt.h" + +#define max_functions 5 //number of functions in main program loop + + +//************************************************************************************************** +// Eventally - the program itself starts ............ +//************************************************************************************************** + + +void loop() +{ + + #ifndef NoMenu + do + { + doMenu(); + } while (1); + #endif + + while (Serial.read() != -1); //clear serial buffer + + Setup_LoRaTrackerMode(); + listen_LoRa(TrackerMode, 0); + Serial.println(); + while (Serial.read() != -1); //clear serial buffer + + Setup_LoRaSearchMode(); + listen_LoRa(SearchMode, 0); + Serial.println(); +} + +void doMenu() +{ + //prints the terminal menu, caqn be ignored in handheld display mode (no serial characters to input +menustart: + + digitalWrite(LED1, LOW); //make sure LED is off + Setup_LoRaTrackerMode(); + + Serial.println(); + Serial.println(); + print_last_HABpacket(); + print_TRData(); + Serial.println(); + print_CurrentLoRaSettings(); + print_Nodes(); + Serial.println(); + Serial.println(F("1) Enable FSK RTTY")); + Serial.println(F("2) Disable FSK RTTY")); + Serial.println(F("3) Enable Address Strip")); + Serial.println(F("4) Disable Address Strip")); + Serial.println(F("5) Enable GPS Power Off")); + Serial.println(F("6) Disable GPS Power Off")); + Serial.println(F("7) Enable Fence Check")); + Serial.println(F("8) Disable Fence Check")); + Serial.println(F("9) Enable Doze Mode")); + Serial.println(F("0) Disable Doze Mode")); + Serial.println(); + Serial.println(F("B) Bind Receive")); + Serial.println(F("C) Command Mode Listen")); + Serial.println(F("D) Default Configuration")); + Serial.println(F("L) Link Report")); + Serial.println(F("O) Offset for Tracker Frequency")); + Serial.println(F("P) Packet Test")); + Serial.println(F("R) RTTY Test")); + Serial.println(F("S) Search Mode Listen")); + Serial.println(F("T) Tracker Mode Listen")); + + Serial.println(F("X) Reset Tracker Transmitter")); + Serial.println(F("Y) Clear All Memory and Settings (re-config needed)")); + Serial.println(); + Serial.println(F("+) Increase Transmitter Frequency 1KHZ")); + Serial.println(F("-) Reduce Transmitter Frequency 1KHZ")); + Serial.println(); + Serial.print(F("> ")); + delay(switch_delay); + + while (Serial.read() != -1); //clear serial buffer + + while ((Serial.available() == 0)) + { + //we are in menu mode so wait for a keypress or a switch press + } + + keypress = Serial.read(); //get the keypress + + Serial.println(keypress); + Serial.println(); + + if (keypress == '1') + { + Serial.println(F("Queue Enable FSKRTTY")); + send_ConfigCommand(Config0, ThisNode, FSKRTTYEnable, 1); + } + + if (keypress == '2') + { + Serial.println(F("Queue Disable FSKRTTY")); + send_ConfigCommand(Config0, ThisNode, FSKRTTYEnable, 0); + } + + if (keypress == '3') + { + Serial.println(F("Queue Enable Address Strip")); + send_ConfigCommand(Config0, ThisNode, AddressStrip, 1); + } + + if (keypress == '4') + { + Serial.println(F("Queue Disable Address Strip")); + send_ConfigCommand(Config0, ThisNode, AddressStrip, 0); + } + + if (keypress == '5') + { + //this is lat,long and alt at low data rate + Serial.println(F("Queue Enable GPS Power Off")); + send_ConfigCommand(Config0, ThisNode, GPSHotFix, 1); + } + + if (keypress == '6') + { + //this is lat,long and alt at low data rate + Serial.println(F("Queue Disable GPS Power Off")); + send_ConfigCommand(Config0, ThisNode, GPSHotFix, 0); + } + + if (keypress == '7') + { + Serial.println(F("Queue Enable Fence Check")); + send_ConfigCommand(Config0, ThisNode, CheckFence, 1); + } + + + if (keypress == '8') + { + Serial.println(F("Queue Disable Fence Check")); + send_ConfigCommand(Config0, ThisNode, CheckFence, 0); + } + + if (keypress == '9') + { + Serial.println(F("Queue Enable Doze")); + send_ConfigCommand(Config0, ThisNode, DozeEnable, 1); + } + + if (keypress == '0') + { + Serial.println(F("Queue Disable Doze")); + send_ConfigCommand(Config0, ThisNode, DozeEnable, 0); + } + + + if ((keypress == 'B') || (keypress == 'b')) + { + Function_Number = 5; //bind only accepted in function 5 + listen_LoRa(BindMode, 0); + Serial.println(F("Exit Bind Mode")); + } + + if ((keypress == 'C') || (keypress == 'c')) + { + Function_Number = 0; + listen_LoRa(CommandMode, 0); + } + + + + if ((keypress == 'L') || (keypress == 'l')) + { + lora_TXBUFF[0] = '0'; + Serial.println(F("Queue Link Report")); + Setup_LoRaCommandMode(); + lora_QueuedSend(0, 0, LinkReport, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a Link Report Request + delay(inter_Packet_delay); + listen_LoRa(CommandMode, 0); //listen for the link budget reply + } + + if ((keypress == 'O') || (keypress == 'o')) + { + enter_CalibrationOffset(); + } + + if ((keypress == 'P') || (keypress == 'p')) + { + Serial.println(F("Queue LoRa Packet Test")); + Setup_LoRaCommandMode(); + send_TestRequest('0'); + listen_LoRa(TrackerMode, 0); //command has been sent so listen for replies + } + + if ((keypress == 'R') || (keypress == 'r')) + { + Serial.println(F("Queue FSK RTTY Test Request")); + Setup_LoRaCommandMode(); + send_TestRequest('1'); + } + + if ((keypress == 'S') || (keypress == 's')) + { + Function_Number = 2; + listen_LoRa(SearchMode, 0); + } + + if ((keypress == 'T') || (keypress == 't')) + { + Function_Number = 1; + listen_LoRa(TrackerMode, 0); + } + + + if (keypress == 'D') + { + //Serial.println(F("Configure from Defaults")); + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); + } + + if (keypress == 'Y') + { + Clear_All_Memory(); + read_Settings_Memory(); + } + + if (keypress == 'X') + { + load_key(); + Serial.println(F("Queue Reset Tracker")); + lora_QueuedSend(0, 3, ResetTracker, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a reset request + } + + if (keypress == '+') + { + Serial.println(F("Increase Tracker Frequency 1KHZ")); + lora_QueuedSend(0, 1, INCFreq, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); + } + + if (keypress == '-') + { + Serial.println(F("Decrease Tracker Frequency 1KHZ")); + lora_QueuedSend(0, 1, DECFreq, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); + } + + goto menustart; //all programs deserve at least one goto, if only because it works +} + + +void load_key() +{ + //loads the protection key to first locations in TX buffer + lora_TXBUFF[0] = key0; + lora_TXBUFF[1] = key1; + lora_TXBUFF[2] = key2; + lora_TXBUFF[3] = key3; +} + + +void enter_CalibrationOffset() +{ + //allows calibration offset of recever to be changed from terminal keyboard + float tempfloat; + char temp=0; + temp++; + Serial.println(F("Enter Khz offset > ")); + while (Serial.available() == 0); + { + tempfloat = Serial.parseFloat(); + Serial.print(F("Offset = ")); + Serial.println(tempfloat, 5); + } + while (Serial.available() > 0) + { + temp = Serial.read(); //clear keyboard buffer + } +} + + +boolean Is_Key_Valid() +{ + //checks if protection key in RX bauffer matches + + Serial.print(F("Received Key ")); + Serial.write(lora_RXBUFF[0]); + Serial.write(lora_RXBUFF[1]); + Serial.write(lora_RXBUFF[2]); + Serial.write(lora_RXBUFF[3]); + Serial.println(); + + if ( (lora_RXBUFF[0] == key0) && (lora_RXBUFF[1] == key1) && (lora_RXBUFF[2] == key2) && (lora_RXBUFF[3] == key3) ) + { + Serial.println(F("Key Valid")); + return true; + } + else + { + Serial.println(F("Key Not Valid")); + return false; + } +} + + +byte listen_LoRa(byte lmode, unsigned long listen_mS) +{ + //listen for packets in specific mode, timeout in mS, 0 = continuous wait + unsigned long listen_endmS; + + switch (lmode) + { + case TrackerMode: + Setup_LoRaTrackerMode(); + break; + + case SearchMode: + Setup_LoRaSearchMode(); + break; + + case CommandMode: + Setup_LoRaCommandMode(); + break; + + case BindMode: + Setup_LoRaBindMode(); + break; + } + + print_CurrentLoRaSettings(); + listen_endmS = (millis() + listen_mS); //calculate the millis to stop listing at. + + keypress = 0; + + while (Serial.read() != -1); //empty serial buffer + + //Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXpacketCount = 0; + keypress = 0; + lora_RXONLoRa(); + + do + { + check_for_Packet(); + + if (listen_mS > 0) + { + if (millis() >= listen_endmS) + { + Serial.println(F("Listen Timeout")); + break; + } + } + } + while ((Serial.available() == 0)); + + if (Serial.available() != 0) + { + keypress = Serial.read(); + } + + if (keypress > 0) + { + Serial.println(F("Key Press")); + } + + if ( (millis() > listen_endmS) && (listen_mS != 0) ) + { + Serial.println(F("Timeout")); + keypress = 1; + } + + return keypress; +} + + +void print_mode(byte lmode) +{ + switch (lmode) + { + case TrackerMode: + Serial.print(F("Tracker Mode ")); + break; + + case SearchMode: + Serial.print(F("Search Mode ")); + break; + + case CommandMode: + Serial.print(F("Command Mode ")); + break; + + case BindMode: + Serial.print(F("Bind Mode ")); + break; + } +} + + +void send_TestRequest(char cmd) +{ + //transmit a test request + Serial.print(F("Send Test Request ")); + Serial.write(cmd); + Serial.println(); + + lora_TXBUFF[0] = cmd; + lora_QueuedSend(0, 0, Test, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a Test Request + delay(inter_Packet_delay); +} + + +void send_ConfigCommand(char confignum, char configdestination, char bitnum, char bitval) +{ + //transmits a config command + byte returnbyte; + Setup_LoRaCommandMode(); + bitnum = bitnum + 48; + bitval = bitval + 48; + lora_TXBUFF[0] = bitnum; //set the bitnum + lora_TXBUFF[1] = bitval; //set the bitval + + returnbyte = lora_QueuedSend(0, 1, Config0, configdestination, ThisNode, 10, lora_Power, default_attempts, NoStrip); + + if (returnbyte == 1) + { + Serial.println(F("Config Sent OK")); + print_TrackerLastSNR(); + print_TrackerLastRSSI(); + } + else + { + Serial.println(F("Config Send Failed")); + } + Serial.println(); + delay(inter_Packet_delay); +} + + + +void print_TrackerLastSNR() +{ + int8_t temp; + temp = Read_Byte(0, lora_RXBUFF); + Serial.print(F("Last Tracker SNR ")); + Serial.print(temp); + Serial.println(F("dB")); +} + + +void print_TrackerLastRSSI() +{ + int8_t temp; + temp = Read_Byte(1, lora_RXBUFF); + Serial.print(F("Last Tracker RSSI ")); + Serial.print(temp); + Serial.println(F("dB")); +} + + +byte check_for_Packet() +{ + //checks to see if a packet has arrived + byte returnbyte; + + #ifdef No_DIO0_RX_Ready + returnbyte = lora_readRXready(); + #else + returnbyte = lora_readRXready2(); + #endif + + if (returnbyte == 64) + { + digitalWrite(LED1, HIGH); + lora_ReadPacket(); + lora_AddressInfo(); + lora_ReceptionInfo(); + Serial.println(); + process_Packet(); + digitalWrite(LED1, LOW); + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXONLoRa(); //ready for next and clear flags + return 1; + } + + if (returnbyte == 96) + { + Serial.println(F("CRC Error")); + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXONLoRa(); //ready for next + } + + return 0; +} + + +void write_HABPacketMemory(byte RXStart, byte RXEnd) +{ + //stores the HAB packet in memory, FRAM or EEPROM + byte index, bufferdata; + unsigned int MemAddr = addr_StartHABPayloadData; //address in FRAM where last received HAB payload stored + + Memory_WriteByte(MemAddr, lora_RXPacketType); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXDestination); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXSource); + MemAddr++; + for (index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + Memory_WriteByte(MemAddr, bufferdata); + MemAddr++; + } + Memory_WriteByte(MemAddr, 0xFF); +} + + +void print_FightID() +{ + //send flight ID to serila terminal + byte index, bufferdata; + index = 0; + do + { + bufferdata = Flight_ID[index++]; + Serial.write(bufferdata); + } + while (bufferdata != 0); +} + + + +void extract_HABPacket(byte passedRXStart, byte passedRXEnd) +{ + //extracts data from received HAB packets where first fields are lat,lon,alt. + byte tempbyte; + byte savedRXStart; + + savedRXStart = lora_RXStart; //save current value of lora_RXStart + lora_RXStart = passedRXStart; //use lora_RXStart as its global + + //Skip leading $ + do + { + tempbyte = lora_RXBUFF[lora_RXStart++]; + } + while ( tempbyte == '$'); + lora_RXStart--; + + //ID + tempbyte = sizeof(Flight_ID); + + extract_Buffer(Flight_ID, sizeof(Flight_ID)); + + print_FightID(); + Serial.print(F(" ")); + + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Lat + TRLat = extract_Float(); + + //Lon + TRLon = extract_Float(); + + //Alt + TRAlt = extract_Uint(); + + print_Tracker_Location(); + Serial.println(); + + TRSats = extract_Uint(); + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Reset + TResets = extract_Uint(); + lora_RXStart = next_Comma(lora_RXStart); + TRStatus = extract_Uint(); + lora_RXStart = savedRXStart; //restore lora_RXStart, just in case +} + + +float extract_Float() +{ + //extracts a float in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte bufferdata; + float tempfloat; + do + { + bufferdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = bufferdata; + } + while (bufferdata != ','); + temp[tempptr] = 0; //terminator for string + tempfloat = (float)atof(temp); + return tempfloat; +} + + +void extract_Buffer(char * mybuffer, size_t bufSize) +{ + //extracts a buffer in ASCII format from RXbuffer + byte index, buffersize; + + buffersize = bufSize - 1; + for (index = 0; index <= buffersize; index++) + { + mybuffer[index] = lora_RXBUFF[lora_RXStart++]; + if (mybuffer[index] == ',') + { + break; + } + } + mybuffer[index] = 0; +} + + +float extract_Uint() +{ + //extracts an unsigned int in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte buffdata; + unsigned int tempint; + do + { + buffdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = buffdata; + } + while (buffdata != ','); + temp[tempptr] = 0; //terminator for string + tempint = (unsigned int)atof(temp); + return tempint; +} + + +byte next_Comma(byte localpointer) +{ + //skips through HAB packet (in CSV format) to next comma + byte bufferdata; + do + { + bufferdata = lora_RXBUFF[localpointer++]; + } + while (bufferdata != ','); + return localpointer; +} + + +/********************************************************************** + Tracker data routines +*********************************************************************** +*/ + +void extract_TRbinarylocationData() +{ + //extracts the binary location data from receive buffer and records date and time + + TRLat = Read_Float(0, lora_RXBUFF); + TRLon = Read_Float(4, lora_RXBUFF); + TRAlt = Read_UInt(8, lora_RXBUFF); +} + + +void print_TRData() +{ + //prints the last received tracker location data + Serial.print(F("Last Location ")); + Serial.print(TRLat, 5); + Serial.print(F(" ")); + Serial.print(TRLon, 5); + Serial.print(F(" ")); + Serial.println(TRAlt); +} + + +void save_TRData() +{ + //writes the last received tracker location data to memory + Memory_WriteFloat(addr_TRLat, TRLat); + Memory_WriteFloat(addr_TRLon, TRLon); + Memory_WriteUInt(addr_TRAlt, TRAlt); + +} + + +void read_TRData() +{ + //read stored tracker location data from memory + TRLat = Memory_ReadFloat(addr_TRLat); + TRLon = Memory_ReadFloat(addr_TRLon); + TRAlt = Memory_ReadUInt(addr_TRAlt); +} + + +void clear_TRData() +{ + //sets the tracker location data to zero + TRLat = 0; + TRLon = 0; + TRAlt = 0; +} + + +void print_Tracker_Location() +{ + //prints the tracker location data only + Serial.print(TRLat, 6); + Serial.print(F(",")); + Serial.print(TRLon, 6); + Serial.print(F(",")); + Serial.print(TRAlt); +} + + +void print_packet_HEX(byte RXStart, byte RXEnd) +{ + //prints contents of received packet as hexadecimal + byte bufferdata; + Serial.print(lora_RXPacketType, HEX); + Serial.print(F(" ")); + Serial.print(lora_RXDestination, HEX); + Serial.print(F(" ")); + Serial.print(lora_RXSource, HEX); + Serial.print(F(" ")); + + for (byte index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + if (bufferdata < 0x10) + { + Serial.print(F("0")); + } + Serial.print(bufferdata, HEX); + Serial.print(F(" ")); + } + +} + + +void process_Packet() +{ + //process and decide what to do with received packet + unsigned int tempint; + byte tempbyte; + + + int8_t tempchar; + + digitalWrite(LED1, HIGH); + + if (lora_RXPacketType == LocationBinaryPacket) + { + Remote_GPS_Fix = true; + + if (modenumber == SearchMode) + { + SearchMode_Packets++; + } + + if (modenumber == TrackerMode) + { + TrackerMode_Packets++; + } + + extract_TRbinarylocationData(); + save_TRData(); + + print_Tracker_Location(); + TRStatus = Read_Byte(10, lora_RXBUFF); + Serial.print(F(",")); + print_AllBits(TRStatus); + Serial.println(); + + +#ifdef UseSD + SD_WriteBinarypacket_Log(); +#endif + + + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + Serial.println(); + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth, sends two NMEA strings + Serial.println(); +#endif + + display_fix_Status(); + return; + } + + + if (lora_RXPacketType == HABPacket) + { + Remote_GPS_Fix = true; + TrackerMode_Packets++; + + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + +#ifdef UseSD + SD_WriteHABpacket_Log(); +#endif + + write_HABPacketMemory(lora_RXStart, lora_RXEnd); + extract_HABPacket(lora_RXStart, lora_RXEnd); + + save_TRData(); + + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth + Serial.println(); +#endif + +#ifdef USE_AFSK_RTTY_Upload + Serial.print(F("AFSK RTTY Upload ")); + Serial.println(); + start_AFSK_RTTY(); + + for (index = 0; index <= 3; index++) + { + SendAFSKRTTY('$'); + } + + for (index = lora_RXStart; index <= lora_RXEnd; index++) + { + SendAFSKRTTY(lora_RXBUFF[index]); + } + SendAFSKRTTY(13); + SendAFSKRTTY(10); + end_AFSK_RTTY(); +#endif + + display_fix_Status(); + return; + } + + + if (lora_RXPacketType == Testpacket) + { + Serial.print(F("TestPacket ")); + TestMode_Packets++; + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + return; + } + + +#ifndef NoMenu + byte ptr; + unsigned int returnedCRC, index; + + if (lora_RXPacketType == Bind ) + { + + Serial.println(F("Tracker Bind Received")); + ptr = 4; //set pointer to start of Bind data in lora_RXBUFF + + if (!Is_Key_Valid()) + { + return; + } + + if ((Function_Number != 5)) //only accept incoming bind request when in function 5 + { + Serial.println(F("Not in Bind Mode")); + return; + } + + Print_CRC_Bind_Memory(); + + tempint = (lora_RXBUFF[lora_RXEnd] * 256) + (lora_RXBUFF[lora_RXEnd - 1]); + + Serial.print(F("Transmitted CRC ")); + Serial.println(tempint, HEX); + returnedCRC = RXBuffer_CRC(ptr, (lora_RXEnd - 2)); + Serial.print(F("Received CRC ")); + Serial.println(returnedCRC, HEX); + + + if (returnedCRC == tempint) + { + Serial.println(F("Accepted")); + + for (index = addr_StartBindData; index <= addr_EndBindData; index++) + { + tempbyte = lora_RXBUFF[ptr++]; + Memory_WriteByte(index, tempbyte); + } + read_Settings_Memory(); //now bring the new settings into use + Print_CRC_Bind_Memory(); + } + else + { + Serial.println(F("Rejected")); + //writescreen_Alert7(); + return; + } + } +#endif + + + if (lora_RXPacketType == Wakeup) + { + Serial.write(7); //print a bell + Serial.println(); + return; + } + + + if (lora_RXPacketType == NoFix) + { + NoFix_Packets++; + Serial.print(F("No Tracker GPS Fix ")); + Serial.println(NoFix_Packets); + return; + } + + if (lora_RXPacketType == NoGPS) + { + Serial.print(F("Tracker GPS Error ")); + return; + } + + + if (lora_RXPacketType == PowerUp) + { + tempint = Read_UInt(2, lora_RXBUFF); + Serial.print(F("Power Up ")); + Serial.print(tempint); + Serial.println(F("mV")); + return; + } + + if (lora_RXPacketType == Info) + { + Serial.println(); + Serial.print(F("Tracker Last Packet Reception SNR,")); + tempchar = Read_Byte(0, lora_RXBUFF); + Serial.print(tempchar); + Serial.print(F("dB")); + tempchar = Read_Byte(1, lora_RXBUFF); + Serial.print(F(" RSSI,")); + Serial.print(tempchar); + Serial.println(F("dB")); + Serial.print(F("Battery,")); + tempint = Read_Int(2, lora_RXBUFF); + Serial.print(tempint); + Serial.print(F("mV,TRStatus,")); + tempbyte = (byte) Read_Int(4, lora_RXBUFF); + print_AllBits(tempbyte); + Serial.println(); + Serial.println(); + return; + } + + if (lora_RXPacketType == ClearToSendCommand) + { + return; //do nothing + } + + if (lora_RXPacketType == ClearToSend) + { + return; //do nothing + } + + + if (lora_RXPacketType == Sensor1) + { + Serial.println(F("Sensor1 Packet")); + process_Sensor1(); + } + + +} + + +unsigned int RXBuffer_CRC(unsigned int startaddr, unsigned int endaddr) +{ + unsigned int i, CRC; + + CRC = 0xffff; //start value for CRC16 + byte j; + + for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start + { + CRC ^= ((uint16_t) lora_RXBUFF[i] << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + return CRC; + +} + + + + +void process_Sensor1() +{ + float lTemperature, lHumidity, lPressure, lAltitude; + + lTemperature = Read_Float(0, lora_RXBUFF); + lHumidity = Read_Float(4, lora_RXBUFF); + lPressure = Read_Float(8, lora_RXBUFF); + lAltitude = Read_Float(12, lora_RXBUFF); + + Serial.print(F("Temperature: ")); + Serial.print(lTemperature, 2); + Serial.println(F(" degrees C")); + + Serial.print(F("%RH: ")); + Serial.print(lHumidity, 2); + Serial.println(F(" %")); + + Serial.print(F("Pressure: ")); + Serial.print(lPressure, 2); + Serial.println(F(" Pa")); + + Serial.print(F("Altitude: ")); + Serial.print(lAltitude, 2); + Serial.println(F("m")); +} + + +void print_AllBits(byte myByte) +{ + //prints bits of byte as binary + for (byte mask = 0x80; mask; mask >>= 1) { + if (mask & myByte) + Serial.print('1'); + else + Serial.print('0'); + } +} + + +void display_fix_Status() +{ + //display fix status of tracker + + if (!(bitRead(TRStatus, GPSFix))) + { + Serial.print(F("No ")); + } + + Serial.println(F("Tracker GPS fix")); +} + + +#ifdef UseSD +void SD_WriteHABpacket_Log() +{ + //write HAB packet to SD card + byte index; + + if (SD_Found) + { + logFile.write(lora_RXPacketType); + logFile.write(lora_RXDestination); + logFile.write(lora_RXSource); + logFile.print(F(",")); + + for (index = lora_RXStart; index <= lora_RXEnd; index++) + { + logFile.write(lora_RXBUFF[index]); + } + logFile.write(13); + logFile.write(10); + logFile.flush(); + } + else + { + Serial.println("No SD card !"); + } +} + + +void SD_WriteBinarypacket_Log() +{ + //send the location data in binary packet to the log + if (SD_Found) + { + logFile.write(lora_RXPacketType); + logFile.write(lora_RXDestination); + logFile.write(lora_RXSource); + logFile.print(F(",")); + SD_addLatLonAlt_Log(); + + logFile.write(13); + logFile.write(10); + logFile.flush(); + } + else + { + Serial.println(F("No SD card !")); + } +} + + +void SD_addLatLonAlt_Log() +{ + logFile.print(TRLat, 6); + logFile.print(F(",")); + logFile.print(TRLon, 6); + logFile.print(F(",")); + logFile.print(TRAlt, 6); +} + + + +boolean setup_SDLOG() +{ + //checks if the SD card is present and can be initialised + + Serial.print(F("SD card...")); + + if (!SD.begin(SD_CS)) + { + Serial.println(F("Failed, or not present")); + SD_Found = false; + return false; //don't do anything more: + } + + Serial.print(F("Initialized OK")); + SD_Found = true; + + char filename[] = "Track000.txt"; + for (uint8_t i = 0; i < 100; i++) { + filename[6] = i / 10 + '0'; + filename[7] = i % 10 + '0'; + if (! SD.exists(filename)) { + // only open a new file if it doesn't exist + logFile = SD.open(filename, FILE_WRITE); + break; // leave the loop! + } + } + + Serial.print(F("...Writing to ")); + Serial.print(F("Track0")); + Serial.write(filename[6]); + Serial.write(filename[7]); + Serial.print(F(".txt")); + return true; +} + + + +void printlog_addleadingZero(byte temp) +{ + if (temp < 10) + { + logFile.print(F("0")); + } + logFile.print(temp); +} +#endif + + + +void print_CurrentLoRaSettings() +{ + //prints the current LoRa settings, reads device registers + float tempfloat; + int tempint; + byte regdata; + unsigned long bw; + + tempfloat = lora_GetFreq(); + Serial.print(tempfloat, 3); + Serial.print(F("MHz (")); + + tempint = ramc_CalibrationOffset; + tempfloat = (float)(tempint / 1000); + Serial.print(tempfloat, 1); + + Serial.print(F("Khz)")); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & 0xF0; + bw = lora_returnbandwidth(regdata); + Serial.print(F(" BW")); + Serial.print(bw); + + regdata = lora_Read(lora_RegModemConfig2); + regdata = (regdata & 0xF0) / 16; + Serial.print(F(" SF")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & B00001110; + regdata = regdata / 2; //move right one + regdata = regdata + 4; + + Serial.print(F(" CR4/")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig3); + regdata = regdata & B00001000; + Serial.print(F(" LDROPT_")); + if (regdata == 8) + { + Serial.print(F("ON")); + } + else + { + Serial.print(F("OFF")); + } + + regdata = lora_Read(lora_RegPaConfig); + regdata = regdata - 0xEE; + + Serial.print(F(" Power ")); + Serial.print(regdata); + Serial.print(F("dBm")); + Serial.println(); +} + + +void system_Error() +{ + //there is a error, likley no LoRa device found, cannot continue + while (1) + { + digitalWrite(LED1, HIGH); + delay(50); + digitalWrite(LED1, LOW); + delay(50); + } +} + + +void led_Flash(unsigned int flashes, unsigned int dealymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(dealymS); + digitalWrite(LED1, LOW); + delay(dealymS); + } +} + + +void read_Settings_Defaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Configuring Settings from Defaults")); + ramc_CalibrationOffset = CalibrationOffset; + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_CommandMode_Frequency = CommandMode_Frequency; + ramc_SearchMode_Frequency = SearchMode_Frequency; + ramc_TrackerMode_Bandwidth = TrackerMode_Bandwidth; + ramc_TrackerMode_SpreadingFactor = TrackerMode_SpreadingFactor; + ramc_TrackerMode_CodeRate = TrackerMode_CodeRate; + ramc_CommandMode_Bandwidth = CommandMode_Bandwidth; + ramc_CommandMode_SpreadingFactor = CommandMode_SpreadingFactor; + ramc_CommandMode_CodeRate = CommandMode_CodeRate; + ramc_SearchMode_Bandwidth = SearchMode_Bandwidth; + ramc_SearchMode_SpreadingFactor = SearchMode_SpreadingFactor; + ramc_SearchMode_CodeRate = SearchMode_CodeRate; + ramc_TrackerMode_Power = TrackerMode_Power; + ramc_SearchMode_Power = SearchMode_Power; + ramc_CommandMode_Power = CommandMode_Power; +} + + +void read_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Configuring Settings from Memory")); + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_CommandMode_Frequency = Memory_ReadULong(addr_CommandMode_Frequency); + ramc_SearchMode_Frequency = Memory_ReadULong(addr_SearchMode_Frequency); + ramc_TrackerMode_Bandwidth = Memory_ReadByte(addr_TrackerMode_Bandwidth); + ramc_TrackerMode_SpreadingFactor = Memory_ReadByte(addr_TrackerMode_SpreadingFactor); + ramc_TrackerMode_CodeRate = Memory_ReadByte(addr_TrackerMode_CodeRate); + ramc_CommandMode_Bandwidth = Memory_ReadByte(addr_CommandMode_Bandwidth); + ramc_CommandMode_SpreadingFactor = Memory_ReadByte(addr_CommandMode_SpreadingFactor); + ramc_CommandMode_CodeRate = Memory_ReadByte(addr_CommandMode_CodeRate); + ramc_SearchMode_Bandwidth = Memory_ReadByte(addr_SearchMode_Bandwidth); + ramc_SearchMode_SpreadingFactor = Memory_ReadByte(addr_SearchMode_SpreadingFactor); + ramc_SearchMode_CodeRate = Memory_ReadByte(addr_SearchMode_CodeRate); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + ramc_SearchMode_Power = Memory_ReadByte(addr_SearchMode_Power); + ramc_CommandMode_Power = Memory_ReadByte(addr_CommandMode_Power); +} + +void write_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver.. + Serial.println(F("Writing RAM Settings to Memory")); + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //clear memory area first + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteULong(addr_CommandMode_Frequency, ramc_CommandMode_Frequency); + Memory_WriteULong(addr_SearchMode_Frequency, ramc_SearchMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Bandwidth, ramc_TrackerMode_Bandwidth); + Memory_WriteByte(addr_TrackerMode_SpreadingFactor, ramc_TrackerMode_SpreadingFactor); + Memory_WriteByte(addr_TrackerMode_CodeRate, ramc_TrackerMode_CodeRate); + Memory_WriteByte(addr_CommandMode_Bandwidth, ramc_CommandMode_Bandwidth); + Memory_WriteByte(addr_CommandMode_SpreadingFactor, ramc_CommandMode_SpreadingFactor); + Memory_WriteByte(addr_CommandMode_CodeRate, ramc_CommandMode_CodeRate); + Memory_WriteByte(addr_SearchMode_Bandwidth, ramc_SearchMode_Bandwidth); + Memory_WriteByte(addr_SearchMode_SpreadingFactor, ramc_SearchMode_SpreadingFactor); + Memory_WriteByte(addr_SearchMode_CodeRate, ramc_SearchMode_CodeRate); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + Memory_WriteByte(addr_SearchMode_Power, ramc_SearchMode_Power); + Memory_WriteByte(addr_CommandMode_Power, ramc_CommandMode_Power); +} + + + +void Serialprint_addleadingZero(byte temp) +{ + if (temp < 10) + { + Serial.print(F("0")); + } + Serial.print(temp); +} + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.print(F("Clearing All Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + + +void Print_CRC_Bind_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("CRC_Bind_Memory ")); + Serial.println(returnedCRC, HEX); +} + + +//******************************************************************************************************* + + +void print_Nodes() +{ + //prints current node of this device + Serial.print(F("This Node ")); + Serial.write(ThisNode); + Serial.println(); +} + + +void print_last_HABpacket() +{ + //prints last received HAB packet to serial terminal + byte memorydata; + unsigned int address; + address = addr_StartHABPayloadData; + + Serial.print(F("Last HAB Packet ")); + do + { + memorydata = Memory_ReadByte(address); + if ((memorydata == 0xFF) || (address >= addr_EndHABPayloadData)) + { + break; + } + Serial.write(memorydata); + address++; + } + while (true); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + //sets LoRa modem to Tracker mode + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_TrackerMode_Bandwidth, ramc_TrackerMode_SpreadingFactor, ramc_TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_TrackerMode_Power; + modenumber = TrackerMode; +} + + +void Setup_LoRaSearchMode() +{ + //sets LoRa modem to Search mode + lora_SetFreq(ramc_SearchMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_SearchMode_Bandwidth, ramc_SearchMode_SpreadingFactor, ramc_SearchMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_SearchMode_Power; + modenumber = SearchMode; +} + +void Setup_LoRaCommandMode() +{ + //sets LoRa modem to Command mode + lora_SetFreq(ramc_CommandMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_CommandMode_Bandwidth, ramc_CommandMode_SpreadingFactor, ramc_CommandMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_CommandMode_Power; + modenumber = CommandMode; +} + + +void Setup_LoRaBindMode() +{ + //sets LoRa modem to Bind mode + lora_SetFreq(BindMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(BindMode_Bandwidth, BindMode_SpreadingFactor, BindMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = BindMode_Power; + modenumber = BindMode; +} + + +void display_frequency() +{ + //display current set frequency of LoRa device + float freq_temp; + freq_temp = lora_GetFreq(); + Serial.print(F("Set to Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + + +void display_frequencies_memory() +{ + //display the frequncies set in memory, good check to see if all is well with memory + unsigned long freq_temp; + freq_temp = Memory_ReadULong(addr_TrackerMode_Frequency); + Serial.print(F("TrackerMode ")); + Serial.println(freq_temp); + freq_temp = Memory_ReadULong(addr_SearchMode_Frequency); + Serial.print(F("SearchMode ")); + Serial.println(freq_temp); + freq_temp = Memory_ReadULong(addr_CommandMode_Frequency); + Serial.print(F("CommandMode ")); + Serial.println(freq_temp); + Serial.println(); + +} + + +void setstatusByte(byte bitnum, byte bitval) +{ + //program the status byte +#ifdef Debug + if (bitval) + { + Serial.print(F("Set Status Bit ")); + } + else + { + Serial.print(F("Clear Status Bit ")); + } + + Serial.println(bitnum); +#endif + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } +} + + +void setup() +{ + //needs no explanation I hope ............... + + pinMode(LED1, OUTPUT); //setup pin for PCB LED + led_Flash(2, 250); + + Serial.begin(9600); //setup Serial console ouput + Serial.println(); + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(aurthorname)); + Serial.println(); + + SPI.begin(); //initialize SPI: + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + pinMode(lora_NReset, OUTPUT); //LoRa Device reset line + pinMode (lora_NSS, OUTPUT); //LoRa Device select line + digitalWrite(lora_NSS, HIGH); + digitalWrite(lora_NReset, HIGH); + delay(1); + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); + Serial.println(); + Serial.println(); +#endif + + +#ifdef ClearConfigData + Clear_Config_Memory(); +#endif + + +#ifdef ConfigureDefaults + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); + Serial.flush(); +#endif + +#ifdef ConfigureFromMemory + read_Settings_Memory(); +#endif + + Print_CRC_Bind_Memory(); + + read_TRData(); + + SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); //redo faster SPI as changed by display_setup + + if (!lora_CheckDevice()) + { + Serial.println(F("LoRa Error!")); + led_Flash(40, 50); + } + + lora_Setup(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial_Setup(); +#endif + + print_Nodes(); + Serial.println(); + + Setup_LoRaTrackerMode(); + + Serial.println(); + lora_Print(); + Serial.println(); + +#ifdef CalibrateTone + digitalWrite(LED1, HIGH); //turn on LED + lora_Tone(1000, 3000, 10); //Transmit an FM tone, 1000hz, 1000ms, 10dBm + digitalWrite(LED1, LOW); //LED is off + delay(1000); +#endif + + lora_RXONLoRa(); + +#ifdef UseSD + setup_SDLOG(); //setup SD and delay a bit to ensure any pending ints cleared +#endif + + Serial.println(); + print_last_HABpacket(); + print_TRData(); + Serial.println(); + + Serial.println(); + display_frequencies_memory(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial.println(F("Bluetooth Active")); +#endif + +} + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Logger_061017/Basic_Receiver_Logger_Settings.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Logger_061017/Basic_Receiver_Logger_Settings.h new file mode 100644 index 0000000..219a3a8 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Logger_061017/Basic_Receiver_Logger_Settings.h @@ -0,0 +1,166 @@ +//LoRaTracker_Settings.h +/* +****************************************************************************************************** + +LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson - 23/08/2017 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without +the explicit permission of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the +intended purpose and free from errors. + +To Do: +disable bind mode when menu not selected + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +#define UseSD +//#define Board_Definition "Sensor1_Board_Definitions.h" //define the board definition file to use here +#define Board_Definition "LCD_Receiver_Board_Definitions.h" + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +#define ConfigureDefaults //Configure settings from default program defaults, these are then stored in memory +//#define ClearConfigData //zero the config memory +//#define ClearAllMemory //Clears from start memory to end memory, normally 1kbyte, needs to be followed by ConfigureDefaults +//#define ConfigureFromMemory //Configure settings from values stored in memory, this needs to be the active mode for bind to work + +#define CalibrateTone //comment in to have a calibrate tone at startup + +#define NoMenu //having no terminal menu reduces Flash requirement, you cannot have the menu, Bluetooth uplink and SD card logging together + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 434400000; + +//Search mode +const unsigned long SearchMode_Frequency = 434300000; + +//Command mode +const unsigned long CommandMode_Frequency = 434500000; + +//Bind mode - Change this with great care !!!!! +const unsigned long BindMode_Frequency = 434100000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = -3500; + + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +#define LoRa_Device_in_MB1 //if using a MikroBus based specify the socket for the LoRa Device + +//Tracker mode +const byte TrackerMode_Power = 10; +#define TrackerMode_Bandwidth BW62500 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 + +//Search mode +const byte SearchMode_Power = 10; +#define SearchMode_Bandwidth BW62500 +#define SearchMode_SpreadingFactor SF12 +#define SearchMode_CodeRate CR45 + +//Command mode +const byte CommandMode_Power = 5; +#define CommandMode_Bandwidth BW62500 +#define CommandMode_SpreadingFactor SF10 +#define CommandMode_CodeRate CR45 + + +//Bind mode - Change this with great care !!!!! +const byte BindMode_Power = 2; +#define BindMode_Bandwidth BW500000 +#define BindMode_SpreadingFactor SF8 +#define BindMode_CodeRate CR45 + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 128; +const byte lora_TXBUFF_Size = 16; //logger does not send much + + +#define RemoteControlNode 'G' //normally used by tracker transmitter in promiscuous_Mode +#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +#define ThisNode ControlledNode +const boolean Promiscuous_Mode = true; //if set to false remote control packets from any node accepted +const int inter_Packet_delay = 500; //allows time for receiver to be ready to see a possible reply +const byte Cmd_WaitSecs = 15; //number of seconds to stay in command mode +const byte default_attempts = 5; //default number of times a command will attempt to be sent + +//Protected Command Settings +const char key0 = 'L'; //Used to restrict access to some commands +const char key1 = 'o'; +const char key2 = 'R'; +const char key3 = 'a'; + +//#define No_DIO0_RX_Ready //needed for boards that cannot directly ready the DIO0 pin + + + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +#define Memory_Library "I2CFRAM_MB85RC16PNF.h" +//#define Memory_Library "EEPROM_Memory.h" +//#define Memory_Library "SPIFRAM_Memory_FM25CL64B_MB85RS64.h" //define this file if a SPI FRAM is in use + + +//************************************************************************************************** +// 9) AFSK RTTY Options +//************************************************************************************************** + +//#define USE_AFSK_RTTY_Upload +const int AFSKrttybaud = 1465; //delay in uS x 2 for 1 bit and 300baud. Decode range in FLDIGI 1420 to 1510 +const int afskleadinmS = 500; //number of ms for AFSK constant lead in tone +const int tonehighHz = 1000; //high tone in Hertz +const int tonelowHz = 650; //low tone in Hertz + + +//************************************************************************************************** +// 10) Bluetooth Options +//************************************************************************************************** + +//#define Use_NMEA_Bluetooth_Uplink +//#define USE_SendOnlySoftwareSerial //if you want the Bluetooth device on a pin other than the hardware serial por, define this +//#define USE_HardwareSerial //use hardware serial port to send Bluetooth +//#define Hardware_Bluetooth_Port Serial //Which Hardware port to use for Bluetooth +#define BluetoothBaud 9600 + +const byte Bluetooth_Buff_Size = 128; //size of buffer for NMEA output + + +//************************************************************************************************** +// 12) Miscellaneous program settings +//************************************************************************************************** + +const unsigned int switch_delay = 1000; //delay in mS after a switch press before another can take place + + +//************************************************************************************************** +// 14) HAB2 settings +//************************************************************************************************** + +#define PayloadArraySize 20 //Maximum number of fields when parsing long HAB payload + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/Basic_Receiver_Portable_011217.ino b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/Basic_Receiver_Portable_011217.ino new file mode 100644 index 0000000..ab18cb7 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/Basic_Receiver_Portable_011217.ino @@ -0,0 +1,1140 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the LoRaTracker_Settings file not here ! +// +//************************************************************************************************** + +#define programname "Basic_Receiver_Portable_011217" +#define programversion "V2.1" +#define aurthorname "Stuart Robinson - www.LoRaTracker.uk" + +#include +#include + +#include "Program_Definitions.h" +#include "Basic_Receiver_Portable_Settings.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 01/12/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + This is a basic portable receiver that will run on an ATMEGA328P, it picks up the packets form the + tracker and displays them. There is no two way comminications functionality, apart from the bind function. + The program is a trimmed version of the Receiver2 program. + + To make the program compatible with LoRaTracker boards that use A1 a switch input the switch is polled, + avoiding an interrupt conflict between NeoSWserial and pin change interrupt. + + + + To do: + Check there is Display_Setup() in all libraries + Check need for print_CurrentLoRaSettings() + Why record_LocalData(); save_LocalData(); distanceto(); directionto(); called when def for no GPS + + ****************************************************************************************************** +*/ + + +//Program Variables +int ramc_CalibrationOffset; //adjustment for frequency in Hertz + +unsigned long ramc_TrackerMode_Frequency; //Initial default for FlightFrequency +byte ramc_TrackerMode_Bandwidth; //used to keep Tracker mode settings +byte ramc_TrackerMode_SpreadingFactor; +byte ramc_TrackerMode_CodeRate; +byte ramc_TrackerMode_Power; + +unsigned long ramc_SearchMode_Frequency; //Initial default for FlightFrequency +byte ramc_SearchMode_Bandwidth; //used to keep Searc mode settings +byte ramc_SearchMode_SpreadingFactor; +byte ramc_SearchMode_CodeRate; +byte ramc_SearchMode_Power; + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; +byte TRStatus; //Status byte from tracker binary payload +unsigned int TRdirection; //Tracker direction in degrees +float TRdistance; +boolean Remote_GPS_Fix = false; //set if we have received a location from the remote tracker +boolean GLONASS_Active; +boolean GPS_Config_Error; + +float LocalLat; //local GPS co-ordinates +float LocalLon; +unsigned int LocalAlt; +boolean Local_GPS_Fix = false; //set if there is a Local GPS fix at last check + +byte Switchpress = 0; //set when a switch is pressed, 0 if not otherwise 1-5 +byte Function_Number = 1; //identifiews the current function + +char keypress; //records the keypress from serial terminal +byte modenumber; //records which set of LoRa settings in use, 1 = tracker, 2 = search, 3 = command, 4=bind + +unsigned long TrackerMode_Packets; //running count of trackermode packets received +unsigned int SearchMode_Packets; //running count of searchmode packets received +unsigned int SupplyVolts; + + +//File Includes + +#include Board_Definition //include previously defined board definition file +#include Display_Library //include previously defined Display Library + +#include Memory_Library //include previously defined Memory Library + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //Create the TinyGPS++ object +TinyGPSCustom GNGGAFIXQ(gps, "GNGGA", 5); //custom sentences used to detect possible switch to GLONASS mode + + +#ifdef USE_SOFTSERIAL_GPS +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPSserial(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial +#endif + +#ifndef Do_Not_Use_GPS +#include GPS_Library //include previously defined GPS Library +#endif + +#include +#include +#include "LoRa3.h" +#include Display_Screens //include previously defined screens + +#ifdef USE_SendOnlySoftwareSerial +#include //http://gammon.com.au/Arduino/SendOnlySoftwareSerial.zip +SendOnlySoftwareSerial Bluetooth_Serial (Bluetooth_TX); +#endif + +#ifdef USE_HardwareSerial +#define Bluetooth_Serial Hardware_Bluetooth_Port +#endif + +#ifdef Use_NMEA_Bluetooth_Uplink +#include "Generate_NMEA2.h" +#endif + +#include "Binary2.h" + +#define max_functions 5 //number of functions in main program loop + +//************************************************************************************************** +// Eventally - the program itself starts ............ +//************************************************************************************************** + + +void loop() +{ + run_function(); +} + + +void run_function() +{ + //following a key press to change function this routine runs the appropriate function + + delay(switch_delay); //debounce switch a bit + + switch (Function_Number) + { + case 1: + current_screen_number = 1; + Check_LoRa_and_GPS(TrackerMode, 0); + break; + + case 2: + current_screen_number = 2; + Check_LoRa_and_GPS(SearchMode, 0); + break; + + case 3: + current_screen_number = 3; + //Serial.println(F("Tracker Data Display")); + Check_LoRa_and_GPS(TrackerMode, 0); + break; + + case 4: + current_screen_number = 4; + //Serial.println(F("Local Data Display")); + Check_LoRa_and_GPS(TrackerMode, 0); + break; + + case 5: + current_screen_number = 5; + Check_LoRa_and_GPS(BindMode, 0); + break; + + default: + break; + } +} + +void Display_Listen_Mode() +{ + if ((current_screen_number == 1) || (current_screen_number == 3) || (current_screen_number == 4)) + { + Serial.print(F("Tracker")); + } + if (current_screen_number == 2) + { + Serial.print(F("Search")); + } + if (current_screen_number == 5) + { + Serial.print(F("Bind")); + } + + Serial.print(F(" Listen, ")); +} + + +void print_CurrentLoRaSettings() +{ + //prints the current LoRa settings, reads device registers + float tempfloat; + int tempint; + byte regdata; + unsigned long bw; + + tempfloat = lora_GetFreq(); + Serial.print(tempfloat, 3); + Serial.print(F("MHz (")); + + tempint = ramc_CalibrationOffset; + tempfloat = (float)(tempint / 1000); + Serial.print(tempfloat, 1); + + Serial.print(F("Khz)")); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & 0xF0; + bw = lora_returnbandwidth(regdata); + Serial.print(F(" BW")); + Serial.print(bw); + + regdata = lora_Read(lora_RegModemConfig2); + regdata = (regdata & 0xF0) / 16; + Serial.print(F(" SF")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & B00001110; + regdata = regdata / 2; //move right one + regdata = regdata + 4; + + Serial.print(F(" CR4/")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig3); + regdata = regdata & B00001000; + Serial.print(F(" LDROPT_")); + if (regdata == 8) + { + Serial.print(F("ON")); + } + else + { + Serial.print(F("OFF")); + } + + regdata = lora_Read(lora_RegPaConfig); + regdata = regdata - 0xEE; + + Serial.print(F(" Power ")); + Serial.print(regdata); + Serial.print(F("dBm")); + Serial.println(); +} + + +byte Check_LoRa_and_GPS(byte lmode, unsigned long listen_mS) +{ + //listen for packets in specific mode, timeout in mS, 0 = continuous wait + byte GPSByte; + + switch (lmode) + { + case TrackerMode: + Setup_LoRaTrackerMode(); + break; + + case SearchMode: + Setup_LoRaSearchMode(); + break; + + case BindMode: + Setup_LoRaBindMode(); + break; + } + + Switchpress = 0; + + print_CurrentLoRaSettings(); + + update_screen(current_screen_number); + + Display_Listen_Mode(); + lora_RXpacketCount = 0; + Switchpress = 0; + keypress = 0; + lora_RXONLoRa(); + + do + { + + if (!digitalRead(SWITCH1)) + { + Serial.println(F("Switch1")); + Serial.println(); + Switchpress = SWITCH1; + Function_Number++; + } + + if (Function_Number > max_functions) + { + Function_Number = 1; + } + + if (Function_Number == 0) + { + Function_Number = max_functions; + } + + check_for_Packet(); + +#ifndef Do_Not_Use_GPS + do + { + GPSByte = GPS_GetByte(); + if (GPSByte != 0xFF) + { + gps.encode(GPSByte); + } + } + while (GPSByte != 0xFF); + + check_GPSforFix(); +#endif + + +#ifdef Do_Not_Use_GPS + + Local_GPS_Fix = true; + GLONASS_Active = false; + + record_LocalData(); + save_LocalData(); + + distanceto(); + directionto(); + + update_screen(current_screen_number); + delay(2000); + +#endif + + } + while ((Switchpress == 0)); + + return keypress; +} + + +byte check_for_Packet() +{ + //checks to see if a packet has arrived + byte returnbyte; + +#ifdef No_DIO0_RX_Ready + returnbyte = lora_readRXready(); +#else + returnbyte = lora_readRXready2(); +#endif + + if (returnbyte == 64) + { + digitalWrite(LED1, HIGH); + lora_ReadPacket(); + process_Packet(); + digitalWrite(LED1, LOW); + Display_Listen_Mode(); + lora_RXONLoRa(); //ready for next and clear flags + return 1; + + } + + if (returnbyte == 96) + { + Serial.println(F("CRC Error")); + Display_Listen_Mode(); + lora_RXONLoRa(); //ready for next + } + return 0; //no valid packet received +} + + +void write_HABPacketMemory(byte RXStart, byte RXEnd) +{ + //stores the HAB packet in memory, FRAM or EEPROM + byte index, bufferdata; + unsigned int MemAddr = addr_StartHABPayloadData; //address in FRAM where last received HAB payload stored + + Memory_WriteByte(MemAddr, lora_RXPacketType); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXDestination); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXSource); + MemAddr++; + for (index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + Memory_WriteByte(MemAddr, bufferdata); + MemAddr++; + } + Memory_WriteByte(MemAddr, 0xFF); + +} + + +void extract_HABPacket(byte passedRXStart, byte passedRXEnd) +{ + //extracts data from received HAB packets where first fields are lat,lon,alt. + byte tempbyte; + byte savedRXStart; + + savedRXStart = lora_RXStart; //save current value of lora_RXStart + lora_RXStart = passedRXStart; //use lora_RXStart as its global + + //Skip leading $ + do + { + tempbyte = lora_RXBUFF[lora_RXStart++]; + } + while ( tempbyte == '$'); + lora_RXStart--; + + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Lat + TRLat = extract_Float(); + + //Lon + TRLon = extract_Float(); + + //Alt + TRAlt = extract_Uint(); + + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + lora_RXStart = savedRXStart; //restore lora_RXStart, just in case +} + + +float extract_Float() +{ + //extracts a float in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte bufferdata; + float tempfloat; + do + { + bufferdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = bufferdata; + } + while (bufferdata != ','); + temp[tempptr] = 0; //terminator for string + tempfloat = (float)atof(temp); + return tempfloat; +} + + +float extract_Uint() +{ + //extracts an unsigned int in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte buffdata; + unsigned int tempint; + do + { + buffdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = buffdata; + } + while (buffdata != ','); + temp[tempptr] = 0; //terminator for string + tempint = (unsigned int)atof(temp); + return tempint; +} + + +byte next_Comma(byte localpointer) +{ + //skips through HAB packet (in CSV format) to next comma + byte bufferdata; + do + { + bufferdata = lora_RXBUFF[localpointer++]; + } + while (bufferdata != ','); + return localpointer; +} + + +/********************************************************************** + Tracker data routines +*********************************************************************** +*/ + +void extract_TRbinarylocationData() +{ + //extracts the binary location data from receive buffer and records date and time + TRLat = Read_Float(0, lora_RXBUFF); + TRLon = Read_Float(4, lora_RXBUFF); + TRAlt = Read_UInt(8, lora_RXBUFF); +} + + +void save_TRData() +{ + //writes the last received tracker location data to memory + Memory_WriteFloat(addr_TRLat, TRLat); + Memory_WriteFloat(addr_TRLon, TRLon); + Memory_WriteUInt(addr_TRAlt, TRAlt); +} + + +void read_TRData() +{ + //read stored tracker location data from memory + TRLat = Memory_ReadFloat(addr_TRLat); + TRLon = Memory_ReadFloat(addr_TRLon); + TRAlt = Memory_ReadUInt(addr_TRAlt); +} + + +void clear_TRData() +{ + //sets the tracker location data to zero + TRLat = 0; + TRLon = 0; + TRAlt = 0; +} + + +/********************************************************************** + Local data routines +*********************************************************************** +*/ + +void record_LocalData() +{ + //gets the current local location fix data and time + //time_t t = now(); // Store the current time in time + LocalLat = gps.location.lat(); + LocalLon = gps.location.lng(); + LocalAlt = gps.altitude.meters(); + +#ifdef Use_Test_Location //overwrite local GPS location for test purposes + LocalLat = TestLatitude; + LocalLon = TestLongitude; + LocalAlt = TestAltitude; +#endif + +} + + +void save_LocalData() +{ + //writes local GPS location data to memory + Memory_WriteFloat(addr_LocalLat, LocalLat); //save tracker lat in non volatile memory + Memory_WriteFloat(addr_LocalLon, LocalLon); //save tracker lon in non volatile memory + Memory_WriteUInt(addr_LocalAlt, LocalAlt); //save tracker lon in non volatile memory +} + + + +void read_LocalData() +{ + //reads local GPS location data from memory + LocalLat = Memory_ReadFloat(addr_LocalLat); + LocalLon = Memory_ReadFloat(addr_LocalLon); + LocalAlt = Memory_ReadUInt(addr_LocalAlt); +} + + +void clear_LocalData() +{ + //sets the current local location data to zero + LocalLat = 0; + LocalLon = 0; + LocalAlt = 0; +} + + +boolean Is_Key_Valid() +{ + //checks if protection key in RX buffer matches + + //Serial.print(F("Received Key ")); + //Serial.write(lora_RXBUFF[0]); + //Serial.write(lora_RXBUFF[1]); + //Serial.write(lora_RXBUFF[2]); + //Serial.write(lora_RXBUFF[3]); + //Serial.println(); + + if ( (lora_RXBUFF[0] == key0) && (lora_RXBUFF[1] == key1) && (lora_RXBUFF[2] == key2) && (lora_RXBUFF[3] == key3) ) + { + //Serial.println(F("Key Valid")); + return true; + } + else + { + Serial.println(F("Key Not Valid")); + return false; + } +} + + +void process_Packet() +{ + //process and decide what to do with received packet + unsigned int index, tempint; + byte tempbyte, ptr; + unsigned int returnedCRC; + + digitalWrite(LED1, HIGH); + + if (lora_RXPacketType == LocationBinaryPacket) + { + Remote_GPS_Fix = true; + + if (modenumber == SearchMode) + { + SearchMode_Packets++; + } + + if (modenumber == TrackerMode) + { + TrackerMode_Packets++; + } + + extract_TRbinarylocationData(); + save_TRData(); + print_Tracker_Location(); + Serial.println(); + TRStatus = Read_Byte(10, lora_RXBUFF); + + + if (Local_GPS_Fix) + { + distanceto(); + directionto(); + } + + update_screen(current_screen_number); //and update the appropriate screen + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth, sends two NMEA strings + Serial.println(); +#endif + return; + } + + + if (lora_RXPacketType == HABPacket) + { + Remote_GPS_Fix = true; + TrackerMode_Packets++; + + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + + write_HABPacketMemory(lora_RXStart, lora_RXEnd); + extract_HABPacket(lora_RXStart, lora_RXEnd); + + save_TRData(); + + if (Local_GPS_Fix) + { + distanceto(); + directionto(); + } + + update_screen(current_screen_number); //and update the appropriate screen + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth + Serial.println(); +#endif + + return; + } + + + if (lora_RXPacketType == Bind ) + { + + Serial.println(F("Tracker Bind Received")); + ptr = 4; //set pointer to start of Bind data in lora_RXBUFF + + if (!Is_Key_Valid()) + { + return; + } + + if ((Function_Number != 5)) //only accept incoming bind request when in function 5 + { + Serial.println(F("Not in Bind Mode")); + return; + } + + Print_CRC_Bind_Memory(); + + tempint = (lora_RXBUFF[lora_RXEnd] * 256) + (lora_RXBUFF[lora_RXEnd - 1]); + + Serial.print(F("Transmitted CRC ")); + Serial.println(tempint, HEX); + returnedCRC = RXBuffer_CRC(ptr, (lora_RXEnd - 2)); + Serial.print(F("Received CRC ")); + Serial.println(returnedCRC, HEX); + + + if (returnedCRC == tempint) + { + Serial.println(F("Accepted")); + writescreen_Alert2(); + + for (index = addr_StartBindData; index <= addr_EndBindData; index++) + { + tempbyte = lora_RXBUFF[ptr++]; + Memory_WriteByte(index, tempbyte); + } + read_Settings_Memory(); //now bring the new settings into use + Print_CRC_Bind_Memory(); + } + else + { + Serial.println(F("Rejected")); + writescreen_Alert7(); + return; + } + } + + + if (lora_RXPacketType == NoFix) + { + writescreen_Alert4(); + return; + } + + if (lora_RXPacketType == NoGPS) + { + writescreen_Alert4(); + return; + } + + if (lora_RXPacketType == PowerUp) + { + tempint = Read_UInt(2, lora_RXBUFF); + writescreen_Alert5(tempint); + return; + } + + + if (lora_RXPacketType == Testpacket) + { + Serial.print(F("TestPacket ")); + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + writescreen_7(); + + return; + } + + if (lora_RXPacketType == IsLost) + { + Serial.print(F("Tracker Lost")); + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + writescreen_Alert10(); + delay(1500); + return; + } + + + Serial.println(F("Packet not recognised")); + +} + + +void Print_CRC_Bind_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("Local Bind CRC ")); + Serial.println(returnedCRC, HEX); +} + + +unsigned int RXBuffer_CRC(unsigned int startaddr, unsigned int endaddr) +{ + unsigned int i, CRC; + + CRC = 0xffff; //start value for CRC16 + byte j; + + for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start + { + CRC ^= ((uint16_t) lora_RXBUFF[i] << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + return CRC; + +} + + +void print_Tracker_Location() +{ + //prints the tracker location data only + Serial.print(TRLat, 6); + Serial.print(F(",")); + Serial.print(TRLon, 6); + Serial.print(F(",")); + Serial.print(TRAlt); +} + + +void led_Flash(unsigned int flashes, unsigned int dealymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(dealymS); + digitalWrite(LED1, LOW); + delay(dealymS); + } +} + + +void read_Settings_Defaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + //Serial.print(F("Configuring Settings from Defaults - ")); + ramc_CalibrationOffset = CalibrationOffset; + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_SearchMode_Frequency = SearchMode_Frequency; + ramc_TrackerMode_Bandwidth = TrackerMode_Bandwidth; + ramc_TrackerMode_SpreadingFactor = TrackerMode_SpreadingFactor; + ramc_TrackerMode_CodeRate = TrackerMode_CodeRate; + ramc_SearchMode_Bandwidth = SearchMode_Bandwidth; + ramc_SearchMode_SpreadingFactor = SearchMode_SpreadingFactor; + ramc_SearchMode_CodeRate = SearchMode_CodeRate; + ramc_TrackerMode_Power = TrackerMode_Power; + ramc_SearchMode_Power = SearchMode_Power; +} + + +void read_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + //Serial.print(F("Configuring Settings from Memory")); + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_SearchMode_Frequency = Memory_ReadULong(addr_SearchMode_Frequency); + ramc_TrackerMode_Bandwidth = Memory_ReadByte(addr_TrackerMode_Bandwidth); + ramc_TrackerMode_SpreadingFactor = Memory_ReadByte(addr_TrackerMode_SpreadingFactor); + ramc_TrackerMode_CodeRate = Memory_ReadByte(addr_TrackerMode_CodeRate); + ramc_SearchMode_Bandwidth = Memory_ReadByte(addr_SearchMode_Bandwidth); + ramc_SearchMode_SpreadingFactor = Memory_ReadByte(addr_SearchMode_SpreadingFactor); + ramc_SearchMode_CodeRate = Memory_ReadByte(addr_SearchMode_CodeRate); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + ramc_SearchMode_Power = Memory_ReadByte(addr_SearchMode_Power); +} + + +void write_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver.. + //Serial.print(F("Writing RAM Settings to Memory")); + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //clear memory area first + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteULong(addr_SearchMode_Frequency, ramc_SearchMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Bandwidth, ramc_TrackerMode_Bandwidth); + Memory_WriteByte(addr_TrackerMode_SpreadingFactor, ramc_TrackerMode_SpreadingFactor); + Memory_WriteByte(addr_TrackerMode_CodeRate, ramc_TrackerMode_CodeRate); + Memory_WriteByte(addr_SearchMode_Bandwidth, ramc_SearchMode_Bandwidth); + Memory_WriteByte(addr_SearchMode_SpreadingFactor, ramc_SearchMode_SpreadingFactor); + Memory_WriteByte(addr_SearchMode_CodeRate, ramc_SearchMode_CodeRate); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + Memory_WriteByte(addr_SearchMode_Power, ramc_SearchMode_Power); +} + + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.print(F("Clear Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void check_GPSforFix() +{ + //check GPS for new fix + if (gps.location.isUpdated() && gps.altitude.isUpdated()) //check the fix is updated + { + //last_LocalGPSfixmS = millis(); + + Local_GPS_Fix = true; + GLONASS_Active = false; + + record_LocalData(); + save_LocalData(); + + distanceto(); + directionto(); + + update_screen(current_screen_number); + + } + else + { + +#ifndef Do_Not_Use_GPS + if (GNGGAFIXQ.age() < 2000) //check to see if GLONASS has gone active + { + Serial.println(F("GLONASS !")); + GLONASS_Active = true; + GPS_Setup(); + writescreen_Alert1(); + delay(1000); + update_screen(current_screen_number); + } + else + { + GLONASS_Active = false; + } + + if (gps.location.age() > FixisoldmS) + { + Local_GPS_Fix = false; + } +#endif + + } + +} + + +void directionto() +{ + //using remote and local lat and long calculate direction in degrees + TRdirection = (int) TinyGPSPlus::courseTo(LocalLat, LocalLon, TRLat, TRLon); +} + + +void distanceto() +{ + //using remote and local lat and long calculate distance in metres + TRdistance = TinyGPSPlus::distanceBetween(LocalLat, LocalLon, TRLat, TRLon); +} + + +void Setup_LoRaTrackerMode() +{ + //sets LoRa modem to Tracker mode + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_TrackerMode_Bandwidth, ramc_TrackerMode_SpreadingFactor, ramc_TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_TrackerMode_Power; + modenumber = TrackerMode; +} + + +void Setup_LoRaSearchMode() +{ + //sets LoRa modem to Search mode + lora_SetFreq(ramc_SearchMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_SearchMode_Bandwidth, ramc_SearchMode_SpreadingFactor, ramc_SearchMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_SearchMode_Power; + modenumber = SearchMode; +} + + +void Setup_LoRaBindMode() +{ + //sets LoRa modem to Bind mode + lora_SetFreq(BindMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(BindMode_Bandwidth, BindMode_SpreadingFactor, BindMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = BindMode_Power; + modenumber = BindMode; +} + + +unsigned int ReadSupplyVolts() +{ + //relies on 1V1 internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + unsigned int temp; + byte i; + SupplyVolts = 0; + + analogReference(INTERNAL); + for (i = 0; i <= 2; i++) //sample AD 3 times + { + temp = analogRead(SupplyAD); + SupplyVolts = SupplyVolts + temp; + } + SupplyVolts = (unsigned int) ((SupplyVolts / 3) * ADMultiplier); + return SupplyVolts; +} + + +void setup() +{ + //needs no explanation I hope ............... + + pinMode(LED1, OUTPUT); //setup pin for PCB LED + led_Flash(2, 250); + + pinMode(GPSPOWER, OUTPUT); //setup pin for GPSPower contol, if fitted + digitalWrite(GPSPOWER, LOW); + + Serial.begin(9600); //setup Serial console ouput + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(aurthorname)); + ReadSupplyVolts(); + + pinMode(SWITCH1, INPUT_PULLUP); //setup switches + +#ifndef Do_Not_Use_GPS + GPS_On(DoGPSPowerSwitch); +#endif + + SPI.begin(); //initialize SPI: + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + pinMode(lora_NReset, OUTPUT); //LoRa Device reset line + pinMode (lora_NSS, OUTPUT); //LoRa Device select line + pinMode (lora_DIO0, INPUT); //LoRa DIO0 pin, used for RX ready + + digitalWrite(lora_NSS, HIGH); + digitalWrite(lora_NReset, HIGH); + delay(1); + + Memory_Start(); + Display_Setup(); + +#ifdef ClearAllMemory + writescreen_9(); + Clear_All_Memory(); +#endif + + +#ifdef ConfigureDefaults + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); +#endif + +#ifdef ConfigureFromMemory + read_Settings_Memory(); +#endif + + +#ifdef write_CalibrationOffset + Memory_WriteInt(addr_CalibrationOffset, CalibrationOffset); +#endif + + read_TRData(); + read_LocalData(); + + if (!lora_CheckDevice()) + { + Serial.println(F("LoRa Error")); + led_Flash(40, 50); + } + + lora_Setup(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial_Setup(); +#endif + + Setup_LoRaTrackerMode(); + + writescreen_8(ramc_TrackerMode_Frequency, ramc_SearchMode_Frequency, SupplyVolts); + +#ifdef CalibrateTone + digitalWrite(LED1, HIGH); //turn on LED + lora_Tone(1000, 3000, 10); //Transmit an FM tone, 1000hz, 1000ms, 10dBm + digitalWrite(LED1, LOW); //LED is off + delay(1000); +#endif + + update_screen(3); + + lora_RXONLoRa(); + +#ifndef Do_Not_Use_GPS + GPS_On(DoGPSPowerSwitch); + GPS_Setup(); + Serial.println(); +#endif + + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial.println("Bluetooth Active"); +#endif + + Function_Number = 1; //start in tracker mode + +} + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/Basic_Receiver_Portable_Settings.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/Basic_Receiver_Portable_Settings.h new file mode 100644 index 0000000..5f5aabb --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/Basic_Receiver_Portable_Settings.h @@ -0,0 +1,217 @@ +//LoRaTracker_Settings.h +/* +****************************************************************************************************** + +LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson - 05/10/2017 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without +the explicit permission of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the +intended purpose and free from errors. + +To Do: + + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board definition file type here +//************************************************************************************************** + +//#define Board_Definition "Locator2_Board_Definitions.h" +//#define Board_Definition "Receiver2_Board_Definitions.h" +//#define Board_Definition "Sensor1_Board_Definitions.h" +//#define Board_Definition "RFM98_Shield_January2016_Board_Definitions.h" +//#define Board_Definition "MicroRX_Board_Definitions.h" +#define Board_Definition "LCD_Receiver_Board_Definitions.h" + + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +#define ConfigureDefaults //Configure settings from default program defaults, needs to be run at least once, cleared if bind is run +//#define ClearAllMemory //Clears from start memory to end memory, normally 1kbyte, needs to be followed by ConfigureDefaults +//#define ConfigureFromMemory //Configure settings from values stored in memory, this needs to be the active mode for bind to work + +#define CalibrateTone //comment in to have a calibrate tone at startup + +//#define DEBUG //if defined debug mode used, results in more diagnostics to serial terminal +#define ReceiveBind //during flight allows for a bind to be received + + + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 434400000; + +//Search mode +const unsigned long SearchMode_Frequency = 434400000; + +//Bind mode - Change this with great care !!!!! +const unsigned long BindMode_Frequency = 434100000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 0; + + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +#define LoRa_Device_in_MB1 //if using a MikroBus based board specify the socket for the LoRa Device + +//Tracker mode +const byte TrackerMode_Power = 10; +#define TrackerMode_Bandwidth BW62500 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 + +//Search mode +const byte SearchMode_Power = 10; +#define SearchMode_Bandwidth BW62500 +#define SearchMode_SpreadingFactor SF12 +#define SearchMode_CodeRate CR45 + + +//Bind mode - Change this with great care !!!!! +const byte BindMode_Power = 2; +#define BindMode_Bandwidth BW500000 +#define BindMode_SpreadingFactor SF8 +#define BindMode_CodeRate CR45 + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 128; +const byte lora_TXBUFF_Size = 1; + + +//#define RemoteControlNode 'G' //normally used by tracker transmitter in promiscuous_Mode +//#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +//#define ThisNode ControlledNode + +//#define LORADEBUG //displays extra debug messages when using LoRa + +//Protected Command Settings +const char key0 = 'L'; //Used to restrict access to some commands, such as bind +const char key1 = 'o'; +const char key2 = 'R'; +const char key3 = 'a'; + +//#define No_DIO0_RX_Ready //needed for boards that cannot directly ready the DIO0 pin + + +//************************************************************************************************** +// 5) GPS Options +//************************************************************************************************** + + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +#define GPS_in_MB2 //if using a MikroBus based board specify the socket for the GPS +//#define GPS_Library "UBLOX_SerialGPS2.h" //define this file if a UBLOX GPS is being used +//#define GPS_Library "No_GPS.h" //define this file if no GPS is being used +#define GPS_Library "Generic_SerialGPS.h" //define this file if generic GPS such as Mediatek is being used + + +//#define Do_Not_Use_GPS //test mode, does not use GPS used test location instead +//#define Use_Test_Location //uses test location for local position, so you can take pictures without revealing your location +//#define GPS_ALLOW_GPGSV //define this so that GPGSV are seen on UBLOX GPS + +const unsigned int GPSBaud = 9600; +#define WhenNoGPSFix LeaveOn //What to do with GPS power when there is no fix at ends of wait period (LeaveOn or LeaveOff) +const byte WaitGPSFixSeconds = 30; //in flight mode time to wait for a new GPS fix + +const byte GPS_attempts = 3; //number of times the sending of GPS config will be attempted. +const unsigned int GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const byte GPS_Reply_Size = 12; //size of GPS reply buffer +const unsigned int GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent + +const unsigned long FixisoldmS = 10000; //if location has not updated in this number of mS, assume GPS has lost fix +const unsigned int GPSFixes = 100; //number of GPS fixes between setting system clock from GPS + + + +//Centre of Cardiff Castle keep +//const float TestLatitude = 51.48230; +//const float TestLongitude = -3.18136; +//const unsigned int TestAltitude = 48; + + + +//Passive GPS station: Swanbridge - C1ST1667 +//https://www.ordnancesurvey.co.uk/gps/legacy-control-information/C1ST1667 +//N 51 23'59.105955", W 3 11',47.413031 +//51.399751654166664, -3.196503619722222 +const float TestLatitude = 51.399752; +const float TestLongitude = -3.196504; +const unsigned int TestAltitude = 2; + + +//************************************************************************************************** +// 6) Which Memory to use for settings storage +//************************************************************************************************** + +//#define Memory_Library "I2CFRAM_MB85RC16PNF.h" //define this file if a I2C FRAM is in use +#define Memory_Library "EEPROM_Memory.h" //define this file if the EEPROM is being used for memory - not recommended for portable receiver + + + +//************************************************************************************************** +// 7) Display Settings - Need to define a library to use and screens +//************************************************************************************************** + +#define Display_Library "Display_I2C_LCD2.h" //This is the 20x4 LCD display, driven by a PCF8574 backpack +#define Display_Screens "I2C_LCD_20x4_Screens.h" //use the I2C LCD Screens, 20x4 +const int PCF8574Address = 0x3F; //I2C address of the PCF8574, this define allows the address to be specified, normally 0x27 or 0x3F + +//#define Display_Library "Display_I2CBackPack.h" //This is the LoRaTracker I2C connected display backpack. +//#define Display_Screens "I2CDisplay_Screens_ILI9341.h" //use the screens for the ILI9341 which needs to be connected to the backpack +//const int Display_Address = 0x08; //I2C address of the backpack + + +//#define Display_Library "Display_SD1306_AVR.h" //use an SSD1306 I2C display +//#define Display_Screens "SD1306_SMALL_TEXT_Screens.h" //use small text on display, more information +//#define Display_Screens "SD1306_LARGE_TEXT_Screens.h" //use large text on screen, easier to read +//const int I2C_ADDRESS = 0x3C; //address of SD13206 will be 0x3C or 0x3D + + +//************************************************************************************************** +// 9) AFSK RTTY Options +//************************************************************************************************** + +#define USE_AFSK_RTTY_Upload +const int AFSKrttybaud = 1465; //delay in uS x 2 for 1 bit and 300baud. Decode range in FLDIGI 1420 to 1510 +const int afskleadinmS = 500; //number of ms for AFSK constant lead in tone +const int tonehighHz = 1000; //high tone in Hertz +const int tonelowHz = 650; //low tone in Hertz + + +//************************************************************************************************** +// 10) Bluetooth Options +//************************************************************************************************** + +//#define Use_NMEA_Bluetooth_Uplink +#define USE_HardwareSerial //use hardware serial port to send Bluetooth +#define Hardware_Bluetooth_Port Serial //Which Hardware port to use for Bluetooth +//#define USE_SendOnlySoftwareSerial + + +#define BluetoothBaud 9600 +const byte Bluetooth_Buff_Size = 128; //size of buffer for NMEA output + + +//************************************************************************************************** +// 12) Miscellaneous program settings +//************************************************************************************************** + +const unsigned int switch_delay = 1000; //delay in mS after a switch press before another can take place diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/I2CDisplay_Screens_ILI9341.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/I2CDisplay_Screens_ILI9341.h new file mode 100644 index 0000000..ec99352 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/I2CDisplay_Screens_ILI9341.h @@ -0,0 +1,436 @@ +//Portable_Screens_Small.h +/* +************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 05/08/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + These screens are for a ILI9341 320 x 240 display, in text size 3 this is 18 columnd x 10 rows + + To Do: + +************************************************************************************************** +*/ + + +void writescreen_1(); //tracker mode receive screen +void writescreen_2(); //search mode receive screen +void writescreen_3(); //tracker location screen +void writescreen_4(); //local location screen +void writescreen_5(); //send bind screen +void writescreen_6(); //receive bind screen +void writescreen_7(); //test packet screen +void writescreen_8(uint32_t f1, uint32_t f2, int volts); //frequencies screen +void writescreen_9(); //memory clear +void writescreen_Alert1(); //GLONASS warning +void writescreen_Alert2(); //bind received +void writescreen_Alert4(); //no tracker GPS fix +void writescreen_Alert5(unsigned int battvolts); +void writescreen_Alert7(); //bind rejected +void writescreen_Alert8(); //memory clear +void writescreen_Alert9(); //tracker GPS error +void writescreen_Alert10(); //tracker lost +void Display_Setup(); //needed by some programs + +void writeSNR(byte col, byte row); +void revert_Screen(); +void add_Tracker_Location(); +void add_Tracker_DD(); + +unsigned int writePktCount(byte col, byte row, unsigned int packetcount); +byte current_screen_number = 1; + + +/****************************************************** + Screens +*******************************************************/ + + +void update_screen(byte screennumber) +{ + switch (screennumber) + { + case 1: + writescreen_1(); + break; + + case 2: + writescreen_2(); + break; + + case 3: + writescreen_3(); + break; + + case 4: + writescreen_4(); + break; + + case 5: + writescreen_5(); + break; + + default: + break; + } +} + + +void writescreen_1() +{ + Display_SetTextSize(2); + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + Display_SetCurPos(0, 3); + add_Tracker_DD(); + } + + writeSNR(0, 4); + Display_SetCurPos(0, 5); + disp.print(F("Tracker Pkts ")); + disp.print(TrackerMode_Packets); + disp.print(F(" ")); + Display_Update; +} + + +void writescreen_2() +{ + Display_SetTextSize(2); + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + Display_SetCurPos(0, 3); + add_Tracker_DD(); + } + + writeSNR(0, 4); + Display_SetCurPos(0, 5); + disp.print(F("Search Pkts ")); + disp.print(SearchMode_Packets); + disp.print(F(" ")); + Display_Update; +} + + +void writescreen_3() +{ + //This displays last received tracker co-ordinates stored in memory; + Display_SetTextSize(2); + Display_Clear(); + add_Tracker_Location(); + Display_SetCurPos(0, 5); + disp.print(F("Last Tracker Fix")); + Display_Update(); +} + + +void writescreen_4() +{ + //This displays last Local co-ordinates from memory; + Display_SetTextSize(2); + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("LAT ")); + disp.print(LocalLat, 6); + Display_SetCurPos(0, 1); + disp.print(F("LON ")); + disp.print(LocalLon, 6); + Display_SetCurPos(0, 2); + disp.print(F("Alt ")); + disp.print(LocalAlt); + Display_SetCurPos(0, 5); + disp.print(F("Last Local Fix ")); + Display_Update(); +} + + + +void writescreen_5() +{ + Display_SetTextSize(2); + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Receive Bind")); + Display_Update(); +} + + +void writescreen_7() +{ + byte tempbyte, tempbyte1, power; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print("Test Packet "); + Display_SetCurPos(0, 1); + disp.print("Power "); + tempbyte = lora_RXBUFF[0] - 48; //convert ASCII to number + tempbyte1 = lora_RXBUFF[1] - 48; //convert ASCII to number + power = (tempbyte * 10) + tempbyte1; + disp.print(power); + disp.print("dBm"); + writeSNR(0, 4); + delay(750); //so we have enough time to see packet on screen + Display_Update(); +} + + +void writescreen_8(uint32_t f1, uint32_t f2, int volts) +{ + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Locator2")); + Display_SetCurPos(0, 2); + disp.print(F("Tracker ")); + disp.print(f1); + Display_SetCurPos(0, 3); + disp.print(F("Search ")); + disp.print(f2); + Display_SetCurPos(0, 5); + disp.print(volts); + disp.print(F("mV")); + delay(750); //so we have enough time to see packet on screen + Display_Update(); +} + + +void writescreen_9() +{ + Display_Clear(); + Display_SetCurPos(0, 0); + disp.println(F("Memory Clear")); + disp.println(F("Press SWITCH1")); + Display_Update(); +} + +void add_Tracker_DD() +{ +float temp; + +if (TRdistance < 1000) + { + disp.print(TRdistance, 0); + disp.print(F("M")); + } + else if (TRdistance < 10000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 2); + disp.print(("Km")); + } + else if (TRdistance < 100000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 1); + disp.print(("Km")); + } + else + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 0); + disp.print(("Km")); + } + + disp.print(F(" ")); + disp.print(TRdirection); + disp.print(F("D")); +} + + +void add_Tracker_Location() +{ + Display_SetCurPos(18, 0); + + if (Local_GPS_Fix) + { + disp.print(F("G")); + } + else + { + disp.print(F("?")); + } + + Display_SetCurPos(0, 0); + disp.print(F("LAT ")); + disp.print(TRLat, 6); + disp.print(F(" ")); + Display_SetCurPos(0, 1); + disp.print(F("LON ")); + disp.print(TRLon, 6); + disp.print(F(" ")); + Display_SetCurPos(0, 2); + disp.print(F("Alt ")); + disp.print(TRAlt); + disp.print(F("M ")); +} + + +void writeSNR(byte col, byte row) +{ + if (lora_RXpacketCount) //if no packets do not display SNR + { + Display_SetTextSize(2); + Display_SetCurPos(col, row); + disp.print(F("SNR ")); + disp.print(lora_PacketSNR); //now print the SNR + disp.print(F("dB")); + } + +} + + +unsigned int writePktCount(byte col, byte row, unsigned int packetcount) +{ + //now print the last two digits of lora_RXpacketCount so we can see if packets are arriving + + if (packetcount > 0) //if no packets do not display count + { + if (packetcount > 999) + { + packetcount = 1; + } + Display_SetTextSize(2); + Display_SetCurPos(col, row); //cursor to last two cols of bottom line + disp.print(packetcount); //send count 0-999 to LCD + } + return packetcount; +} + + +void writescreen_Alert1() +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 2); + disp.print(F("GLONASS NMEA")); + Display_SetCurPos(0, 3); + disp.print(F(" Detected ")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert2() +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Accepted")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert4() +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" No Tracker")); + Display_SetCurPos(0, 3); + disp.print(F(" GPS Fix")); + Display_Update(); + delay(750); +} + + +void writescreen_Alert5(unsigned int supplyvolts) +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 0); + disp.print(F("Power Up")); + Display_SetCurPos(0, 2); + disp.print(F("Batt ")); + disp.print(supplyvolts); + disp.print(F("mV")); + Display_SetCurPos(0, 5); + disp.print(F("Tracker")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert7() +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Rejected")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert8() +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Memory Clear ")); + Display_Update(); + delay(1500); +} + +void writescreen_Alert9() +{ + Display_SetTextSize(2); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Tracker")); + Display_SetCurPos(0, 3); + disp.print(F(" GPS Error")); + Display_Update(); +} + + +void writescreen_Alert10() +{ + Display_Clear(); //set large font and clear + Display_SetTextSize(2); + Display_SetCurPos(3, 1); + disp.print(F("Tracker")); + Display_SetCurPos(1, 3); + disp.print(F("Lost")); + Display_Update(); +} + + +void revert_Screen() +{ + if (current_screen_number == 1) + { + writescreen_1(); + } + + if (current_screen_number == 2) + { + writescreen_2(); + } + delay(1000); //leave screen up for a while +} + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/I2C_LCD_20x4_Screens.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/I2C_LCD_20x4_Screens.h new file mode 100644 index 0000000..ea6b96e --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/I2C_LCD_20x4_Screens.h @@ -0,0 +1,424 @@ +//I2C_20x4_LCD_Screens.h +/* +************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 05/08/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + To Do: + +************************************************************************************************** +*/ + + +void writescreen_1(); //tracker mode receive screen +void writescreen_2(); //search mode receive screen +void writescreen_3(); //tracker location screen +void writescreen_4(); //local location screen +void writescreen_5(); //send bind screen +void writescreen_6(); //receive bind screen +void writescreen_7(); //test packet screen +void writescreen_8(uint32_t f1, uint32_t f2, uint32_t f3, int volts); +void writescreen_9(); //memory clear +void writescreen_Alert1(); //GLONASS warning +void writescreen_Alert2(); //bind received +void writescreen_Alert4(); //no tracker GPS fix +void writescreen_Alert5(unsigned int battvolts); +void writescreen_Alert7(); //bind rejected +void writescreen_Alert8(); //memory clear +void writescreen_Alert9(); //tracker GPS error +void writescreen_Alert10(); //tracker lost + +void writeSNR(byte col, byte row); +void revert_Screen(); +void add_Tracker_Location(); +void add_Tracker_DD(); +void Display_Status(); + +void writePktCount(byte col, byte row, unsigned int packetcount); + +byte current_screen_number = 1; + +/****************************************************** + Screens +*******************************************************/ + + +void update_screen(byte screennumber) +{ + switch (screennumber) + { + case 1: + writescreen_1(); + break; + + case 2: + writescreen_2(); + break; + + case 3: + writescreen_3(); + break; + + case 4: + writescreen_4(); + break; + + case 5: + writescreen_5(); + break; + + default: + break; + } +} + + +void writescreen_1() +{ + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + add_Tracker_DD(); + } + + Display_SetCurPos(16, 3); + disp.print(F("TR")); + Display_Status(); + writeSNR(0,3); + writePktCount(12,3,lora_RXpacketCount); +} + + +void Display_Status() +{ + if (Local_GPS_Fix) + { + disp.print(F("G")); + } + else + { + disp.print(F("?")); + } + + if (bitRead(TRStatus,TrackerLost)) + { + disp.print(F("L")); + } + +} + + +void writescreen_2() +{ + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + add_Tracker_DD(); + } + + Display_SetCurPos(16, 3); + disp.print(F("SE")); + Display_Status(); + writeSNR(0,3); + writePktCount(12,3,lora_RXpacketCount); +} + + +void writescreen_3() +{ + //This displays last received tracker co-ordinates stored in memory; + Display_Clear(); + add_Tracker_Location(); + Display_SetCurPos(0, 3); + disp.print(F("Last Tracker Fix")); + Display_Update(); +} + + +void writescreen_4() +{ + //This displays last Local co-ordinates from memory; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("LAT ")); + disp.print(LocalLat, 6); + Display_SetCurPos(0, 1); + disp.print(F("LON ")); + disp.print(LocalLon, 6); + Display_SetCurPos(0, 2); + disp.print(F("Alt ")); + disp.print(LocalAlt); + Display_SetCurPos(0, 3); + disp.print(F("Last Local Fix")); + + Display_Update(); +} + + + +void writescreen_5() +{ + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Receive Bind")); + Display_Update(); +} + + +void writescreen_7() +{ + byte tempbyte, tempbyte1, power; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print("Test Packet "); + Display_SetCurPos(0, 1); + disp.print("Power "); + tempbyte = lora_RXBUFF[0] - 48; //convert ASCII to number + tempbyte1 = lora_RXBUFF[1] - 48; //convert ASCII to number + power = (tempbyte * 10) + tempbyte1; + disp.print(power); + disp.print("dBm"); + writeSNR(0, 3); + delay(750); //so we have enough time to see packet on screen + Display_Clear(); +} + + + +void writescreen_8(uint32_t f1, uint32_t f2, int volts) +{ + //float tempfloat; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Locator2")); + Display_SetCurPos(0, 1); + disp.print(F("Tracker ")); + disp.print(f1); + Display_SetCurPos(0, 2); + disp.print(F("Search ")); + disp.print(f2); + Display_SetCurPos(0, 3); + disp.print(volts); + disp.print(F("mV")); + Display_Update(); +} + + +void writescreen_9() +{ + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Memory Clear")); + Display_Update(); + delay(1000); +} + + +void add_Tracker_DD() +{ + float temp; + Display_SetCurPos(0, 2); + if (TRdistance < 1000) + { + disp.print(TRdistance, 0); + disp.print(F("M")); + } + else if (TRdistance < 10000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 1); + disp.print(("K")); + } + else if (TRdistance < 100000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 0); + disp.print(("Km")); + } + else + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 0); + disp.print(("K")); + } + + disp.print(F(" ")); + disp.print(TRdirection); + disp.print(F("D")); +} + + +void add_Tracker_Location() +{ + //prints the tracker lat, long and alt + Display_SetCurPos(0, 0); + disp.print(F("LAT ")); + disp.print(TRLat, 5); //5 decimal places is enough, gives location to the nearest approx 10M + Display_SetCurPos(0, 1); + disp.print(F("LON ")); + disp.print(TRLon, 5); + Display_SetCurPos(14, 0); + disp.print(TRAlt); + disp.print("M "); +} + + + +void writeSNR(byte col, byte row) +{ + if (lora_RXpacketCount) //if no packets do not display SNR + { + + Display_SetCurPos(col, row); + disp.print(F("SNR ")); + disp.print(lora_PacketSNR); //now print the SNR + disp.print(F("dB")); + } + +} + + +void writePktCount(byte col, byte row, unsigned int packetcount) +{ + Display_SetCurPos(col, row); //cursor to last position + disp.print(packetcount); //send count to LCD +} + + +void writescreen_Alert1() +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 2); + disp.print(F("GLONASS NMEA")); + Display_SetCurPos(0, 3); + disp.print(F(" Detected ")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert2() +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Accepted")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert4() +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(5, 1); + disp.print(F("No Tracker")); + Display_SetCurPos(5, 2); + disp.print(F("GPS Fix")); + delay(750); + Display_Update(); +} + + +void writescreen_Alert5(unsigned int supplyvolts) +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 0); + disp.print(F("Power Up")); + Display_SetCurPos(0, 2); + disp.print(F("Batt ")); + disp.print(supplyvolts); + disp.print(F("mV")); + Display_SetCurPos(0, 3); + disp.print(F("Tracker")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert7() +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Rejected")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert8() +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Memory Clear ")); + delay(1500); +} + + +void writescreen_Alert9() +{ + //Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Tracker")); + Display_SetCurPos(0, 3); + disp.print(F(" GPS Error")); + Display_Update(); +} + + +void writescreen_Alert10() +{ + Display_Clear(); //set large font and clear + Display_SetCurPos(7, 1); + disp.print(F("Tracker")); + Display_SetCurPos(7, 2); + disp.print(F("Lost")); + Display_Update(); +} + + + +void revert_Screen() +{ + if (current_screen_number == 1) + { + writescreen_1(); + } + + if (current_screen_number == 2) + { + writescreen_2(); + } + delay(1000); //leave screen up for a while +} + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/SD1306_LARGE_TEXT_Screens.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/SD1306_LARGE_TEXT_Screens.h new file mode 100644 index 0000000..39fa088 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/SD1306_LARGE_TEXT_Screens.h @@ -0,0 +1,434 @@ +//Portable_Screens_Large.h +/* +************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 05/08/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + To Do: + +************************************************************************************************** +*/ + + +void writescreen_1(); //tracker mode receive screen +void writescreen_2(); //search mode receive screen +void writescreen_3(); //tracker location screen +void writescreen_4(); //local location screen +void writescreen_5(); //send bind screen +void writescreen_6(); //receive bind screen +void writescreen_7(); //test packet screen +void writescreen_8(uint32_t f1, uint32_t f2, int volts); +void writescreen_9(); +void writescreen_Alert1(); //GLONASS warning +void writescreen_Alert2(); //bind received +//void writescreen_Alert3(); //bind accepted +void writescreen_Alert4(); // +void writescreen_Alert5(unsigned int battvolts); +void writescreen_Alert7(); //bind rejected +void writescreen_Alert8(); +void writescreen_Alert9(); +void writescreen_Alert10(); //tracker lost + +void writeSNR(byte col, byte row); +void revert_Screen(); +void add_Tracker_Location(); +void add_Tracker_DD(); +void Display_Status(); + +unsigned int writePktCount(byte col, byte row, unsigned int packetcount); +byte current_screen_number = 1; + +/****************************************************** + Screens +*******************************************************/ + + +void update_screen(byte screennumber) +{ + switch (screennumber) + { + case 1: + writescreen_1(); + break; + + case 2: + writescreen_2(); + break; + + case 3: + writescreen_3(); + break; + + case 4: + writescreen_4(); + break; + + case 5: + writescreen_5(); + break; + + default: + break; + } +} + + +void writescreen_1() +{ + Display_SetTextSize(2); + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + add_Tracker_DD(); + } + + Display_SetCurPos(15, 4); + disp.print(F("TR")); + Display_Status(); + +} + + +void Display_Status() +{ + if (Local_GPS_Fix) + { + disp.print(F("G")); + } + else + { + disp.print(F("?")); + } +} + + +void writescreen_2() +{ + Display_SetTextSize(2); + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + add_Tracker_DD(); + } + + Display_SetCurPos(15, 4); + disp.print(F("SE")); + Display_Status(); +} + + +void writescreen_3() +{ + //This displays last received tracker co-ordinates stored in memory; + Display_SetTextSize(1); + Display_Clear(); + //add_Tracker_Location(); + Display_SetCurPos(0, 0); + disp.print(F("LA ")); + disp.print(TRLat, 6); + Display_SetCurPos(0, 1); + disp.print(F("LO ")); + disp.print(TRLon, 6); + Display_SetCurPos(0, 2); + disp.print(F("Alt ")); + disp.print(TRAlt); + Display_SetCurPos(0, 5); + disp.print(F("Last Tracker Fix")); + Display_Update(); +} + + +void writescreen_4() +{ + //This displays last Local co-ordinates from memory; + Display_SetTextSize(1); + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("LA ")); + disp.print(LocalLat, 6); + Display_SetCurPos(0, 1); + disp.print(F("LO ")); + disp.print(LocalLon, 6); + Display_SetCurPos(0, 2); + disp.print(F("Alt ")); + disp.print(LocalAlt); + Display_SetCurPos(0, 5); + disp.print(F("Last Local Fix")); + Display_Update(); +} + + + +void writescreen_5() +{ + Display_SetTextSize(1); + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Receive Bind")); + Display_Update(); +} + + +void writescreen_7() +{ + byte tempbyte, tempbyte1, power; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print("Test "); + Display_SetCurPos(0, 1); + tempbyte = lora_RXBUFF[0] - 48; //convert ASCII to number + tempbyte1 = lora_RXBUFF[1] - 48; //convert ASCII to number + power = (tempbyte * 10) + tempbyte1; + disp.print(power); + disp.print("dBm"); + writeSNR(0, 3); + delay(750); //so we have enough time to see packet on screen + Display_Clear(); +} + + +void writescreen_8(uint32_t f1, uint32_t f2, int volts) +{ + //float tempfloat; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Locator2")); + Display_SetCurPos(0, 2); + disp.print(F("Trk ")); + disp.print(f1); + Display_SetCurPos(0, 3); + disp.print(F("Ser ")); + disp.print(f2); + Display_SetCurPos(0, 5); + disp.print(volts); + disp.print(F("mV")); + Display_Update(); +} + + +void writescreen_9() +{ + //float tempfloat; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.println(F("Memory Clear")); + disp.println(F("Press SWITCH1")); + Display_Update(); +} + +void add_Tracker_DD() +{ +float temp; +Display_SetCurPos(0, 6); +if (TRdistance < 1000) + { + disp.print(TRdistance, 0); + disp.print(F("M")); + } + else if (TRdistance < 10000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 1); + disp.print(("K")); + } + else if (TRdistance < 100000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 0); + disp.print(("Km")); + } + else + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 0); + disp.print(("K")); + } + + disp.print(F(" ")); + disp.print(TRdirection); + disp.print(F("D")); +} + + +void add_Tracker_Location() +{ + //prints the tracker lat, long and alt + Display_SetCurPos(0, 0); + disp.print(TRLat, 5); //5 decimal places is enough, gives location to the nearest approx 10M + Display_SetCurPos(0, 2); + disp.print(TRLon, 5); + Display_SetCurPos(0, 4); + disp.print(TRAlt); + disp.print("M "); +} + + +void writeSNR(byte col, byte row) +{ + if (lora_RXpacketCount) //if no packets do not display SNR + { + Display_SetTextSize(1); + Display_SetCurPos(col, row); + + disp.print(lora_PacketSNR); //now print the SNR + disp.print(F("dB")); + } + +} + + +unsigned int writePktCount(byte col, byte row, unsigned int packetcount) +{ + //now print the last two digits of lora_RXpacketCount so we can see if packets are arriving + if (packetcount > 0) //if no packets do not display count + { + if (packetcount > 999) + { + packetcount = 1; + } + Display_SetTextSize(1); + Display_SetCurPos(col, row); //cursor to last two cols of bottom line + disp.print(packetcount); //send count 0-999 to LCD + } + return packetcount; +} + + +void writescreen_Alert1() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 2); + disp.print(F("GLONASS NMEA")); + Display_SetCurPos(0, 3); + disp.print(F(" Detected ")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert2() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Accepted")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert4() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" No Tracker")); + Display_SetCurPos(0, 3); + disp.print(F(" GPS Fix")); + delay(750); + Display_Update(); +} + + +void writescreen_Alert5(unsigned int supplyvolts) +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 0); + disp.print(F("Power Up")); + Display_SetCurPos(0, 2); + disp.print(F("Batt ")); + disp.print(supplyvolts); + disp.print(F("mV")); + Display_SetCurPos(0, 5); + disp.print(F("Tracker")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert7() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Rejected")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert8() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Memory Clear ")); + delay(1500); +} + + +void writescreen_Alert9() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(3, 1); + disp.print(F("Tracker")); + Display_SetCurPos(1, 3); + disp.print(F("GPS Error")); + Display_Update(); +} + + +void writescreen_Alert10() +{ + Display_Clear(); //set large font and clear + Display_SetTextSize(1); + Display_SetCurPos(3, 1); + disp.print(F("Tracker")); + Display_SetCurPos(1, 3); + disp.print(F("Lost")); + Display_Update(); +} + + + +void revert_Screen() +{ + if (current_screen_number == 1) + { + writescreen_1(); + } + + if (current_screen_number == 2) + { + writescreen_2(); + } + delay(1000); //leave screen up for a while +} + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/SD1306_SMALL_TEXT_Screens.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/SD1306_SMALL_TEXT_Screens.h new file mode 100644 index 0000000..967416f --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Portable_011217/SD1306_SMALL_TEXT_Screens.h @@ -0,0 +1,433 @@ +//Portable_Screens_Small.h +/* +************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 05/08/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + To Do: + +************************************************************************************************** +*/ + + +void writescreen_1(); //tracker mode receive screen +void writescreen_2(); //search mode receive screen +void writescreen_3(); //tracker location screen +void writescreen_4(); //local location screen +void writescreen_5(); //send bind screen +void writescreen_6(); //receive bind screen +void writescreen_7(); //test packet screen +void writescreen_8(uint32_t f1, uint32_t f2, int volts); +void writescreen_9(); +void writescreen_Alert1(); //GLONASS warning +void writescreen_Alert2(); //bind received +//void writescreen_Alert3(); //bind accepted +void writescreen_Alert4(); // +void writescreen_Alert5(unsigned int battvolts); +//void writescreen_Alert6(); //No SD Card +void writescreen_Alert7(); //bind rejected +void writescreen_Alert8(); +void writescreen_Alert9(); +void writescreen_Alert10(); //tracker lost + + +void writeSNR(byte col, byte row); +void revert_Screen(); +void add_Tracker_Location(); +void add_Tracker_DD(); + +unsigned int writePktCount(byte col, byte row, unsigned int packetcount); +byte current_screen_number = 1; + +/****************************************************** + Screens +*******************************************************/ + + +void update_screen(byte screennumber) +{ + switch (screennumber) + { + case 1: + writescreen_1(); + break; + + case 2: + writescreen_2(); + break; + + case 3: + writescreen_3(); + break; + + case 4: + writescreen_4(); + break; + + case 5: + writescreen_5(); + break; + + default: + break; + } +} + + +void writescreen_1() +{ + Display_SetTextSize(1); + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + Display_SetCurPos(0, 3); + add_Tracker_DD(); + } + + writeSNR(0, 4); + Display_SetCurPos(0, 5); + disp.print(F("Tracker ")); + disp.print(TrackerMode_Packets); + Display_Update(); +} + + + +void writescreen_2() +{ + Display_SetTextSize(1); + Display_Clear(); + add_Tracker_Location(); + + if (Local_GPS_Fix) + { + Display_SetCurPos(0, 3); + add_Tracker_DD(); + } + + writeSNR(0, 4); + Display_SetCurPos(0, 5); + disp.print(F("Search ")); + disp.print(SearchMode_Packets); + Display_Update(); +} + + +void writescreen_3() +{ + //This displays last received tracker co-ordinates stored in memory; + Display_SetTextSize(1); + Display_Clear(); + add_Tracker_Location(); + Display_SetCurPos(0, 5); + disp.print(F("Last Tracker Fix")); + Display_Update(); +} + + +void writescreen_4() +{ + //This displays last Local co-ordinates from memory; + Display_SetTextSize(1); + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("LA ")); + disp.print(LocalLat, 6); + Display_SetCurPos(0, 1); + disp.print(F("LO ")); + disp.print(LocalLon, 6); + Display_SetCurPos(0, 2); + disp.print(F("Alt ")); + disp.print(LocalAlt); + Display_SetCurPos(0, 5); + disp.print(F("Last Local Fix")); + + Display_Update(); +} + + + +void writescreen_5() +{ + Display_SetTextSize(1); + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Receive Bind")); + Display_Update(); +} + + +void writescreen_7() +{ + byte tempbyte, tempbyte1, power; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print("Test Packet "); + Display_SetCurPos(0, 1); + disp.print("Power "); + tempbyte = lora_RXBUFF[0] - 48; //convert ASCII to number + tempbyte1 = lora_RXBUFF[1] - 48; //convert ASCII to number + power = (tempbyte * 10) + tempbyte1; + disp.print(power); + disp.print("dBm"); + writeSNR(0, 3); + delay(750); //so we have enough time to see packet on screen + Display_Clear(); +} + + +void writescreen_8(uint32_t f1, uint32_t f2, int volts) +{ + //float tempfloat; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.print(F("Locator2")); + Display_SetCurPos(0, 2); + disp.print(F("Trk ")); + disp.print(f1); + Display_SetCurPos(0, 3); + disp.print(F("Ser ")); + disp.print(f2); + Display_SetCurPos(0, 5); + disp.print(volts); + disp.print(F("mV")); + Display_Update(); +} + + +void writescreen_9() +{ + //float tempfloat; + Display_Clear(); + Display_SetCurPos(0, 0); + disp.println(F("Memory Clear")); + disp.println(F("Press SWITCH1")); + Display_Update(); +} + +void add_Tracker_DD() +{ +float temp; + +if (TRdistance < 1000) + { + disp.print(TRdistance, 0); + disp.print(F("M")); + } + else if (TRdistance < 10000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 2); + disp.print(("Km")); + } + else if (TRdistance < 100000) + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 1); + disp.print(("Km")); + } + else + { + temp = (float)(TRdistance / 1000); + disp.print(temp, 0); + disp.print(("Km")); + } + + disp.print(F(" ")); + disp.print(TRdirection); + disp.print(F("D")); +} + + +void add_Tracker_Location() +{ + Display_SetCurPos(18, 0); + + if (Local_GPS_Fix) + { + disp.print(F("G")); + } + else + { + disp.print(F("?")); + } + + Display_SetCurPos(0, 0); + disp.print(F("LA ")); + disp.print(TRLat, 6); + Display_SetCurPos(0, 1); + disp.print(F("LO ")); + disp.print(TRLon, 6); + Display_SetCurPos(0, 2); + disp.print(F("AL ")); + disp.print(TRAlt); + disp.print(F("M")); +} + + +void writeSNR(byte col, byte row) +{ + if (lora_RXpacketCount) //if no packets do not display SNR + { + Display_SetTextSize(1); + Display_SetCurPos(col, row); + disp.print(F("SNR ")); + disp.print(lora_PacketSNR); //now print the SNR + disp.print(F("dB")); + } + +} + + +unsigned int writePktCount(byte col, byte row, unsigned int packetcount) +{ + //now print the last two digits of lora_RXpacketCount so we can see if packets are arriving + + if (packetcount > 0) //if no packets do not display count + { + if (packetcount > 999) + { + packetcount = 1; + } + Display_SetTextSize(1); + Display_SetCurPos(col, row); //cursor to last two cols of bottom line + disp.print(packetcount); //send count 0-999 to LCD + } + return packetcount; +} + + +void writescreen_Alert1() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 2); + disp.print(F("GLONASS NMEA")); + Display_SetCurPos(0, 3); + disp.print(F(" Detected ")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert2() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Accepted")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert4() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" No Tracker")); + Display_SetCurPos(0, 3); + disp.print(F(" GPS Fix")); + delay(750); + Display_Update(); +} + + +void writescreen_Alert5(unsigned int supplyvolts) +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 0); + disp.print(F("Power Up")); + Display_SetCurPos(0, 2); + disp.print(F("Batt ")); + disp.print(supplyvolts); + disp.print(F("mV")); + Display_SetCurPos(0, 5); + disp.print(F("Tracker")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert7() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Bind")); + Display_SetCurPos(0, 3); + disp.print(F(" Rejected")); + Display_Update(); + delay(1500); + revert_Screen(); +} + + +void writescreen_Alert8() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Memory Clear ")); + delay(1500); +} + +void writescreen_Alert9() +{ + Display_SetTextSize(1); + Display_Clear(); //set large font and clear + Display_SetCurPos(0, 1); + disp.print(F(" Tracker")); + Display_SetCurPos(0, 3); + disp.print(F(" GPS Error")); + Display_Update(); +} + + +void writescreen_Alert10() +{ + Display_Clear(); //set large font and clear + Display_SetTextSize(1); + Display_SetCurPos(3, 1); + disp.print(F("Tracker")); + Display_SetCurPos(1, 3); + disp.print(F("Lost")); + Display_Update(); +} + + +void revert_Screen() +{ + if (current_screen_number == 1) + { + writescreen_1(); + } + + if (current_screen_number == 2) + { + writescreen_2(); + } + delay(1000); //leave screen up for a while +} + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/Basic_Receiver_Terminal_151117.ino b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/Basic_Receiver_Terminal_151117.ino new file mode 100644 index 0000000..98ad455 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/Basic_Receiver_Terminal_151117.ino @@ -0,0 +1,1739 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the Basic_Receiver_Terminal_Settingsfile not here ! +// +//************************************************************************************************** + +#define programname "Basic_Receiver_Terminal_151117" +#define programversion "V1.1" +#define aurthorname "Stuart Robinson - www.LoRaTracker.uk" + +#include +#include + +#include "Program_Definitions.h" +#include "Basic_Receiver_Terminal_Settings.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To do: + Check function of enter_CalibrationOffset() + + ****************************************************************************************************** +*/ + + +//Program Variables +int ramc_CalibrationOffset; //adjustment for frequency in Hertz + +unsigned long ramc_TrackerMode_Frequency; //Initial default for FlightFrequency +byte ramc_TrackerMode_Bandwidth; //used to keep Tracker mode settings +byte ramc_TrackerMode_SpreadingFactor; +byte ramc_TrackerMode_CodeRate; +byte ramc_TrackerMode_Power; + +unsigned long ramc_SearchMode_Frequency; //Initial default for FlightFrequency +byte ramc_SearchMode_Bandwidth; //used to keep Searc mode settings +byte ramc_SearchMode_SpreadingFactor; +byte ramc_SearchMode_CodeRate; +byte ramc_SearchMode_Power; + +unsigned long ramc_CommandMode_Frequency; //Initial default for command and reporting frequency +byte ramc_CommandMode_Bandwidth; //used to keep Command mode settings +byte ramc_CommandMode_SpreadingFactor; +byte ramc_CommandMode_CodeRate; +byte ramc_CommandMode_Power; + + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; +unsigned int TResets; //keeps the count of remote tracker resets +byte TRStatus; //Status byte from tracker binary payload +byte TRSats; //last received number of GPS satellites from tracker +boolean Remote_GPS_Fix = false; //set if we have received a location from the remote tracker + +char keypress; //records the keypress from serial terminal +byte modenumber; //records which set of LoRa settings in use, 1 = tracker, 2 = search, 3 = command, 4=bind +byte Function_Number = 0; + +boolean SD_Found = false; //set if SD card found at program startup + +unsigned long TrackerMode_Packets; //running count of trackermode packets received +unsigned int SearchMode_Packets; //running count of searchmode packets received +unsigned int TestMode_Packets; //running count of searchmode packets received +unsigned long NoFix_Packets; //running count of No GPS fix packets received + +unsigned int SupplyVolts; + +char Flight_ID[15]; + +//File Includes +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include +#include "LoRa3.h" + +#ifdef UseSD +#include //https://github.com/greiman/SdFat +SdFat SD; +File logFile; +#endif + + +#ifdef USE_AFSK_RTTY_Upload +#include "AFSK_RTTY.h" +#endif + +#ifdef USE_SendOnlySoftwareSerial +#include //https://github.com/disq/i2c-gps-nav/blob/master/I2C_GPS_NAV/SendOnlySoftwareSerial.h +SendOnlySoftwareSerial Bluetooth_Serial (Bluetooth_TX); +#endif + +#ifdef USE_HardwareSerial +#define Bluetooth_Serial Hardware_Bluetooth_Port +#endif + +#ifdef Use_NMEA_Bluetooth_Uplink +#include "Generate_NMEA2.h" +#endif + +#include "Binary2.h" +#include "PinChangeInterrupt.h" + +#define max_functions 5 //number of functions in main program loop + + +//************************************************************************************************** +// Eventally - the program itself starts ............ +//************************************************************************************************** + + +void loop() +{ + Setup_LoRaTrackerMode(); + listen_LoRa(TrackerMode, 0); + while (Serial.read() != -1); //clear serial buffer + + #ifndef NoMenu + do + { + doMenu(); + } while (1); + #endif + +} + +void doMenu() +{ +//prints the terminal menu, caqn be ignored in handheld display mode (no serial characters to input + +menustart: + digitalWrite(LED1, LOW); //make sure LED is off + Setup_LoRaTrackerMode(); + + Serial.println(); + Serial.println(); + print_last_HABpacket(); + print_TRData(); + Serial.println(); + print_CurrentLoRaSettings(); + print_Nodes(); + Serial.println(); + Serial.println(F("1) Enable FSK RTTY")); + Serial.println(F("2) Disable FSK RTTY")); + Serial.println(F("3) Enable Address Strip")); + Serial.println(F("4) Disable Address Strip")); + Serial.println(F("5) Enable GPS Power Off")); + Serial.println(F("6) Disable GPS Power Off")); + Serial.println(F("7) Enable Fence Check")); + Serial.println(F("8) Disable Fence Check")); + Serial.println(F("9) Enable Doze Mode")); + Serial.println(F("0) Disable Doze Mode")); + Serial.println(); + Serial.println(F("B) Bind Receive")); + Serial.println(F("C) Command Mode Listen")); + Serial.println(F("D) Default Configuration")); + Serial.println(F("L) Link Report")); + Serial.println(F("O) Offset for Tracker Frequency")); + Serial.println(F("P) Packet Test")); + Serial.println(F("R) RTTY Test")); + Serial.println(F("S) Search Mode Listen")); + Serial.println(F("T) Tracker Mode Listen")); + + Serial.println(F("X) Reset Tracker Transmitter")); + Serial.println(F("Y) Clear All Memory and Settings (re-config needed)")); + Serial.println(); + Serial.println(F("+) Increase Transmitter Frequency 1KHZ")); + Serial.println(F("-) Reduce Transmitter Frequency 1KHZ")); + Serial.println(); + Serial.print(F("> ")); + delay(switch_delay); + + while (Serial.read() != -1); //clear serial buffer + + while ((Serial.available() == 0)) + { + //we are in menu mode so wait for a keypress or a switch press + } + + keypress = Serial.read(); //get the keypress + + Serial.println(keypress); + Serial.println(); + + if (keypress == '1') + { + Serial.println(F("Queue Enable FSKRTTY")); + send_ConfigCommand(Config0, ThisNode, FSKRTTYEnable, 1); + } + + if (keypress == '2') + { + Serial.println(F("Queue Disable FSKRTTY")); + send_ConfigCommand(Config0, ThisNode, FSKRTTYEnable, 0); + } + + if (keypress == '3') + { + Serial.println(F("Queue Enable Address Strip")); + send_ConfigCommand(Config0, ThisNode, AddressStrip, 1); + } + + if (keypress == '4') + { + Serial.println(F("Queue Disable Address Strip")); + send_ConfigCommand(Config0, ThisNode, AddressStrip, 0); + } + + if (keypress == '5') + { + //this is lat,long and alt at low data rate + Serial.println(F("Queue Enable GPS Power Off")); + send_ConfigCommand(Config0, ThisNode, GPSHotFix, 1); + } + + if (keypress == '6') + { + //this is lat,long and alt at low data rate + Serial.println(F("Queue Disable GPS Power Off")); + send_ConfigCommand(Config0, ThisNode, GPSHotFix, 0); + } + + if (keypress == '7') + { + Serial.println(F("Queue Enable Fence Check")); + send_ConfigCommand(Config0, ThisNode, CheckFence, 1); + } + + + if (keypress == '8') + { + Serial.println(F("Queue Disable Fence Check")); + send_ConfigCommand(Config0, ThisNode, CheckFence, 0); + } + + if (keypress == '9') + { + Serial.println(F("Queue Enable Doze")); + send_ConfigCommand(Config0, ThisNode, DozeEnable, 1); + } + + if (keypress == '0') + { + Serial.println(F("Queue Disable Doze")); + send_ConfigCommand(Config0, ThisNode, DozeEnable, 0); + } + + + if ((keypress == 'B') || (keypress == 'b')) + { + Function_Number = 5; //bind only accepted in function 5 + listen_LoRa(BindMode, 0); + Serial.println(F("Exit Bind Mode")); + } + + if ((keypress == 'C') || (keypress == 'c')) + { + Function_Number = 0; + listen_LoRa(CommandMode, 0); + } + + + + if ((keypress == 'L') || (keypress == 'l')) + { + lora_TXBUFF[0] = '0'; + Serial.println(F("Queue Link Report")); + lora_QueuedSend(0, 0, LinkReport, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a Link Report Request + delay(inter_Packet_delay); + listen_LoRa(CommandMode, 0); //listen for the link budget reply + } + + if ((keypress == 'O') || (keypress == 'o')) + { + enter_CalibrationOffset(); + } + + if ((keypress == 'P') || (keypress == 'p')) + { + Serial.println(F("Queue LoRa Packet Test")); + send_TestRequest('0'); + listen_LoRa(TrackerMode, 0); //command has been sent so listen for replies + } + + if ((keypress == 'R') || (keypress == 'r')) + { + Serial.println(F("Queue FSK RTTY Test Request")); + send_TestRequest('1'); + } + + if ((keypress == 'S') || (keypress == 's')) + { + Function_Number = 2; + listen_LoRa(SearchMode, 0); + } + + if ((keypress == 'T') || (keypress == 't')) + { + Function_Number = 1; + listen_LoRa(TrackerMode, 0); + } + + + if (keypress == 'D') + { + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); + } + + if (keypress == 'Y') + { + Clear_All_Memory(); + read_Settings_Memory(); + } + + if (keypress == 'X') + { + load_key(); + Serial.println(F("Queue Reset Tracker")); + lora_QueuedSend(0, 3, ResetTracker, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a reset request + } + + if (keypress == '+') + { + Serial.println(F("Increase Tracker Frequency 1KHZ")); + lora_QueuedSend(0, 1, INCFreq, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); + } + + if (keypress == '-') + { + Serial.println(F("Decrease Tracker Frequency 1KHZ")); + lora_QueuedSend(0, 1, DECFreq, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); + } + + goto menustart; //all programs deserve at least one goto, if only because it works +} + + +void enter_CalibrationOffset() +{ + //allows calibration offset of recever to be changed from terminal keyboard + float tempfloat; + + Serial.println(F("Enter Khz offset > ")); + while (Serial.available() == 0); + { + tempfloat = Serial.parseFloat(); + Serial.print(F("Offset = ")); + Serial.println(tempfloat, 5); + } + + while (Serial.read() != -1); //clear serial buffer + +} + + +void load_key() +{ + //loads the protection key to first locations in TX buffer + lora_TXBUFF[0] = key0; + lora_TXBUFF[1] = key1; + lora_TXBUFF[2] = key2; + lora_TXBUFF[3] = key3; +} + + +boolean Is_Key_Valid() +{ + //checks if protection key in RX bauffer matches + + Serial.print(F("Received Key ")); + Serial.write(lora_RXBUFF[0]); + Serial.write(lora_RXBUFF[1]); + Serial.write(lora_RXBUFF[2]); + Serial.write(lora_RXBUFF[3]); + Serial.println(); + + if ( (lora_RXBUFF[0] == key0) && (lora_RXBUFF[1] == key1) && (lora_RXBUFF[2] == key2) && (lora_RXBUFF[3] == key3) ) + { + Serial.println(F("Key Valid")); + return true; + } + else + { + Serial.println(F("Key Not Valid")); + return false; + } +} + + +byte listen_LoRa(byte lmode, unsigned long listen_mS) +{ + //listen for packets in specific mode, timeout in mS, 0 = continuous wait + unsigned long listen_endmS; + + switch (lmode) + { + case TrackerMode: + Setup_LoRaTrackerMode(); + break; + + case SearchMode: + Setup_LoRaSearchMode(); + break; + + case CommandMode: + Setup_LoRaCommandMode(); + break; + + case BindMode: + Setup_LoRaBindMode(); + break; + } + + print_CurrentLoRaSettings(); + listen_endmS = (millis() + listen_mS); //calculate the millis to stop listing at. + + keypress = 0; + + while (Serial.read() != -1); //empty serial buffer + + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXpacketCount = 0; + keypress = 0; + lora_RXONLoRa(); + + do + { + check_for_Packet(); + + if (listen_mS > 0) + { + if (millis() >= listen_endmS) + { + Serial.println(F("Listen Timeout")); + break; + } + } + } + while ((Serial.available() == 0)); + + if (Serial.available() != 0) + { + keypress = Serial.read(); + } + + if (keypress > 0) + { + Serial.println(F("Key Press")); + } + + if ( (millis() > listen_endmS) && (listen_mS != 0) ) + { + Serial.println(F("Timeout")); + keypress = 1; + } + + return keypress; +} + + +void print_mode(byte lmode) +{ + switch (lmode) + { + case TrackerMode: + Serial.print(F("Tracker Mode ")); + break; + + case SearchMode: + Serial.print(F("Search Mode ")); + break; + + case CommandMode: + Serial.print(F("Command Mode ")); + break; + + case BindMode: + Serial.print(F("Bind Mode ")); + break; + } +} + + +void send_TestRequest(char cmd) +{ + //transmit a test request + Setup_LoRaCommandMode(); + Serial.print(F("Send Test Request ")); + Serial.write(cmd); + Serial.println(); + + lora_TXBUFF[0] = cmd; + lora_QueuedSend(0, 0, Test, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a Test Request + delay(inter_Packet_delay); +} + + +void send_ConfigCommand(char confignum, char configdestination, char bitnum, char bitval) +{ + //transmits a config command + byte returnbyte; + Setup_LoRaCommandMode(); + bitnum = bitnum + 48; + bitval = bitval + 48; + lora_TXBUFF[0] = bitnum; //set the bitnum + lora_TXBUFF[1] = bitval; //set the bitval + + returnbyte = lora_QueuedSend(0, 1, Config0, configdestination, ThisNode, 10, lora_Power, default_attempts, NoStrip); + + if (returnbyte == 1) + { + Serial.println(F("Config Sent OK")); + print_TrackerLastSNR(); + print_TrackerLastRSSI(); + } + else + { + Serial.println(F("Config Send Failed")); + } + Serial.println(); + delay(inter_Packet_delay); +} + + + +void print_TrackerLastSNR() +{ + int8_t temp; + temp = Read_Byte(0, lora_RXBUFF); + Serial.print(F("Last Tracker SNR ")); + Serial.print(temp); + Serial.println(F("dB")); +} + + +void print_TrackerLastRSSI() +{ + int8_t temp; + temp = Read_Byte(1, lora_RXBUFF); + Serial.print(F("Last Tracker RSSI ")); + Serial.print(temp); + Serial.println(F("dB")); +} + + +byte check_for_Packet() +{ + //checks to see if a packet has arrived + byte returnbyte; + + #ifdef No_DIO0_RX_Ready + returnbyte = lora_readRXready(); + #else + returnbyte = lora_readRXready2(); + #endif + + if (returnbyte == 64) + { + digitalWrite(LED1, HIGH); + lora_ReadPacket(); + lora_AddressInfo(); + lora_ReceptionInfo(); + Serial.println(); + process_Packet(); + digitalWrite(LED1, LOW); + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXONLoRa(); //ready for next and clear flags + return 1; + } + + if (returnbyte == 96) + { + Serial.println(F("CRC Error")); + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXONLoRa(); //ready for next + } + + return 0; +} + + +void write_HABPacketMemory(byte RXStart, byte RXEnd) +{ + //stores the HAB packet in memory, FRAM or EEPROM + byte index, bufferdata; + unsigned int MemAddr = addr_StartHABPayloadData; //address in FRAM where last received HAB payload stored + + Memory_WriteByte(MemAddr, lora_RXPacketType); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXDestination); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXSource); + MemAddr++; + for (index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + Memory_WriteByte(MemAddr, bufferdata); + MemAddr++; + } + Memory_WriteByte(MemAddr, 0xFF); +} + + +void print_FightID() +{ + //send flight ID to serila terminal + byte index, bufferdata; + index = 0; + do + { + bufferdata = Flight_ID[index++]; + Serial.write(bufferdata); + } + while (bufferdata != 0); +} + + + +void extract_HABPacket(byte passedRXStart, byte passedRXEnd) +{ + //extracts data from received HAB packets where first fields are lat,lon,alt. + byte tempbyte; + byte savedRXStart; + + savedRXStart = lora_RXStart; //save current value of lora_RXStart + lora_RXStart = passedRXStart; //use lora_RXStart as its global + + //Skip leading $ + do + { + tempbyte = lora_RXBUFF[lora_RXStart++]; + } + while ( tempbyte == '$'); + lora_RXStart--; + + //ID + tempbyte = sizeof(Flight_ID); + + extract_Buffer(Flight_ID, sizeof(Flight_ID)); + + print_FightID(); + Serial.print(F(" ")); + + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Lat + TRLat = extract_Float(); + + //Lon + TRLon = extract_Float(); + + //Alt + TRAlt = extract_Uint(); + + print_Tracker_Location(); + Serial.println(); + + TRSats = extract_Uint(); + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Reset + TResets = extract_Uint(); + lora_RXStart = next_Comma(lora_RXStart); + TRStatus = extract_Uint(); + lora_RXStart = savedRXStart; //restore lora_RXStart, just in case +} + + +float extract_Float() +{ + //extracts a float in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte bufferdata; + float tempfloat; + do + { + bufferdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = bufferdata; + } + while (bufferdata != ','); + temp[tempptr] = 0; //terminator for string + tempfloat = (float)atof(temp); + return tempfloat; +} + + +void extract_Buffer(char * mybuffer, size_t bufSize) +{ + //extracts a buffer in ASCII format from RXbuffer + byte index, buffersize; + + buffersize = bufSize - 1; + for (index = 0; index <= buffersize; index++) + { + mybuffer[index] = lora_RXBUFF[lora_RXStart++]; + if (mybuffer[index] == ',') + { + break; + } + } + mybuffer[index] = 0; +} + + +float extract_Uint() +{ + //extracts an unsigned int in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte buffdata; + unsigned int tempint; + do + { + buffdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = buffdata; + } + while (buffdata != ','); + temp[tempptr] = 0; //terminator for string + tempint = (unsigned int)atof(temp); + return tempint; +} + + +byte next_Comma(byte localpointer) +{ + //skips through HAB packet (in CSV format) to next comma + byte bufferdata; + do + { + bufferdata = lora_RXBUFF[localpointer++]; + } + while (bufferdata != ','); + return localpointer; +} + + +/********************************************************************** + Tracker data routines +*********************************************************************** +*/ + +void extract_TRbinarylocationData() +{ + //extracts the binary location data from receive buffer and records date and time + + TRLat = Read_Float(0, lora_RXBUFF); + TRLon = Read_Float(4, lora_RXBUFF); + TRAlt = Read_UInt(8, lora_RXBUFF); +} + + +void print_TRData() +{ + //prints the last received tracker location data + Serial.print(F("Last Location ")); + Serial.print(TRLat, 5); + Serial.print(F(" ")); + Serial.print(TRLon, 5); + Serial.print(F(" ")); + Serial.println(TRAlt); +} + + +void save_TRData() +{ + //writes the last received tracker location data to memory + Memory_WriteFloat(addr_TRLat, TRLat); + Memory_WriteFloat(addr_TRLon, TRLon); + Memory_WriteUInt(addr_TRAlt, TRAlt); + +} + + +void read_TRData() +{ + //read stored tracker location data from memory + TRLat = Memory_ReadFloat(addr_TRLat); + TRLon = Memory_ReadFloat(addr_TRLon); + TRAlt = Memory_ReadUInt(addr_TRAlt); +} + + +void clear_TRData() +{ + //sets the tracker location data to zero + TRLat = 0; + TRLon = 0; + TRAlt = 0; +} + + +void print_Tracker_Location() +{ + //prints the tracker location data only + Serial.print(TRLat, 6); + Serial.print(F(",")); + Serial.print(TRLon, 6); + Serial.print(F(",")); + Serial.print(TRAlt); +} + + +void print_packet_HEX(byte RXStart, byte RXEnd) +{ + //prints contents of received packet as hexadecimal + byte bufferdata; + Serial.print(lora_RXPacketType, HEX); + Serial.print(F(" ")); + Serial.print(lora_RXDestination, HEX); + Serial.print(F(" ")); + Serial.print(lora_RXSource, HEX); + Serial.print(F(" ")); + + for (byte index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + if (bufferdata < 0x10) + { + Serial.print(F("0")); + } + Serial.print(bufferdata, HEX); + Serial.print(F(" ")); + } + +} + + +void process_Packet() +{ + //process and decide what to do with received packet + unsigned int index, tempint; + byte tempbyte, ptr; + unsigned int returnedCRC; + int8_t tempchar; + + digitalWrite(LED1, HIGH); + + if (lora_RXPacketType == LocationBinaryPacket) + { + Remote_GPS_Fix = true; + + if (modenumber == SearchMode) + { + SearchMode_Packets++; + } + + if (modenumber == TrackerMode) + { + TrackerMode_Packets++; + } + + extract_TRbinarylocationData(); + save_TRData(); + + print_Tracker_Location(); + TRStatus = Read_Byte(10, lora_RXBUFF); + Serial.print(F(",")); + print_AllBits(TRStatus); + Serial.println(); + + +#ifdef UseSD + SD_WriteBinarypacket_Log(); +#endif + + + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + Serial.println(); + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth, sends two NMEA strings + Serial.println(); +#endif + + display_fix_Status(); + return; + } + + + if (lora_RXPacketType == HABPacket) + { + Remote_GPS_Fix = true; + TrackerMode_Packets++; + + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + +#ifdef UseSD + SD_WriteHABpacket_Log(); +#endif + + write_HABPacketMemory(lora_RXStart, lora_RXEnd); + extract_HABPacket(lora_RXStart, lora_RXEnd); + + save_TRData(); + + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth + Serial.println(); +#endif + +#ifdef USE_AFSK_RTTY_Upload + Serial.print(F("AFSK RTTY Upload ")); + Serial.println(); + start_AFSK_RTTY(); + + for (index = 0; index <= 3; index++) + { + SendAFSKRTTY('$'); + } + + for (index = lora_RXStart; index <= lora_RXEnd; index++) + { + SendAFSKRTTY(lora_RXBUFF[index]); + } + SendAFSKRTTY(13); + SendAFSKRTTY(10); + end_AFSK_RTTY(); +#endif + + display_fix_Status(); + return; + } + + + if (lora_RXPacketType == Testpacket) + { + Serial.print(F("TestPacket ")); + TestMode_Packets++; + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + return; + } + + +#ifndef NoMenu + if (lora_RXPacketType == Bind ) + { + + Serial.println(F("Tracker Bind Received")); + ptr = 4; //set pointer to start of Bind data in lora_RXBUFF + + if (!Is_Key_Valid()) + { + return; + } + + if ((Function_Number != 5)) //only accept incoming bind request when in function 5 + { + Serial.println(F("Not in Bind Mode")); + return; + } + + Print_CRC_Bind_Memory(); + + tempint = (lora_RXBUFF[lora_RXEnd] * 256) + (lora_RXBUFF[lora_RXEnd - 1]); + + Serial.print(F("Transmitted CRC ")); + Serial.println(tempint, HEX); + returnedCRC = RXBuffer_CRC(ptr, (lora_RXEnd - 2)); + Serial.print(F("Received CRC ")); + Serial.println(returnedCRC, HEX); + + + if (returnedCRC == tempint) + { + Serial.println(F("Accepted")); + + for (index = addr_StartBindData; index <= addr_EndBindData; index++) + { + tempbyte = lora_RXBUFF[ptr++]; + Memory_WriteByte(index, tempbyte); + } + read_Settings_Memory(); //now bring the new settings into use + Print_CRC_Bind_Memory(); + } + else + { + Serial.println(F("Rejected")); + return; + } + } +#endif + + + if (lora_RXPacketType == Wakeup) + { + Serial.write(7); //print a bell + Serial.println(); + return; + } + + + if (lora_RXPacketType == NoFix) + { + NoFix_Packets++; + Serial.print(F("No Tracker GPS Fix ")); + Serial.println(NoFix_Packets); + return; + } + + if (lora_RXPacketType == NoGPS) + { + Serial.print(F("Tracker GPS Error ")); + return; + } + + + if (lora_RXPacketType == PowerUp) + { + tempint = Read_UInt(2, lora_RXBUFF); + Serial.print(F("Power Up ")); + Serial.print(tempint); + Serial.println(F("mV")); + return; + } + + + if (lora_RXPacketType == Info) + { + Serial.println(); + Serial.print(F("Tracker Last Packet Reception SNR,")); + tempchar = Read_Byte(0, lora_RXBUFF); + Serial.print(tempchar); + Serial.print(F("dB")); + tempchar = Read_Byte(1, lora_RXBUFF); + Serial.print(F(" RSSI,")); + Serial.print(tempchar); + Serial.println(F("dB")); + Serial.print(F("Battery,")); + tempint = Read_Int(2, lora_RXBUFF); + Serial.print(tempint); + Serial.print(F("mV,TRStatus,")); + tempbyte = (byte) Read_Int(4, lora_RXBUFF); + print_AllBits(tempbyte); + Serial.println(); + Serial.println(); + return; + } + + + if (lora_RXPacketType == ClearToSendCommand) + { + return; //do nothing + } + + + if (lora_RXPacketType == ClearToSend) + { + return; //do nothing + } + + + if (lora_RXPacketType == Sensor1) + { + Serial.println(F("Sensor1 Packet")); + process_Sensor1(); + } + + +} + + +unsigned int RXBuffer_CRC(unsigned int startaddr, unsigned int endaddr) +{ + unsigned int i, CRC; + + CRC = 0xffff; //start value for CRC16 + byte j; + + for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start + { + CRC ^= ((uint16_t) lora_RXBUFF[i] << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + return CRC; + +} + + + + +void process_Sensor1() +{ + float lTemperature, lHumidity, lPressure, lAltitude; + + lTemperature = Read_Float(0, lora_RXBUFF); + lHumidity = Read_Float(4, lora_RXBUFF); + lPressure = Read_Float(8, lora_RXBUFF); + lAltitude = Read_Float(12, lora_RXBUFF); + + Serial.print(F("Temperature: ")); + Serial.print(lTemperature, 2); + Serial.println(F(" degrees C")); + + Serial.print(F("%RH: ")); + Serial.print(lHumidity, 2); + Serial.println(F(" %")); + + Serial.print(F("Pressure: ")); + Serial.print(lPressure, 2); + Serial.println(F(" Pa")); + + Serial.print(F("Altitude: ")); + Serial.print(lAltitude, 2); + Serial.println(F("m")); +} + + +void print_AllBits(byte myByte) +{ + //prints bits of byte as binary + for (byte mask = 0x80; mask; mask >>= 1) { + if (mask & myByte) + Serial.print('1'); + else + Serial.print('0'); + } +} + + +void display_fix_Status() +{ + //display fix status of tracker + + if (!(bitRead(TRStatus, GPSFix))) + { + Serial.print(F("No ")); + } + + Serial.println(F("Tracker GPS fix")); +} + + +#ifdef UseSD +void SD_WriteHABpacket_Log() +{ + //write HAB packet to SD card + byte index; + + if (SD_Found) + { + logFile.write(lora_RXPacketType); + logFile.write(lora_RXDestination); + logFile.write(lora_RXSource); + logFile.print(F(",")); + + for (index = lora_RXStart; index <= lora_RXEnd; index++) + { + logFile.write(lora_RXBUFF[index]); + } + logFile.write(13); + logFile.write(10); + logFile.flush(); + } + else + { + Serial.println("No SD card !"); + } +} + + +void SD_WriteBinarypacket_Log() +{ + //send the location data in binary packet to the log + if (SD_Found) + { + logFile.write(lora_RXPacketType); + logFile.write(lora_RXDestination); + logFile.write(lora_RXSource); + logFile.print(F(",")); + logFile.print(F(",")); + SD_addLatLonAlt_Log(); + + logFile.write(13); + logFile.write(10); + logFile.flush(); + } + else + { + Serial.println(F("No SD card !")); + } +} + + +void SD_addLatLonAlt_Log() +{ + logFile.print(TRLat, 6); + logFile.print(F(",")); + logFile.print(TRLon, 6); + logFile.print(F(",")); + logFile.print(TRAlt, 6); + logFile.write(13); + logFile.write(10); +} + + + +boolean setup_SDLOG() +{ + //checks if the SD card is present and can be initialised + + Serial.print(F("SD card...")); + + if (!SD.begin(SD_CS)) + { + Serial.println(F("Failed, or not present")); + SD_Found = false; + return false; //don't do anything more: + } + + Serial.print(F("Initialized OK")); + SD_Found = true; + + char filename[] = "Track000.txt"; + for (uint8_t i = 0; i < 100; i++) { + filename[6] = i / 10 + '0'; + filename[7] = i % 10 + '0'; + if (! SD.exists(filename)) { + // only open a new file if it doesn't exist + logFile = SD.open(filename, FILE_WRITE); + break; // leave the loop! + } + } + + Serial.print(F("...Writing to ")); + Serial.print(F("Track0")); + Serial.write(filename[6]); + Serial.write(filename[7]); + Serial.print(F(".txt")); + return true; +} + + + +void printlog_addleadingZero(byte temp) +{ + if (temp < 10) + { + logFile.print(F("0")); + } + logFile.print(temp); +} +#endif + + + +void print_CurrentLoRaSettings() +{ + //prints the current LoRa settings, reads device registers + float tempfloat; + int tempint; + byte regdata; + unsigned long bw; + + tempfloat = lora_GetFreq(); + Serial.print(tempfloat, 3); + Serial.print(F("MHz (")); + + tempint = ramc_CalibrationOffset; + tempfloat = (float)(tempint / 1000); + Serial.print(tempfloat, 1); + + Serial.print(F("Khz)")); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & 0xF0; + bw = lora_returnbandwidth(regdata); + Serial.print(F(" BW")); + Serial.print(bw); + + regdata = lora_Read(lora_RegModemConfig2); + regdata = (regdata & 0xF0) / 16; + Serial.print(F(" SF")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & B00001110; + regdata = regdata / 2; //move right one + regdata = regdata + 4; + + Serial.print(F(" CR4/")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig3); + regdata = regdata & B00001000; + Serial.print(F(" LDROPT_")); + if (regdata == 8) + { + Serial.print(F("ON")); + } + else + { + Serial.print(F("OFF")); + } + + regdata = lora_Read(lora_RegPaConfig); + regdata = regdata - 0xEE; + + Serial.print(F(" Power ")); + Serial.print(regdata); + Serial.print(F("dBm")); + Serial.println(); +} + + +void system_Error() +{ + //there is a error, likley no LoRa device found, cannot continue + while (1) + { + digitalWrite(LED1, HIGH); + delay(50); + digitalWrite(LED1, LOW); + delay(50); + } +} + + +void led_Flash(unsigned int flashes, unsigned int dealymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(dealymS); + digitalWrite(LED1, LOW); + delay(dealymS); + } +} + + +void read_Settings_Defaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Configuring Settings from Defaults")); + ramc_CalibrationOffset = CalibrationOffset; + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_CommandMode_Frequency = CommandMode_Frequency; + ramc_SearchMode_Frequency = SearchMode_Frequency; + ramc_TrackerMode_Bandwidth = TrackerMode_Bandwidth; + ramc_TrackerMode_SpreadingFactor = TrackerMode_SpreadingFactor; + ramc_TrackerMode_CodeRate = TrackerMode_CodeRate; + ramc_CommandMode_Bandwidth = CommandMode_Bandwidth; + ramc_CommandMode_SpreadingFactor = CommandMode_SpreadingFactor; + ramc_CommandMode_CodeRate = CommandMode_CodeRate; + ramc_SearchMode_Bandwidth = SearchMode_Bandwidth; + ramc_SearchMode_SpreadingFactor = SearchMode_SpreadingFactor; + ramc_SearchMode_CodeRate = SearchMode_CodeRate; + ramc_TrackerMode_Power = TrackerMode_Power; + ramc_SearchMode_Power = SearchMode_Power; + ramc_CommandMode_Power = CommandMode_Power; +} + + +void read_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Configuring Settings from Memory")); + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_CommandMode_Frequency = Memory_ReadULong(addr_CommandMode_Frequency); + ramc_SearchMode_Frequency = Memory_ReadULong(addr_SearchMode_Frequency); + ramc_TrackerMode_Bandwidth = Memory_ReadByte(addr_TrackerMode_Bandwidth); + ramc_TrackerMode_SpreadingFactor = Memory_ReadByte(addr_TrackerMode_SpreadingFactor); + ramc_TrackerMode_CodeRate = Memory_ReadByte(addr_TrackerMode_CodeRate); + ramc_CommandMode_Bandwidth = Memory_ReadByte(addr_CommandMode_Bandwidth); + ramc_CommandMode_SpreadingFactor = Memory_ReadByte(addr_CommandMode_SpreadingFactor); + ramc_CommandMode_CodeRate = Memory_ReadByte(addr_CommandMode_CodeRate); + ramc_SearchMode_Bandwidth = Memory_ReadByte(addr_SearchMode_Bandwidth); + ramc_SearchMode_SpreadingFactor = Memory_ReadByte(addr_SearchMode_SpreadingFactor); + ramc_SearchMode_CodeRate = Memory_ReadByte(addr_SearchMode_CodeRate); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + ramc_SearchMode_Power = Memory_ReadByte(addr_SearchMode_Power); + ramc_CommandMode_Power = Memory_ReadByte(addr_CommandMode_Power); +} + + +void write_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver.. + Serial.println(F("Writing RAM Settings to Memory")); + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //clear memory area first + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteULong(addr_CommandMode_Frequency, ramc_CommandMode_Frequency); + Memory_WriteULong(addr_SearchMode_Frequency, ramc_SearchMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Bandwidth, ramc_TrackerMode_Bandwidth); + Memory_WriteByte(addr_TrackerMode_SpreadingFactor, ramc_TrackerMode_SpreadingFactor); + Memory_WriteByte(addr_TrackerMode_CodeRate, ramc_TrackerMode_CodeRate); + Memory_WriteByte(addr_CommandMode_Bandwidth, ramc_CommandMode_Bandwidth); + Memory_WriteByte(addr_CommandMode_SpreadingFactor, ramc_CommandMode_SpreadingFactor); + Memory_WriteByte(addr_CommandMode_CodeRate, ramc_CommandMode_CodeRate); + Memory_WriteByte(addr_SearchMode_Bandwidth, ramc_SearchMode_Bandwidth); + Memory_WriteByte(addr_SearchMode_SpreadingFactor, ramc_SearchMode_SpreadingFactor); + Memory_WriteByte(addr_SearchMode_CodeRate, ramc_SearchMode_CodeRate); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + Memory_WriteByte(addr_SearchMode_Power, ramc_SearchMode_Power); + Memory_WriteByte(addr_CommandMode_Power, ramc_CommandMode_Power); +} + + +void Serialprint_addleadingZero(byte temp) +{ + if (temp < 10) + { + Serial.print(F("0")); + } + Serial.print(temp); +} + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.print(F("Clearing All Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +/* + void Print_CRC_All_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartMemory, addr_EndMemory); + Serial.print(F("CRC_All_Memory ")); + Serial.println(returnedCRC, HEX); +} + + +void Print_CRC_Config_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartConfigData, addr_EndConfigData); + Serial.print(F("CRC_Config_Memory ")); + Serial.println(returnedCRC, HEX); +} +*/ + +void Print_CRC_Bind_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("CRC_Bind_Memory ")); + Serial.println(returnedCRC, HEX); +} + + +//******************************************************************************************************* + + +void print_Nodes() +{ + //prints current node of this device + Serial.print(F("This Node ")); + Serial.write(ThisNode); + Serial.println(); +} + + +void print_last_HABpacket() +{ + //prints last received HAB packet to serial terminal + byte memorydata; + unsigned int address; + address = addr_StartHABPayloadData; + + Serial.print(F("Last HAB Packet ")); + do + { + memorydata = Memory_ReadByte(address); + if ((memorydata == 0xFF) || (address >= addr_EndHABPayloadData)) + { + break; + } + Serial.write(memorydata); + address++; + } + while (true); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + //sets LoRa modem to Tracker mode + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_TrackerMode_Bandwidth, ramc_TrackerMode_SpreadingFactor, ramc_TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_TrackerMode_Power; + modenumber = TrackerMode; +} + + +void Setup_LoRaSearchMode() +{ + //sets LoRa modem to Search mode + lora_SetFreq(ramc_SearchMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_SearchMode_Bandwidth, ramc_SearchMode_SpreadingFactor, ramc_SearchMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_SearchMode_Power; + modenumber = SearchMode; +} + +void Setup_LoRaCommandMode() +{ + //sets LoRa modem to Command mode + lora_SetFreq(ramc_CommandMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_CommandMode_Bandwidth, ramc_CommandMode_SpreadingFactor, ramc_CommandMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_CommandMode_Power; + modenumber = CommandMode; +} + + +void Setup_LoRaBindMode() +{ + //sets LoRa modem to Bind mode + lora_SetFreq(BindMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(BindMode_Bandwidth, BindMode_SpreadingFactor, BindMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = BindMode_Power; + modenumber = BindMode; +} + + +void display_frequency() +{ + //display current set frequency of LoRa device + float freq_temp; + freq_temp = lora_GetFreq(); + Serial.print(F("Set to Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + + +void display_frequencies_memory() +{ + //display the frequncies set in memory, good check to see if all is well with memory + unsigned long freq_temp; + freq_temp = Memory_ReadULong(addr_TrackerMode_Frequency); + Serial.print(F("TrackerMode ")); + Serial.println(freq_temp); + freq_temp = Memory_ReadULong(addr_SearchMode_Frequency); + Serial.print(F("SearchMode ")); + Serial.println(freq_temp); + freq_temp = Memory_ReadULong(addr_CommandMode_Frequency); + Serial.print(F("CommandMode ")); + Serial.println(freq_temp); + Serial.println(); + +} + + +void setstatusByte(byte bitnum, byte bitval) +{ + //program the status byte +#ifdef Debug + if (bitval) + { + Serial.print(F("Set Status Bit ")); + } + else + { + Serial.print(F("Clear Status Bit ")); + } + + Serial.println(bitnum); +#endif + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } +} + + +void setup() +{ + //needs no explanation I hope ............... + + pinMode(LED1, OUTPUT); //setup pin for PCB LED + led_Flash(2, 250); + + Serial.begin(38400); //setup Serial console ouput + Serial.println(); + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(aurthorname)); + Serial.println(); + + SPI.begin(); //initialize SPI: + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + pinMode(lora_NReset, OUTPUT); //LoRa Device reset line + pinMode (lora_NSS, OUTPUT); //LoRa Device select line + digitalWrite(lora_NSS, HIGH); + digitalWrite(lora_NReset, HIGH); + delay(1); + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); + Serial.println(); + Serial.println(); +#endif + + +#ifdef ClearConfigData + Clear_Config_Memory(); +#endif + + +#ifdef ConfigureDefaults + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); + Serial.flush(); +#endif + +#ifdef ConfigureFromMemory + read_Settings_Memory(); +#endif + + +//#ifdef write_CalibrationOffset + //Memory_WriteInt(addr_CalibrationOffset, CalibrationOffset); + //tempint = Memory_ReadInt(addr_CalibrationOffset); +//#endif + + Print_CRC_Bind_Memory(); + + read_TRData(); + + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); //redo faster SPI as changed by display_setup + + if (!lora_CheckDevice()) + { + Serial.println(F("LoRa Error!")); + led_Flash(40, 50); + } + + lora_Setup(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial_Setup(); +#endif + + print_Nodes(); + Serial.println(); + + Setup_LoRaTrackerMode(); + + Serial.println(); + lora_Print(); + Serial.println(); + Serial.flush(); + +#ifdef CalibrateTone + digitalWrite(LED1, HIGH); //turn on LED + lora_Tone(1000, 3000, 10); //Transmit an FM tone, 1000hz, 1000ms, 10dBm + digitalWrite(LED1, LOW); //LED is off + delay(1000); +#endif + + lora_RXONLoRa(); + +#ifdef UseSD + setup_SDLOG(); //setup SD and delay a bit to ensure any pending ints cleared +#endif + + Serial.println(); + print_last_HABpacket(); + print_TRData(); + Serial.println(); + + Serial.println(); + display_frequencies_memory(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial.println(F("Bluetooth Active")); +#endif + +} + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/Basic_Receiver_Terminal_Settings.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/Basic_Receiver_Terminal_Settings.h new file mode 100644 index 0000000..5bf9079 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/Basic_Receiver_Terminal_Settings.h @@ -0,0 +1,162 @@ +//Basic_Receiver_Terminal_Settings.h +/* +****************************************************************************************************** + +LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without +the explicit permission of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the +intended purpose and free from errors. + +Note that if you select all possible options, SD Card logging, Bluetooth NMEA uplink and AFSK RTTY +upload you will run out of memory whne the ATMEGA328 is in use, cannot do much about it. + +To Do: +disable bind mode when menu not selected + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +//#define UseSD //define if there is an SD card attached +#define Board_Definition "HAB2_Board_Definitions.h" //define the board type to be used + + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +//#define ClearConfigData //at startup zero the config memory +//#define ClearAllMemory //at startup clears from start memory to end memory, normally 1kbyte, needs to be followed by ConfigureDefaults +//#define ConfigureDefaults //at startup configure settings from default program defaults, these are then stored in memory +#define ConfigureFromMemory //at startup configure settings from values stored in memory, this needs to be the active mode for bind to work + +#define CalibrateTone //comment in to have a calibrate tone at startup + + + +//#define NoMenu + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 433400000; + +//Search mode +const unsigned long SearchMode_Frequency = 433300000; + +//Command mode +const unsigned long CommandMode_Frequency = 433500000; + +//Bind mode - Change this with great care !!!!! +const unsigned long BindMode_Frequency = 434100000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 28900; + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +#define LoRa_Device_in_MB1 //if using a MikroBus based specify the socket for the LoRa Device + +//Tracker mode +const byte TrackerMode_Power = 10; +#define TrackerMode_Bandwidth BW62500 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 + +//Search mode +const byte SearchMode_Power = 10; +#define SearchMode_Bandwidth BW62500 +#define SearchMode_SpreadingFactor SF12 +#define SearchMode_CodeRate CR45 + +//Command mode +const byte CommandMode_Power = 5; +#define CommandMode_Bandwidth BW62500 +#define CommandMode_SpreadingFactor SF10 +#define CommandMode_CodeRate CR45 + + +//Bind mode - Change this with great care !!!!! +const byte BindMode_Power = 2; +#define BindMode_Bandwidth BW500000 +#define BindMode_SpreadingFactor SF8 +#define BindMode_CodeRate CR45 + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 128; +const byte lora_TXBUFF_Size = 128; + + +#define RemoteControlNode 'G' //normally used by tracker transmitter in promiscuous_Mode +#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +#define ThisNode ControlledNode +const boolean Promiscuous_Mode = true; //if set to false remote control packets from any node accepted +const int inter_Packet_delay = 500; //allows time for receiver to be ready to see a possible reply +const byte Cmd_WaitSecs = 15; //number of seconds to stay in command mode +const byte default_attempts = 5; //default number of times a command will attempt to be sent + + +//Protected Command Settings +const char key0 = 'B'; //Used to restrict access to some commands +const char key1 = 'A'; +const char key2 = 'R'; +const char key3 = 'T'; + +//#define No_DIO0_RX_Ready //needed for boards that cannot directly ready the DIO0 pin + + + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +#define Memory_Library "I2CFRAM_MB85RC16PNF.h" +//#define Memory_Library "EEPROM_Memory.h" +//#define Memory_Library "SPIFRAM_Memory_FM25CL64B_MB85RS64.h" //define this file if a SPI FRAM is in use + + +//************************************************************************************************** +// 9) AFSK RTTY Options +//************************************************************************************************** + +//#define USE_AFSK_RTTY_Upload +const int AFSKrttybaud = 1465; //delay in uS x 2 for 1 bit and 300baud. Decode range in FLDIGI 1420 to 1510 +const int afskleadinmS = 500; //number of ms for AFSK constant lead in tone +const int tonehighHz = 1000; //high tone in Hertz +const int tonelowHz = 650; //low tone in Hertz + + +//************************************************************************************************** +// 10) Bluetooth Options +//************************************************************************************************** + +//#define Use_NMEA_Bluetooth_Uplink //define if your going to use a Bluetooth adapter to uplink NMEA into a mapping application +//#define USE_SendOnlySoftwareSerial //if you want the Bluetooth device on a pin other than the hardware serial port, define this +//#define USE_HardwareSerial //use hardware serial port to send Bluetooth +//#define Hardware_Bluetooth_Port Serial //Which Hardware port to use for Bluetooth +//#define BluetoothBaud 9600 + +const byte Bluetooth_Buff_Size = 128; //size of buffer for NMEA output + + +//************************************************************************************************** +// 12) Miscellaneous program settings +//************************************************************************************************** + +const unsigned int switch_delay = 1000; //delay in mS after a switch\key press before another can take place diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/SendOnlySoftwareSerial.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/SendOnlySoftwareSerial.h new file mode 100644 index 0000000..f0d6af8 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_151117/SendOnlySoftwareSerial.h @@ -0,0 +1,91 @@ +/* + + SendOnlySoftwareSerial - adapted from SoftwareSerial by Nick Gammon 28th June 2012 + +SoftwareSerial.h (formerly NewSoftSerial.h) - +Multi-instance software serial library for Arduino/Wiring +-- Interrupt-driven receive and other improvements by ladyada + (http://ladyada.net) +-- Tuning, circular buffer, derivation from class Print/Stream, + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart (http://www.arduiniana.org) +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) +-- 20MHz processor support by Garrett Mace (http://www.macetech.com) +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef SendOnlySoftwareSerial_h +#define SendOnlySoftwareSerial_h + +#include +#include + +/****************************************************************************** +* Definitions +******************************************************************************/ + +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +class SendOnlySoftwareSerial : public Stream +{ +private: + // per object data + uint8_t _transmitBitMask; + volatile uint8_t *_transmitPortRegister; + + uint16_t _tx_delay; + + uint16_t _inverse_logic; + uint16_t _errors_ok; + + // private methods + void tx_pin_write(uint8_t pin_state); + void setTX(uint8_t transmitPin); + + // private static method for timing + static inline void tunedDelay(uint16_t delay); + +public: + // public methods + SendOnlySoftwareSerial(uint8_t transmitPin, bool inverse_logic = false, bool errors_ok = false); + ~SendOnlySoftwareSerial(); + void begin(long speed); + void end(); + int peek(); + + virtual size_t write(uint8_t byte); + virtual int read(); + virtual int available(); + virtual void flush(); + + using Print::write; +}; + +// Arduino 0012 workaround +#undef int +#undef char +#undef long +#undef byte +#undef float +#undef abs +#undef round + +#endif // SendOnlySoftwareSerial_h diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_Beta_240118/Basic_Receiver_Terminal_Beta_240118.ino b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_Beta_240118/Basic_Receiver_Terminal_Beta_240118.ino new file mode 100644 index 0000000..ead0130 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_Beta_240118/Basic_Receiver_Terminal_Beta_240118.ino @@ -0,0 +1,1727 @@ +//************************************************************************************************** +// Note: +// +// Make changes to this Program file at your peril +// +// Configuration changes should be made in the Basic_Receiver_Terminal_Settingsfile not here ! +// +// This program includes the automatic frequency control functions, you can set the tracker mode +// packet to a bandwidth as low as 7.8kHz. To lock the receiver to the transmitter swap across to +// search mode to receive at least one packet, you can then go back to tracker mode. +// +//************************************************************************************************** + +#define programname "Basic_Receiver_Terminal_Beta_240118" +#define programversion "V1.2" +#define aurthorname "Stuart Robinson" +#include +#include + +#include "Program_Definitions.h" +#include "Basic_Receiver_Terminal_Settings.h" + +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the + intended purpose and free from errors. + + To do: + Check function of enter_CalibrationOffset() + + Changes: + 05/01/18 - Added afc functionality + + ****************************************************************************************************** +*/ + + +//Program Variables +int ramc_CalibrationOffset; //adjustment for frequency in Hertz + +unsigned long ramc_TrackerMode_Frequency; //Initial default for FlightFrequency +byte ramc_TrackerMode_Bandwidth; //used to keep Tracker mode settings +byte ramc_TrackerMode_SpreadingFactor; +byte ramc_TrackerMode_CodeRate; +byte ramc_TrackerMode_Power; + +unsigned long ramc_SearchMode_Frequency; //Initial default for FlightFrequency +byte ramc_SearchMode_Bandwidth; //used to keep Searc mode settings +byte ramc_SearchMode_SpreadingFactor; +byte ramc_SearchMode_CodeRate; +byte ramc_SearchMode_Power; + +unsigned long ramc_CommandMode_Frequency; //Initial default for command and reporting frequency +byte ramc_CommandMode_Bandwidth; //used to keep Command mode settings +byte ramc_CommandMode_SpreadingFactor; +byte ramc_CommandMode_CodeRate; +byte ramc_CommandMode_Power; + + +float TRLat; //tracker transmitter co-ordinates +float TRLon; +unsigned int TRAlt; +unsigned int TResets; //keeps the count of remote tracker resets +byte TRStatus; //Status byte from tracker binary payload +byte TRSats; //last received number of GPS satellites from tracker +boolean Remote_GPS_Fix = false; //set if we have received a location from the remote tracker + +char keypress; //records the keypress from serial terminal +byte modenumber; //records which set of LoRa settings in use, 1 = tracker, 2 = search, 3 = command, 4=bind +byte Function_Number = 0; + +boolean SD_Found = false; //set if SD card found at program startup + +unsigned long TrackerMode_Packets; //running count of trackermode packets received +unsigned int SearchMode_Packets; //running count of searchmode packets received +unsigned int TestMode_Packets; //running count of searchmode packets received +unsigned long NoFix_Packets; //running count of No GPS fix packets received + +unsigned int SupplyVolts; + +char Flight_ID[15]; + +//File Includes +#include Board_Definition //include previously defined board file +#include Memory_Library //include previously defined Memory Library + +#include +#include +#include "LoRa4.h" + +#ifdef UseSD +#include //https://github.com/greiman/SdFat +SdFat SD; +File logFile; +#endif + + +#ifdef USE_AFSK_RTTY_Upload +#include "AFSK_RTTY.h" +#endif + +#ifdef USE_SendOnlySoftwareSerial +#include //https://github.com/disq/i2c-gps-nav +SendOnlySoftwareSerial Bluetooth_Serial (Bluetooth_TX); +#endif + +#ifdef USE_HardwareSerial +#define Bluetooth_Serial Hardware_Bluetooth_Port +#endif + +#ifdef Use_NMEA_Bluetooth_Uplink +#include "Generate_NMEA2.h" +#endif + +#include "Binary2.h" +#include "PinChangeInterrupt.h" + +#define max_functions 5 //number of functions in main program loop + + +//************************************************************************************************** +// Eventally - the program itself starts ............ +//************************************************************************************************** + + +void loop() +{ + Setup_LoRaTrackerMode(); + listen_LoRa(TrackerMode, 0); + while (Serial.read() != -1); //clear serial buffer + +#ifndef NoMenu + do + { + doMenu(); + } while (1); +#endif + +} + +void doMenu() +{ + //prints the terminal menu, caqn be ignored in handheld display mode (no serial characters to input + +menustart: + digitalWrite(LED1, LOW); //make sure LED is off + Setup_LoRaTrackerMode(); + + Serial.println(); + Serial.println(); + print_last_HABpacket(); + print_TRData(); + Serial.println(); + print_CurrentLoRaSettings(); + print_Nodes(); + Serial.println(); + Serial.println(F("1) Enable FSK RTTY")); + Serial.println(F("2) Disable FSK RTTY")); + Serial.println(F("3) Enable Address Strip")); + Serial.println(F("4) Disable Address Strip")); + Serial.println(F("5) Enable GPS Power Off")); + Serial.println(F("6) Disable GPS Power Off")); + Serial.println(F("7) Enable Fence Check")); + Serial.println(F("8) Disable Fence Check")); + Serial.println(F("9) Enable Doze Mode")); + Serial.println(F("0) Disable Doze Mode")); + Serial.println(); + Serial.println(F("B) Bind Receive")); + Serial.println(F("C) Command Mode Listen")); + Serial.println(F("D) Default Configuration")); + Serial.println(F("L) Link Report")); + Serial.println(F("O) Offset for Tracker Frequency")); + Serial.println(F("P) Packet Test")); + Serial.println(F("R) RTTY Test")); + Serial.println(F("S) Search Mode Listen")); + Serial.println(F("T) Tracker Mode Listen")); + + Serial.println(F("X) Reset Tracker Transmitter")); + Serial.println(F("Y) Clear All Memory and Settings (re-config needed)")); + Serial.println(); + Serial.println(F("+) Increase Transmitter Frequency 1KHZ")); + Serial.println(F("-) Reduce Transmitter Frequency 1KHZ")); + Serial.println(); + Serial.print(F("> ")); + delay(switch_delay); + + while (Serial.read() != -1); //clear serial buffer + + while ((Serial.available() == 0)) + { + //we are in menu mode so wait for a keypress or a switch press + } + + keypress = Serial.read(); //get the keypress + + Serial.println(keypress); + Serial.println(); + + if (keypress == '1') + { + Serial.println(F("Queue Enable FSKRTTY")); + send_ConfigCommand(Config0, ThisNode, FSKRTTYEnable, 1); + } + + if (keypress == '2') + { + Serial.println(F("Queue Disable FSKRTTY")); + send_ConfigCommand(Config0, ThisNode, FSKRTTYEnable, 0); + } + + if (keypress == '3') + { + Serial.println(F("Queue Enable Address Strip")); + send_ConfigCommand(Config0, ThisNode, AddressStrip, 1); + } + + if (keypress == '4') + { + Serial.println(F("Queue Disable Address Strip")); + send_ConfigCommand(Config0, ThisNode, AddressStrip, 0); + } + + if (keypress == '5') + { + //this is lat,long and alt at low data rate + Serial.println(F("Queue Enable GPS Power Off")); + send_ConfigCommand(Config0, ThisNode, GPSHotFix, 1); + } + + if (keypress == '6') + { + //this is lat,long and alt at low data rate + Serial.println(F("Queue Disable GPS Power Off")); + send_ConfigCommand(Config0, ThisNode, GPSHotFix, 0); + } + + if (keypress == '7') + { + Serial.println(F("Queue Enable Fence Check")); + send_ConfigCommand(Config0, ThisNode, CheckFence, 1); + } + + + if (keypress == '8') + { + Serial.println(F("Queue Disable Fence Check")); + send_ConfigCommand(Config0, ThisNode, CheckFence, 0); + } + + if (keypress == '9') + { + Serial.println(F("Queue Enable Doze")); + send_ConfigCommand(Config0, ThisNode, DozeEnable, 1); + } + + if (keypress == '0') + { + Serial.println(F("Queue Disable Doze")); + send_ConfigCommand(Config0, ThisNode, DozeEnable, 0); + } + + + if ((keypress == 'B') || (keypress == 'b')) + { + Function_Number = 5; //bind only accepted in function 5 + listen_LoRa(BindMode, 0); + Serial.println(F("Exit Bind Mode")); + } + + if ((keypress == 'C') || (keypress == 'c')) + { + Function_Number = 0; + listen_LoRa(CommandMode, 0); + } + + + if ((keypress == 'L') || (keypress == 'l')) + { + lora_TXBUFF[0] = '0'; + Serial.println(F("Queue Link Report")); + lora_QueuedSend(0, 0, LinkReport, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a Link Report Request + delay(inter_Packet_delay); + listen_LoRa(CommandMode, 0); //listen for the link budget reply + } + + if ((keypress == 'O') || (keypress == 'o')) + { + enter_CalibrationOffset(); + } + + if ((keypress == 'P') || (keypress == 'p')) + { + Serial.println(F("Queue LoRa Packet Test")); + send_TestRequest('0'); + listen_LoRa(TrackerMode, 0); //command has been sent so listen for replies + } + + if ((keypress == 'R') || (keypress == 'r')) + { + Serial.println(F("Queue FSK RTTY Test Request")); + send_TestRequest('1'); + } + + if ((keypress == 'S') || (keypress == 's')) + { + Function_Number = 2; + listen_LoRa(SearchMode, 0); + } + + if ((keypress == 'T') || (keypress == 't')) + { + Function_Number = 1; + listen_LoRa(TrackerMode, 0); + } + + + if (keypress == 'D') + { + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); + } + + if (keypress == 'Y') + { + Clear_All_Memory(); + read_Settings_Memory(); + } + + if (keypress == 'X') + { + load_key(); + Serial.println(F("Queue Reset Tracker")); + lora_QueuedSend(0, 3, ResetTracker, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a reset request + } + + if (keypress == '+') + { + Serial.println(F("Increase Tracker Frequency 1KHZ")); + lora_QueuedSend(0, 1, INCFreq, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); + } + + if (keypress == '-') + { + Serial.println(F("Decrease Tracker Frequency 1KHZ")); + lora_QueuedSend(0, 1, DECFreq, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); + } + + goto menustart; //all programs deserve at least one goto, if only because it works +} + + +void check_AFC() +{ + signed int freqerror; + freqerror = lora_GetFrequencyError(); + Serial.print(F(" FreqErr,")); + Serial.print(freqerror); + ramc_CalibrationOffset = ramc_CalibrationOffset - freqerror; + Serial.print(F(" CalOffset,")); + Serial.print(ramc_CalibrationOffset); + lora_SetFreq(lora_CurrentFreq, ramc_CalibrationOffset); +} + + + +void enter_CalibrationOffset() +{ + //allows calibration offset of recever to be changed from terminal keyboard + float tempfloat; + + Serial.println(F("Enter Khz offset > ")); + while (Serial.available() == 0); + { + tempfloat = Serial.parseFloat(); + Serial.print(F("Offset = ")); + Serial.println(tempfloat, 5); + } + + while (Serial.read() != -1); //clear serial buffer + +} + + +void load_key() +{ + //loads the protection key to first locations in TX buffer + lora_TXBUFF[0] = key0; + lora_TXBUFF[1] = key1; + lora_TXBUFF[2] = key2; + lora_TXBUFF[3] = key3; +} + + +boolean Is_Key_Valid() +{ + //checks if protection key in RX bauffer matches + + Serial.print(F("Received Key ")); + Serial.write(lora_RXBUFF[0]); + Serial.write(lora_RXBUFF[1]); + Serial.write(lora_RXBUFF[2]); + Serial.write(lora_RXBUFF[3]); + Serial.println(); + + if ( (lora_RXBUFF[0] == key0) && (lora_RXBUFF[1] == key1) && (lora_RXBUFF[2] == key2) && (lora_RXBUFF[3] == key3) ) + { + Serial.println(F("Key Valid")); + return true; + } + else + { + Serial.println(F("Key Not Valid")); + return false; + } +} + + +byte listen_LoRa(byte lmode, unsigned long listen_mS) +{ + //listen for packets in specific mode, timeout in mS, 0 = continuous wait + unsigned long listen_endmS; + + switch (lmode) + { + case TrackerMode: + Setup_LoRaTrackerMode(); + break; + + case SearchMode: + Setup_LoRaSearchMode(); + break; + + case CommandMode: + Setup_LoRaCommandMode(); + break; + + case BindMode: + Setup_LoRaBindMode(); + break; + } + + print_CurrentLoRaSettings(); + listen_endmS = (millis() + listen_mS); //calculate the millis to stop listing at. + + keypress = 0; + + while (Serial.read() != -1); //empty serial buffer + + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXpacketCount = 0; + keypress = 0; + lora_RXONLoRa(); + + do + { + check_for_Packet(); + + if (listen_mS > 0) + { + if (millis() >= listen_endmS) + { + Serial.println(F("Listen Timeout")); + break; + } + } + } + while ((Serial.available() == 0)); + + if (Serial.available() != 0) + { + keypress = Serial.read(); + } + + if (keypress > 0) + { + Serial.println(F("Key Press")); + } + + if ( (millis() > listen_endmS) && (listen_mS != 0) ) + { + Serial.println(F("Timeout")); + keypress = 1; + } + + return keypress; +} + + +void print_mode(byte lmode) +{ + switch (lmode) + { + case TrackerMode: + Serial.print(F("Tracker Mode ")); + break; + + case SearchMode: + Serial.print(F("Search Mode ")); + break; + + case CommandMode: + Serial.print(F("Command Mode ")); + break; + + case BindMode: + Serial.print(F("Bind Mode ")); + break; + } +} + + +void send_TestRequest(char cmd) +{ + //transmit a test request + Serial.print(F("Send Test Request ")); + Serial.write(cmd); + Serial.println(); + + lora_TXBUFF[0] = cmd; + lora_QueuedSend(0, 0, Test, Broadcast, ThisNode, 10, lora_Power, default_attempts, NoStrip); //send a Test Request + delay(inter_Packet_delay); +} + + +void send_ConfigCommand(char confignum, char configdestination, char bitnum, char bitval) +{ + //transmits a config command + byte returnbyte; + Setup_LoRaCommandMode(); + bitnum = bitnum + 48; + bitval = bitval + 48; + lora_TXBUFF[0] = bitnum; //set the bitnum + lora_TXBUFF[1] = bitval; //set the bitval + + returnbyte = lora_QueuedSend(0, 1, Config0, configdestination, ThisNode, 10, lora_Power, default_attempts, NoStrip); + + if (returnbyte == 1) + { + Serial.println(F("Config Sent OK")); + print_TrackerLastSNR(); + print_TrackerLastRSSI(); + } + else + { + Serial.println(F("Config Send Failed")); + } + Serial.println(); + delay(inter_Packet_delay); +} + + +void print_TrackerLastSNR() +{ + int8_t temp; + temp = Read_Byte(0, lora_RXBUFF); + Serial.print(F("Last Tracker SNR ")); + Serial.print(temp); + Serial.println(F("dB")); +} + + +void print_TrackerLastRSSI() +{ + int8_t temp; + temp = Read_Byte(1, lora_RXBUFF); + Serial.print(F("Last Tracker RSSI ")); + Serial.print(temp); + Serial.println(F("dB")); +} + + +byte check_for_Packet() +{ + //checks to see if a packet has arrived + byte returnbyte; + +#ifdef No_DIO0_RX_Ready + returnbyte = lora_readRXready(); +#else + returnbyte = lora_readRXready2(); +#endif + + if (returnbyte == 64) + { + digitalWrite(LED1, HIGH); + lora_ReadPacket(); + lora_AddressInfo(); + lora_ReceptionInfo(); + +#ifdef LORA_AFC + check_AFC(); +#endif + + Serial.println(); + process_Packet(); + digitalWrite(LED1, LOW); + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXONLoRa(); //ready for next and clear flags + return 1; + } + + if (returnbyte == 96) + { + Serial.println(F("CRC Error")); + Serial.println(); + print_mode(modenumber); + Serial.print(F("Listen > ")); + lora_RXONLoRa(); //ready for next + } + + return 0; +} + + +void write_HABPacketMemory(byte RXStart, byte RXEnd) +{ + //stores the HAB packet in memory, FRAM or EEPROM + byte index, bufferdata; + unsigned int MemAddr = addr_StartHABPayloadData; //address in FRAM where last received HAB payload stored + + Memory_WriteByte(MemAddr, lora_RXPacketType); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXDestination); + MemAddr++; + Memory_WriteByte(MemAddr, lora_RXSource); + MemAddr++; + for (index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + Memory_WriteByte(MemAddr, bufferdata); + MemAddr++; + } + Memory_WriteByte(MemAddr, 0xFF); +} + + +void print_FightID() +{ + //send flight ID to serila terminal + byte index, bufferdata; + index = 0; + do + { + bufferdata = Flight_ID[index++]; + Serial.write(bufferdata); + } + while (bufferdata != 0); +} + + +void extract_HABPacket(byte passedRXStart, byte passedRXEnd) +{ + //extracts data from received HAB packets where first fields are lat,lon,alt. + byte tempbyte; + byte savedRXStart; + + savedRXStart = lora_RXStart; //save current value of lora_RXStart + lora_RXStart = passedRXStart; //use lora_RXStart as its global + + //Skip leading $ + do + { + tempbyte = lora_RXBUFF[lora_RXStart++]; + } + while ( tempbyte == '$'); + lora_RXStart--; + + //ID + tempbyte = sizeof(Flight_ID); + + extract_Buffer(Flight_ID, sizeof(Flight_ID)); + + print_FightID(); + Serial.print(F(" ")); + + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Lat + TRLat = extract_Float(); + + //Lon + TRLon = extract_Float(); + + //Alt + TRAlt = extract_Uint(); + + print_Tracker_Location(); + Serial.println(); + + TRSats = extract_Uint(); + lora_RXStart = next_Comma(lora_RXStart); + lora_RXStart = next_Comma(lora_RXStart); + + //Reset + TResets = extract_Uint(); + lora_RXStart = next_Comma(lora_RXStart); + TRStatus = extract_Uint(); + lora_RXStart = savedRXStart; //restore lora_RXStart, just in case +} + + +float extract_Float() +{ + //extracts a float in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte bufferdata; + float tempfloat; + do + { + bufferdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = bufferdata; + } + while (bufferdata != ','); + temp[tempptr] = 0; //terminator for string + tempfloat = (float)atof(temp); + return tempfloat; +} + + +void extract_Buffer(char * mybuffer, size_t bufSize) +{ + //extracts a buffer in ASCII format from RXbuffer + byte index, buffersize; + + buffersize = bufSize - 1; + for (index = 0; index <= buffersize; index++) + { + mybuffer[index] = lora_RXBUFF[lora_RXStart++]; + if (mybuffer[index] == ',') + { + break; + } + } + mybuffer[index] = 0; +} + + +float extract_Uint() +{ + //extracts an unsigned int in ASCII format from buffer + char temp[12]; + byte tempptr = 0; + byte buffdata; + unsigned int tempint; + do + { + buffdata = lora_RXBUFF[lora_RXStart++]; + temp[tempptr++] = buffdata; + } + while (buffdata != ','); + temp[tempptr] = 0; //terminator for string + tempint = (unsigned int)atof(temp); + return tempint; +} + + +byte next_Comma(byte localpointer) +{ + //skips through HAB packet (in CSV format) to next comma + byte bufferdata; + do + { + bufferdata = lora_RXBUFF[localpointer++]; + } + while (bufferdata != ','); + return localpointer; +} + + +/********************************************************************** + Tracker data routines +*********************************************************************** +*/ + +void extract_TRbinarylocationData() +{ + //extracts the binary location data from receive buffer and records date and time + + TRLat = Read_Float(0, lora_RXBUFF); + TRLon = Read_Float(4, lora_RXBUFF); + TRAlt = Read_UInt(8, lora_RXBUFF); +} + + +void print_TRData() +{ + //prints the last received tracker location data + Serial.print(F("Last Location ")); + Serial.print(TRLat, 5); + Serial.print(F(" ")); + Serial.print(TRLon, 5); + Serial.print(F(" ")); + Serial.println(TRAlt); +} + + +void save_TRData() +{ + //writes the last received tracker location data to memory + Memory_WriteFloat(addr_TRLat, TRLat); + Memory_WriteFloat(addr_TRLon, TRLon); + Memory_WriteUInt(addr_TRAlt, TRAlt); + +} + + +void read_TRData() +{ + //read stored tracker location data from memory + TRLat = Memory_ReadFloat(addr_TRLat); + TRLon = Memory_ReadFloat(addr_TRLon); + TRAlt = Memory_ReadUInt(addr_TRAlt); +} + + +void clear_TRData() +{ + //sets the tracker location data to zero + TRLat = 0; + TRLon = 0; + TRAlt = 0; +} + + +void print_Tracker_Location() +{ + //prints the tracker location data only + Serial.print(TRLat, 6); + Serial.print(F(",")); + Serial.print(TRLon, 6); + Serial.print(F(",")); + Serial.print(TRAlt); +} + + +void print_packet_HEX(byte RXStart, byte RXEnd) +{ + //prints contents of received packet as hexadecimal + byte bufferdata; + Serial.print(lora_RXPacketType, HEX); + Serial.print(F(" ")); + Serial.print(lora_RXDestination, HEX); + Serial.print(F(" ")); + Serial.print(lora_RXSource, HEX); + Serial.print(F(" ")); + + for (byte index = RXStart; index <= RXEnd; index++) + { + bufferdata = lora_RXBUFF[index]; + if (bufferdata < 0x10) + { + Serial.print(F("0")); + } + Serial.print(bufferdata, HEX); + Serial.print(F(" ")); + } + +} + + +void process_Packet() +{ + //process and decide what to do with received packet + unsigned int index, tempint; + byte tempbyte, ptr; + unsigned int returnedCRC; + int8_t tempchar; + + digitalWrite(LED1, HIGH); + + if (lora_RXPacketType == LocationBinaryPacket) + { + Remote_GPS_Fix = true; + + if (modenumber == SearchMode) + { + SearchMode_Packets++; + } + + if (modenumber == TrackerMode) + { + TrackerMode_Packets++; + } + + extract_TRbinarylocationData(); + save_TRData(); + + print_Tracker_Location(); + TRStatus = Read_Byte(10, lora_RXBUFF); + Serial.print(F(",")); + print_AllBits(TRStatus); + Serial.println(); + + +#ifdef UseSD + SD_WriteBinarypacket_Log(); +#endif + + + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + Serial.println(); + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth, sends two NMEA strings + Serial.println(); +#endif + + display_fix_Status(); + return; + } + + + if (lora_RXPacketType == HABPacket) + { + Remote_GPS_Fix = true; + TrackerMode_Packets++; + + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + +#ifdef UseSD + SD_WriteHABpacket_Log(); +#endif + + write_HABPacketMemory(lora_RXStart, lora_RXEnd); + extract_HABPacket(lora_RXStart, lora_RXEnd); + + save_TRData(); + + digitalWrite(LED1, LOW); + +#ifdef Use_NMEA_Bluetooth_Uplink + send_NMEA(TRLat, TRLon, TRAlt); //Send position to Bluetooth + Serial.println(); +#endif + +#ifdef USE_AFSK_RTTY_Upload + Serial.print(F("AFSK RTTY Upload ")); + Serial.println(); + start_AFSK_RTTY(); + + for (index = 0; index <= 3; index++) + { + SendAFSKRTTY('$'); + } + + for (index = lora_RXStart; index <= lora_RXEnd; index++) + { + SendAFSKRTTY(lora_RXBUFF[index]); + } + SendAFSKRTTY(13); + SendAFSKRTTY(10); + end_AFSK_RTTY(); +#endif + + display_fix_Status(); + return; + } + + + if (lora_RXPacketType == Testpacket) + { + Serial.print(F("TestPacket ")); + TestMode_Packets++; + lora_RXBuffPrint(PrintASCII); //print packet contents as ASCII + Serial.println(); + return; + } + + +#ifndef NoMenu + if (lora_RXPacketType == Bind ) + { + + Serial.println(F("Tracker Bind Received")); + ptr = 4; //set pointer to start of Bind data in lora_RXBUFF + + if (!Is_Key_Valid()) + { + return; + } + + if ((Function_Number != 5)) //only accept incoming bind request when in function 5 + { + Serial.println(F("Not in Bind Mode")); + return; + } + + Print_CRC_Bind_Memory(); + + tempint = (lora_RXBUFF[lora_RXEnd] * 256) + (lora_RXBUFF[lora_RXEnd - 1]); + + Serial.print(F("Transmitted CRC ")); + Serial.println(tempint, HEX); + returnedCRC = RXBuffer_CRC(ptr, (lora_RXEnd - 2)); + Serial.print(F("Received CRC ")); + Serial.println(returnedCRC, HEX); + + + if (returnedCRC == tempint) + { + Serial.println(F("Accepted")); + + for (index = addr_StartBindData; index <= addr_EndBindData; index++) + { + tempbyte = lora_RXBUFF[ptr++]; + Memory_WriteByte(index, tempbyte); + } + read_Settings_Memory(); //now bring the new settings into use + Print_CRC_Bind_Memory(); + } + else + { + Serial.println(F("Rejected")); + return; + } + } +#endif + + + if (lora_RXPacketType == Wakeup) + { + Serial.write(7); //print a bell + Serial.println(); + return; + } + + + if (lora_RXPacketType == NoFix) + { + NoFix_Packets++; + Serial.print(F("No Tracker GPS Fix ")); + Serial.println(NoFix_Packets); + return; + } + + if (lora_RXPacketType == NoGPS) + { + Serial.print(F("Tracker GPS Error ")); + return; + } + + + if (lora_RXPacketType == PowerUp) + { + tempint = Read_UInt(2, lora_RXBUFF); + Serial.print(F("Power Up ")); + Serial.print(tempint); + Serial.println(F("mV")); + return; + } + + + if (lora_RXPacketType == Info) + { + Serial.println(); + Serial.print(F("Tracker Last Packet Reception SNR,")); + tempchar = Read_Byte(0, lora_RXBUFF); + Serial.print(tempchar); + Serial.print(F("dB")); + tempchar = Read_Byte(1, lora_RXBUFF); + Serial.print(F(" RSSI,")); + Serial.print(tempchar); + Serial.println(F("dB")); + Serial.print(F("Battery,")); + tempint = Read_Int(2, lora_RXBUFF); + Serial.print(tempint); + Serial.print(F("mV,TRStatus,")); + tempbyte = (byte) Read_Int(4, lora_RXBUFF); + print_AllBits(tempbyte); + Serial.println(); + Serial.println(); + return; + } + + + if (lora_RXPacketType == ClearToSendCommand) + { + return; //do nothing + } + + + if (lora_RXPacketType == ClearToSend) + { + return; //do nothing + } + + + if (lora_RXPacketType == Sensor1) + { + Serial.println(F("Sensor1 Packet")); + process_Sensor1(); + } +} + + +unsigned int RXBuffer_CRC(unsigned int startaddr, unsigned int endaddr) +{ + unsigned int i, CRC; + + CRC = 0xffff; //start value for CRC16 + byte j; + + for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start + { + CRC ^= ((uint16_t) lora_RXBUFF[i] << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + return CRC; + +} + + +void process_Sensor1() +{ + float lTemperature, lHumidity, lPressure, lAltitude; + + lTemperature = Read_Float(0, lora_RXBUFF); + lHumidity = Read_Float(4, lora_RXBUFF); + lPressure = Read_Float(8, lora_RXBUFF); + lAltitude = Read_Float(12, lora_RXBUFF); + + Serial.print(F("Temperature: ")); + Serial.print(lTemperature, 2); + Serial.println(F(" degrees C")); + + Serial.print(F("%RH: ")); + Serial.print(lHumidity, 2); + Serial.println(F(" %")); + + Serial.print(F("Pressure: ")); + Serial.print(lPressure, 2); + Serial.println(F(" Pa")); + + Serial.print(F("Altitude: ")); + Serial.print(lAltitude, 2); + Serial.println(F("m")); +} + + +void print_AllBits(byte myByte) +{ + //prints bits of byte as binary + for (byte mask = 0x80; mask; mask >>= 1) { + if (mask & myByte) + Serial.print('1'); + else + Serial.print('0'); + } +} + + +void display_fix_Status() +{ + //display fix status of tracker + + if (!(bitRead(TRStatus, GPSFix))) + { + Serial.print(F("No ")); + } + + Serial.println(F("Tracker GPS fix")); +} + + +#ifdef UseSD +void SD_WriteHABpacket_Log() +{ + //write HAB packet to SD card + byte index; + + if (SD_Found) + { + logFile.write(lora_RXPacketType); + logFile.write(lora_RXDestination); + logFile.write(lora_RXSource); + logFile.print(F(",")); + + for (index = lora_RXStart; index <= lora_RXEnd; index++) + { + logFile.write(lora_RXBUFF[index]); + } + logFile.write(13); + logFile.write(10); + logFile.flush(); + } + else + { + Serial.println("No SD card !"); + } +} + + +void SD_WriteBinarypacket_Log() +{ + //send the location data in binary packet to the log + if (SD_Found) + { + logFile.write(lora_RXPacketType); + logFile.write(lora_RXDestination); + logFile.write(lora_RXSource); + logFile.print(F(",")); + logFile.print(F(",")); + SD_addLatLonAlt_Log(); + + logFile.write(13); + logFile.write(10); + logFile.flush(); + } + else + { + Serial.println(F("No SD card !")); + } +} + + +void SD_addLatLonAlt_Log() +{ + logFile.print(TRLat, 6); + logFile.print(F(",")); + logFile.print(TRLon, 6); + logFile.print(F(",")); + logFile.print(TRAlt, 6); + logFile.write(13); + logFile.write(10); +} + + +boolean setup_SDLOG() +{ + //checks if the SD card is present and can be initialised + + Serial.print(F("SD card...")); + + if (!SD.begin(SD_CS)) + { + Serial.println(F("Failed, or not present")); + SD_Found = false; + return false; //don't do anything more: + } + + Serial.print(F("Initialized OK")); + SD_Found = true; + + char filename[] = "Track000.txt"; + for (uint8_t i = 0; i < 100; i++) { + filename[6] = i / 10 + '0'; + filename[7] = i % 10 + '0'; + if (! SD.exists(filename)) { + // only open a new file if it doesn't exist + logFile = SD.open(filename, FILE_WRITE); + break; // leave the loop! + } + } + + Serial.print(F("...Writing to ")); + Serial.print(F("Track0")); + Serial.write(filename[6]); + Serial.write(filename[7]); + Serial.print(F(".txt")); + return true; +} + + +void printlog_addleadingZero(byte temp) +{ + if (temp < 10) + { + logFile.print(F("0")); + } + logFile.print(temp); +} +#endif + + +void print_CurrentLoRaSettings() +{ + //prints the current LoRa settings, reads device registers + float tempfloat; + //int tempint; + byte regdata; + unsigned long bw; + + tempfloat = lora_GetFreq(); + Serial.print(tempfloat, 3); + Serial.print(F("MHz (")); + + Serial.print(ramc_CalibrationOffset); + Serial.print(F("hz)")); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & 0xF0; + bw = lora_returnbandwidth(regdata); + Serial.print(F(" BW")); + Serial.print(bw); + + regdata = lora_Read(lora_RegModemConfig2); + regdata = (regdata & 0xF0) / 16; + Serial.print(F(" SF")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig1); + regdata = regdata & B00001110; + regdata = regdata / 2; //move right one + regdata = regdata + 4; + + Serial.print(F(" CR4/")); + Serial.print(regdata); + + regdata = lora_Read(lora_RegModemConfig3); + regdata = regdata & B00001000; + Serial.print(F(" LDROPT_")); + if (regdata == 8) + { + Serial.print(F("ON")); + } + else + { + Serial.print(F("OFF")); + } + + regdata = lora_Read(lora_RegPaConfig); + regdata = regdata - 0xEE; + + Serial.print(F(" Power ")); + Serial.print(regdata); + Serial.print(F("dBm")); + Serial.println(); +} + + +void system_Error() +{ + //there is a error, likley no LoRa device found, cannot continue + while (1) + { + digitalWrite(LED1, HIGH); + delay(50); + digitalWrite(LED1, LOW); + delay(50); + } +} + + +void led_Flash(unsigned int flashes, unsigned int dealymS) +{ + //flash LED to show tracker is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(dealymS); + digitalWrite(LED1, LOW); + delay(dealymS); + } +} + + +void read_Settings_Defaults() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Configuring Settings from Defaults")); + ramc_CalibrationOffset = CalibrationOffset; + ramc_TrackerMode_Frequency = TrackerMode_Frequency; + ramc_CommandMode_Frequency = CommandMode_Frequency; + ramc_SearchMode_Frequency = SearchMode_Frequency; + ramc_TrackerMode_Bandwidth = TrackerMode_Bandwidth; + ramc_TrackerMode_SpreadingFactor = TrackerMode_SpreadingFactor; + ramc_TrackerMode_CodeRate = TrackerMode_CodeRate; + ramc_CommandMode_Bandwidth = CommandMode_Bandwidth; + ramc_CommandMode_SpreadingFactor = CommandMode_SpreadingFactor; + ramc_CommandMode_CodeRate = CommandMode_CodeRate; + ramc_SearchMode_Bandwidth = SearchMode_Bandwidth; + ramc_SearchMode_SpreadingFactor = SearchMode_SpreadingFactor; + ramc_SearchMode_CodeRate = SearchMode_CodeRate; + ramc_TrackerMode_Power = TrackerMode_Power; + ramc_SearchMode_Power = SearchMode_Power; + ramc_CommandMode_Power = CommandMode_Power; +} + + +void read_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver. + Serial.println(F("Configuring Settings from Memory")); + ramc_CalibrationOffset = Memory_ReadInt(addr_CalibrationOffset); + ramc_TrackerMode_Frequency = Memory_ReadULong(addr_TrackerMode_Frequency); + ramc_CommandMode_Frequency = Memory_ReadULong(addr_CommandMode_Frequency); + ramc_SearchMode_Frequency = Memory_ReadULong(addr_SearchMode_Frequency); + ramc_TrackerMode_Bandwidth = Memory_ReadByte(addr_TrackerMode_Bandwidth); + ramc_TrackerMode_SpreadingFactor = Memory_ReadByte(addr_TrackerMode_SpreadingFactor); + ramc_TrackerMode_CodeRate = Memory_ReadByte(addr_TrackerMode_CodeRate); + ramc_CommandMode_Bandwidth = Memory_ReadByte(addr_CommandMode_Bandwidth); + ramc_CommandMode_SpreadingFactor = Memory_ReadByte(addr_CommandMode_SpreadingFactor); + ramc_CommandMode_CodeRate = Memory_ReadByte(addr_CommandMode_CodeRate); + ramc_SearchMode_Bandwidth = Memory_ReadByte(addr_SearchMode_Bandwidth); + ramc_SearchMode_SpreadingFactor = Memory_ReadByte(addr_SearchMode_SpreadingFactor); + ramc_SearchMode_CodeRate = Memory_ReadByte(addr_SearchMode_CodeRate); + ramc_TrackerMode_Power = Memory_ReadByte(addr_TrackerMode_Power); + ramc_SearchMode_Power = Memory_ReadByte(addr_SearchMode_Power); + ramc_CommandMode_Power = Memory_ReadByte(addr_CommandMode_Power); +} + + +void write_Settings_Memory() +{ + //To ensure the program routines are as common as possible betweeen transmitter and receiver + //this receiver program uses constants in RAM copied from memory in the same way as the transmitter. + //There are some exceptions, where the local programs need to use a setting unique to the particular + //receiver.. + Serial.println(F("Writing RAM Settings to Memory")); + Memory_Set(addr_StartConfigData, addr_EndConfigData, 0); //clear memory area first + Memory_WriteInt(addr_CalibrationOffset, ramc_CalibrationOffset); + Memory_WriteULong(addr_TrackerMode_Frequency, ramc_TrackerMode_Frequency); + Memory_WriteULong(addr_CommandMode_Frequency, ramc_CommandMode_Frequency); + Memory_WriteULong(addr_SearchMode_Frequency, ramc_SearchMode_Frequency); + Memory_WriteByte(addr_TrackerMode_Bandwidth, ramc_TrackerMode_Bandwidth); + Memory_WriteByte(addr_TrackerMode_SpreadingFactor, ramc_TrackerMode_SpreadingFactor); + Memory_WriteByte(addr_TrackerMode_CodeRate, ramc_TrackerMode_CodeRate); + Memory_WriteByte(addr_CommandMode_Bandwidth, ramc_CommandMode_Bandwidth); + Memory_WriteByte(addr_CommandMode_SpreadingFactor, ramc_CommandMode_SpreadingFactor); + Memory_WriteByte(addr_CommandMode_CodeRate, ramc_CommandMode_CodeRate); + Memory_WriteByte(addr_SearchMode_Bandwidth, ramc_SearchMode_Bandwidth); + Memory_WriteByte(addr_SearchMode_SpreadingFactor, ramc_SearchMode_SpreadingFactor); + Memory_WriteByte(addr_SearchMode_CodeRate, ramc_SearchMode_CodeRate); + Memory_WriteByte(addr_TrackerMode_Power, ramc_TrackerMode_Power); + Memory_WriteByte(addr_SearchMode_Power, ramc_SearchMode_Power); + Memory_WriteByte(addr_CommandMode_Power, ramc_CommandMode_Power); +} + + +void Serialprint_addleadingZero(byte temp) +{ + if (temp < 10) + { + Serial.print(F("0")); + } + Serial.print(temp); +} + +//******************************************************************************************************* +// Memory Routines +//******************************************************************************************************* + + +void Clear_All_Memory() +{ + //clears the whole of memory, normally 1kbyte + Serial.print(F("Clearing All Memory")); + Memory_Set(addr_StartMemory, addr_EndMemory, 0); +} + + +void Print_CRC_Bind_Memory() +{ + unsigned int returnedCRC = Memory_CRC(addr_StartBindData, addr_EndBindData); + Serial.print(F("CRC_Bind_Memory ")); + Serial.println(returnedCRC, HEX); +} + + +//******************************************************************************************************* + + +void print_Nodes() +{ + //prints current node of this device + Serial.print(F("This Node ")); + Serial.write(ThisNode); + Serial.println(); +} + + +void print_last_HABpacket() +{ + //prints last received HAB packet to serial terminal + byte memorydata; + unsigned int address; + address = addr_StartHABPayloadData; + + Serial.print(F("Last HAB Packet ")); + do + { + memorydata = Memory_ReadByte(address); + if ((memorydata == 0xFF) || (address >= addr_EndHABPayloadData)) + { + break; + } + Serial.write(memorydata); + address++; + } + while (true); + Serial.println(); +} + + +void Setup_LoRaTrackerMode() +{ + //sets LoRa modem to Tracker mode + lora_SetFreq(ramc_TrackerMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_TrackerMode_Bandwidth, ramc_TrackerMode_SpreadingFactor, ramc_TrackerMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_TrackerMode_Power; + modenumber = TrackerMode; +} + + +void Setup_LoRaSearchMode() +{ + //sets LoRa modem to Search mode + lora_SetFreq(ramc_SearchMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_SearchMode_Bandwidth, ramc_SearchMode_SpreadingFactor, ramc_SearchMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_SearchMode_Power; + modenumber = SearchMode; +} + +void Setup_LoRaCommandMode() +{ + //sets LoRa modem to Command mode + lora_SetFreq(ramc_CommandMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(ramc_CommandMode_Bandwidth, ramc_CommandMode_SpreadingFactor, ramc_CommandMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = ramc_CommandMode_Power; + modenumber = CommandMode; +} + + +void Setup_LoRaBindMode() +{ + //sets LoRa modem to Bind mode + lora_SetFreq(BindMode_Frequency, ramc_CalibrationOffset); + lora_SetModem2(BindMode_Bandwidth, BindMode_SpreadingFactor, BindMode_CodeRate, Explicit); //Setup the LoRa modem parameters + lora_Power = BindMode_Power; + modenumber = BindMode; +} + + +void display_frequency() +{ + //display current set frequency of LoRa device + float freq_temp; + freq_temp = lora_GetFreq(); + Serial.print(F("Set to Frequency ")); + Serial.print(freq_temp, 3); + Serial.println(F("MHz")); +} + + + +void display_frequencies_memory() +{ + //display the frequncies set in memory, good check to see if all is well with memory + unsigned long freq_temp; + freq_temp = Memory_ReadULong(addr_TrackerMode_Frequency); + Serial.print(F("TrackerMode ")); + Serial.println(freq_temp); + freq_temp = Memory_ReadULong(addr_SearchMode_Frequency); + Serial.print(F("SearchMode ")); + Serial.println(freq_temp); + freq_temp = Memory_ReadULong(addr_CommandMode_Frequency); + Serial.print(F("CommandMode ")); + Serial.println(freq_temp); + Serial.println(); + +} + + +void setstatusByte(byte bitnum, byte bitval) +{ + //program the status byte +#ifdef Debug + if (bitval) + { + Serial.print(F("Set Status Bit ")); + } + else + { + Serial.print(F("Clear Status Bit ")); + } + + Serial.println(bitnum); +#endif + + if (bitval == 0) + { + bitClear(TRStatus, bitnum); + } + else + { + bitSet(TRStatus, bitnum); + } +} + + +void setup() +{ + //needs no explanation I hope ............... + + pinMode(LED1, OUTPUT); //setup pin for PCB LED + led_Flash(2, 250); + + Serial.begin(38400); //setup Serial console ouput + Serial.println(); + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(aurthorname)); + Serial.println(); + + SPI.begin(); //initialize SPI: + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + pinMode(lora_NReset, OUTPUT); //LoRa Device reset line + pinMode (lora_NSS, OUTPUT); //LoRa Device select line + digitalWrite(lora_NSS, HIGH); + digitalWrite(lora_NReset, HIGH); + delay(1); + + Memory_Start(); + +#ifdef ClearAllMemory + Clear_All_Memory(); + Serial.println(); + Serial.println(); +#endif + + +#ifdef ClearConfigData + Clear_Config_Memory(); +#endif + + +#ifdef ConfigureDefaults + read_Settings_Defaults(); + write_Settings_Memory(); + Serial.println(); + Serial.flush(); +#endif + +#ifdef ConfigureFromMemory + read_Settings_Memory(); +#endif + + Print_CRC_Bind_Memory(); + + read_TRData(); + + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); //redo faster SPI as changed by display_setup + + if (!lora_CheckDevice()) + { + Serial.println(F("LoRa Error!")); + led_Flash(40, 50); + } + + lora_Setup(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial_Setup(); +#endif + + print_Nodes(); + Serial.println(); + + Setup_LoRaTrackerMode(); + + Serial.println(); + lora_Print(); + Serial.println(); + Serial.flush(); + +#ifdef CalibrateTone + digitalWrite(LED1, HIGH); //turn on LED + lora_Tone(1000, 3000, 10); //Transmit an FM tone, 1000hz, 1000ms, 10dBm + digitalWrite(LED1, LOW); //LED is off + delay(1000); +#endif + + lora_RXONLoRa(); + +#ifdef UseSD + setup_SDLOG(); //setup SD and delay a bit to ensure any pending ints cleared +#endif + + Serial.println(); + print_last_HABpacket(); + print_TRData(); + Serial.println(); + + Serial.println(); + display_frequencies_memory(); + +#ifdef Use_NMEA_Bluetooth_Uplink + Bluetooth_Serial.println(F("Bluetooth Active")); +#endif + +} + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_Beta_240118/Basic_Receiver_Terminal_Settings.h b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_Beta_240118/Basic_Receiver_Terminal_Settings.h new file mode 100644 index 0000000..9aa6e49 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Basic_Receiver_Terminal_Beta_240118/Basic_Receiver_Terminal_Settings.h @@ -0,0 +1,166 @@ +//Basic_Receiver_Terminal_Settings.h +/* +****************************************************************************************************** + +LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without +the explicit permission of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the +intended purpose and free from errors. + +Note that if you select all possible options, SD Card logging, Bluetooth NMEA uplink and AFSK RTTY +upload you will run out of memory whne the ATMEGA328 is in use, cannot do much about it. + +To Do: +disable bind mode when menu not selected + +****************************************************************************************************** +*/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify board type here +//************************************************************************************************** + +//#define UseSD //define if there is an SD card attached +#define Board_Definition "LCD_Receiver_Board_Definitions.h" //define the board type to be used + + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +//#define ClearConfigData //at startup zero the config memory +//#define ClearAllMemory //at startup clears from start memory to end memory, normally 1kbyte, needs to be followed by ConfigureDefaults +#define ConfigureDefaults //at startup configure settings from default program defaults, these are then stored in memory +//#define ConfigureFromMemory //at startup configure settings from values stored in memory, this needs to be the active mode for bind to work + +#define CalibrateTone //comment in to have a calibrate tone at startup + + + +//#define NoMenu + +//************************************************************************************************** +// 3) Frequency settings +//************************************************************************************************** + +//Tracker mode +const unsigned long TrackerMode_Frequency = 434400000; + +//Search mode +const unsigned long SearchMode_Frequency = 434300000; + +//Command mode +const unsigned long CommandMode_Frequency = 434500000; + +//Bind mode - Change this with great care !!!!! +const unsigned long BindMode_Frequency = 434100000; + +//this is the LoRa module frequency calibration offset in Hertz +const int CalibrationOffset = 0; + +//************************************************************************************************** +// 4) LoRa settings +//************************************************************************************************** + +#define LoRa_Device_in_MB1 //if using a MikroBus based specify the socket for the LoRa Device + +//#define LORADEBUG //if defined prints some LoRa debug information to serial monitor +#define LORA_AFC //define this if using the afc function + +//Tracker mode +const byte TrackerMode_Power = 10; +#define TrackerMode_Bandwidth BW7800 +#define TrackerMode_SpreadingFactor SF8 +#define TrackerMode_CodeRate CR45 + +//Search mode +const byte SearchMode_Power = 10; +#define SearchMode_Bandwidth BW62500 +#define SearchMode_SpreadingFactor SF12 +#define SearchMode_CodeRate CR45 + +//Command mode +const byte CommandMode_Power = 5; +#define CommandMode_Bandwidth BW62500 +#define CommandMode_SpreadingFactor SF10 +#define CommandMode_CodeRate CR45 + + +//Bind mode - Change this with great care !!!!! +const byte BindMode_Power = 2; +#define BindMode_Bandwidth BW500000 +#define BindMode_SpreadingFactor SF8 +#define BindMode_CodeRate CR45 + +const byte Deviation = 0x52; //typical deviation for tones +const byte lora_RXBUFF_Size = 128; +const byte lora_TXBUFF_Size = 128; + + +#define RemoteControlNode 'G' //normally used by tracker transmitter in promiscuous_Mode +#define ControlledNode '1' //normally used by tracker transmitter in promiscuous_Mode +#define ThisNode ControlledNode +const boolean Promiscuous_Mode = true; //if set to false remote control packets from any node accepted +const int inter_Packet_delay = 500; //allows time for receiver to be ready to see a possible reply +const byte Cmd_WaitSecs = 15; //number of seconds to stay in command mode +const byte default_attempts = 5; //default number of times a command will attempt to be sent + + +//Protected Command Settings +const char key0 = 'L'; //Used to restrict access to some commands +const char key1 = 'o'; +const char key2 = 'R'; +const char key3 = 'a'; + +//#define No_DIO0_RX_Ready //needed for boards that cannot directly ready the DIO0 pin + + + +//************************************************************************************************** +// 6) Which Memory to use for storage +//************************************************************************************************** + +#define Memory_Library "I2CFRAM_MB85RC16PNF.h" +//#define Memory_Library "EEPROM_Memory.h" +//#define Memory_Library "SPIFRAM_Memory_FM25CL64B_MB85RS64.h" //define this file if a SPI FRAM is in use + + +//************************************************************************************************** +// 9) AFSK RTTY Options +//************************************************************************************************** + +//#define USE_AFSK_RTTY_Upload +const int AFSKrttybaud = 1465; //delay in uS x 2 for 1 bit and 300baud. Decode range in FLDIGI 1420 to 1510 +const int afskleadinmS = 500; //number of ms for AFSK constant lead in tone +const int tonehighHz = 1000; //high tone in Hertz +const int tonelowHz = 650; //low tone in Hertz + + +//************************************************************************************************** +// 10) Bluetooth Options +//************************************************************************************************** + +//#define Use_NMEA_Bluetooth_Uplink //define if your going to use a Bluetooth adapter to uplink NMEA into a mapping application +#define USE_SendOnlySoftwareSerial //if you want the Bluetooth device on a pin other than the hardware serial port, define this +#define USE_HardwareSerial //use hardware serial port to send Bluetooth +#define Hardware_Bluetooth_Port Serial //Which Hardware port to use for Bluetooth +#define BluetoothBaud 9600 + +const byte Bluetooth_Buff_Size = 128; //size of buffer for NMEA output + + +//************************************************************************************************** +// 12) Miscellaneous program settings +//************************************************************************************************** + +const unsigned int switch_delay = 1000; //delay in mS after a switch\key press before another can take place + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Configuring the Receiver Programs.doc b/LoRa/LoRaTracker/Receiver1/Programs/Configuring the Receiver Programs.doc new file mode 100644 index 0000000..fd1cc0c Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Programs/Configuring the Receiver Programs.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/Programs/README.md b/LoRa/LoRaTracker/Receiver1/Programs/README.md new file mode 100644 index 0000000..15a4bef --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/README.md @@ -0,0 +1,41 @@ +This folder contains the current version of the LoRaTracker Receiver1 programs. + +The ‘basic’ receiver programs are a cut down versions of the Receiver2 program (designed for ATMEGA1284P) +that will run on simple ATMEGA328P hardware such as the very low cost Arduino Pro Mini 3.3V. + +The terminal receiver program provides the remote control interface to the HAB tracker that allows it to +be controlled and configured whilst it is in flight. + +The portable receiver program displays the tracker location on a display and if a local GPS is fitted then +the receiver will show the distance and direction to the tracker. The receiver can switch between normal +tracker mode, and long distance search mode by pressing the receivers switch. The program will run on most +of the ATMEGA328P based LoRaTracker boards, including the trackers themselves, see examples in the pictures +folder. Currently supported displays are the SD1306 OLED and 20x4 LCD (3.3Version). Future display options +will be the ILI9341 TFT and Nokia 5110. + +The third version of the basic receiver software is for use with boards that have an SD card connected, +the receiver then acts as a logger, recording all received packets to a file on the SD card. + +The programs requre the installation of the current LoRaTracker Library files see here; + +https://github.com/LoRaTracker/LoRaTracker-Library + + + +Configuring the Receivers +------------------------- + +The Receiver programs are configured using the settings file found in the programs directory. Whilst the +programs make a number of configuration options possible, all the LoRaTracker programs tracker transmitters +and receivers have the same basic LoRa and frequency default settings. So for a working setup all you need do +to make sure the settings file is configured as follows; + +1. Select the appropriate board definition file in section '1) Hardware related definitions and options +2. Select the appropriate GPS in section'5) GPS Options' +3. Select the appropriate display connected (in any) in section '7) Display Settings' + +See 'Configuring the Receiver Programs.doc' for further details. + + + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Self Tracking with LoRa - Bluetooth to Android.doc b/LoRa/LoRaTracker/Receiver1/Programs/Self Tracking with LoRa - Bluetooth to Android.doc new file mode 100644 index 0000000..54abf22 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Programs/Self Tracking with LoRa - Bluetooth to Android.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_20x4_LCD_Test/I2C_20x4_LCD_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_20x4_LCD_Test/I2C_20x4_LCD_Test.ino new file mode 100644 index 0000000..5f65dc1 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_20x4_LCD_Test/I2C_20x4_LCD_Test.ino @@ -0,0 +1,65 @@ +//I2C_20x4_LCD_Test.ino +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + Test program for 20x4 LCD display, driven via the PCF8563 I2C I\O expander + + +************************************************************************************************** +*/ +#include //Comes with Arduino IDE +#include //https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/ (version 1.3.4) +#include "I2C_Scanner.h" + +#define PCF8574Address 0x3F //address of PCF8574. This define allows the address to be specified, normally 0x27 or 0x3F +LiquidCrystal_I2C disp(PCF8574Address, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //Set the LCD I2C address and pins used + +void loop() +{ +disp.setCursor(0,0); //Start at character 4 on line 0 +disp.print("www.LoRaTracker.uk"); +delay(1000); +disp.setCursor(0,1); +disp.print("I2C LCD Backpack"); // Print text on 2nd Line +delay(1000); +disp.setCursor(0,2); +disp.print("0123456789ABCDEFGHIJ"); //Print 20 characters on 3rd line +delay(1000); +disp.setCursor(0,3); +disp.print("Last Line of Text"); +delay(3000); +disp.clear(); +delay(1000); +} + + + +void setup() +{ + Serial.begin(38400); + + setup_I2CScan(); + run_I2CScan(); + + disp.begin(20,4); //initialize the lcd for 20 chars 4 lines, turn on backlight + disp.backlight(); //backlight on + +} + + + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_20x4_LCD_Test/I2C_Scanner.h b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_20x4_LCD_Test/I2C_Scanner.h new file mode 100644 index 0000000..e1d3d08 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_20x4_LCD_Test/I2C_Scanner.h @@ -0,0 +1,84 @@ + // -------------------------------------- + // i2c_scanner + // + // Version 1 + // This program (or code that looks like it) + // can be found in many places. + // For example on the Arduino.cc forum. + // The original author is not know. + // Version 2, Juni 2012, Using Arduino 1.0.1 + // Adapted to be as simple as possible by Arduino.cc user Krodal + // Version 3, Feb 26 2013 + // V3 by louarnold + // Version 4, March 3, 2013, Using Arduino 1.0.3 + // by Arduino.cc user Krodal. + // Changes by louarnold removed. + // Scanning addresses changed from 0...127 to 1...119, + // according to the i2c scanner by Nick Gammon + // http://www.gammon.com.au/forum/?id=10896 + // Version 5, March 28, 2013 + // As version 4, but address scans now to 127. + // A sensor seems to use address 120. + // Version 6, November 27, 2015. + // Added waiting for the Leonardo serial communication. + // + // + // This sketch tests the standard 7-bit addresses + // Devices with higher bit address might not be seen properly. + // + + + //#include + + + void setup_I2CScan() + { + Wire.begin(); + + //Serial.begin(9600); + Serial.println("I2C Scanner"); + } + + + void run_I2CScan() + { + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found"); + else + Serial.println("done"); + + Wire.endTransmission(); + } + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_Scanner_Test/I2C_Scanner.h b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_Scanner_Test/I2C_Scanner.h new file mode 100644 index 0000000..0f77699 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_Scanner_Test/I2C_Scanner.h @@ -0,0 +1,74 @@ + // -------------------------------------- + // i2c_scanner + // + // Version 1 + // This program (or code that looks like it) + // can be found in many places. + // For example on the Arduino.cc forum. + // The original author is not know. + // Version 2, Juni 2012, Using Arduino 1.0.1 + // Adapted to be as simple as possible by Arduino.cc user Krodal + // Version 3, Feb 26 2013 + // V3 by louarnold + // Version 4, March 3, 2013, Using Arduino 1.0.3 + // by Arduino.cc user Krodal. + // Changes by louarnold removed. + // Scanning addresses changed from 0...127 to 1...119, + // according to the i2c scanner by Nick Gammon + // http://www.gammon.com.au/forum/?id=10896 + // Version 5, March 28, 2013 + // As version 4, but address scans now to 127. + // A sensor seems to use address 120. + // Version 6, November 27, 2015. + // Added waiting for the Leonardo serial communication. + // + // + // This sketch tests the standard 7-bit addresses + // Devices with higher bit address might not be seen properly. + // + + + + + void run_I2CScan() + { + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found"); + else + Serial.println(); + + Wire.endTransmission(); + } + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_Scanner_Test/I2C_Scanner_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_Scanner_Test/I2C_Scanner_Test.ino new file mode 100644 index 0000000..ec9549b --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/I2C_Scanner_Test/I2C_Scanner_Test.ino @@ -0,0 +1,61 @@ +#define programname "I2C_Scanner" +#define dateproduced "2/10/2017" +#define aurthorname "Stuart Robinson" + +/* +******************************************************************************************************************************** + +Easy Build LoRaTracker Programs for Arduino + +Copyright of the author Stuart Robinson - 2/10/2017 + +http://www.LoRaTracker.uk + +These programs may be used free of charge for personal, recreational and educational purposes only. + +This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission +of the author Stuart Robinson. + +The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and +free from errors. + +This program scans each address on the I2C bus and reports if a device was found, examples. + +BME280 Sensor 0x76 +UBLOX GPS 0x42 +MB85RC16PNF FRAM 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 + + +******************************************************************************************************************************** +*/ + + +#include +#include +#include "I2C_Scanner.h" +#include "Locator2_Board_Definitions.h" + +unsigned int scancount; + +void loop() +{ + scancount++; + Serial.println(); + Serial.print(scancount); + Serial.print(" "); + run_I2CScan(); + delay(1000); +} + + + +void setup() +{ + Serial.begin(38400); //setup Serial console ouput + Serial.println(F(programname)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + Serial.println(); + } + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Interrupt_Switch_LED_Test/Interrupt_Switch_LED_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Interrupt_Switch_LED_Test/Interrupt_Switch_LED_Test.ino new file mode 100644 index 0000000..f0662ca --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Interrupt_Switch_LED_Test/Interrupt_Switch_LED_Test.ino @@ -0,0 +1,97 @@ +#define programname "Interrupt_Switch_LED_Test" +#define programversion "V1.0" +#define dateproduced "04/10/2017" +#define aurthorname "Stuart Robinson" + +/* +******************************************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino ATMEGA328 + + Copyright of the author Stuart Robinson - 04/10/2017 + + http://www.LoRatracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + This program uses interrupts to detect switch operation on the SWITCH1 pin. You can either define this locally or inclued the + appropriate board definition file, SWITCH1 and LED1 are defined for most boards. + + For every SWITCH1 press the LED1 is toggled but there is no switch debounce, and you may see multiple interrupts counted. + +******************************************************************************************************************************** +*/ +#include + +unsigned int SWITCH1_Interrupt_Count; + +//#define SWITCH1 A1 //local defines +//#define LED1 8 //local defines + +#include "Locator2_Board_Definitions.h" + +#include "Program_Definitions.h" +#include "PinChangeInterrupt.h" //https://github.com/NicoHood/PinChangeInterrupt + + +void loop() +{ + + +} + + +void interrupt_detected_SWITCH1() +{ + SWITCH1_Interrupt_Count++; + digitalWrite(LED1, !digitalRead(LED1)); //toggle the LED + Serial.print("SWITCH1_Interrupt_Count "); + Serial.println(SWITCH1_Interrupt_Count); + delay(500); +} + + +void setup_interrupts() +{ + Serial.println("setup_interrupts()"); + attachPCINT(digitalPinToPCINT(SWITCH1), interrupt_detected_SWITCH1, CHANGE); +} + + +void led_FlashStart() +{ + byte i; + Serial.println("led_FlashStart()"); + for (i = 0; i <= 4; i++) + { + digitalWrite(LED1, HIGH); + delay(150); + digitalWrite(LED1, LOW); + delay(150); + } +} + + +void setup() +{ + Serial.begin(38400); //setup Serial console ouput + + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + + pinMode(LED1, OUTPUT); //for PCB LED + led_FlashStart(); + + pinMode(SWITCH1, INPUT_PULLUP); + + setup_interrupts(); + delay(500); +} diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/LoRa_Test/LoRa_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/LoRa_Test/LoRa_Test.ino new file mode 100644 index 0000000..c59feca --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/LoRa_Test/LoRa_Test.ino @@ -0,0 +1,136 @@ +//LoRa_Test.ino +/* +************************************************************************************************** + + LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without + the explicit permission of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + Test program for LoRa device, prints registers and transmits an FM tone on selected frequency. + +************************************************************************************************** +*/ + +#define programname "LoRa_Test" +#define programversion "V1.0" +#define dateproduced "031017" +#define aurthorname "Stuart Robinson" +#include +#include "Program_Definitions.h" + +byte keypress; //used in LoRa routines, so needs to be defined +const byte lora_RXBUFF_Size = 1; +const byte lora_TXBUFF_Size = 1; +const byte Deviation = 0x52; //typical deviation for tones + + +#include "Locator2_Board_Definitions.h" + +#include +#include "LoRa3.h" + + +#define TrackerMode_Frequency 433400000 //transmit frequency in hertz for tones +#define TrackerMode_Power 10 +#define CalibrationOffset 28900 //this is the LoRa module frequency calibration offset in Hertz + +unsigned int seq = 1; + + +void loop() +{ + + Serial.print("Start Test Loop "); + Serial.println(seq++); + Serial.println(); + + Setup_LoRaTrackerMode(); + + lora_Print(); + Serial.println(); + Serial.println(F("LoRa Tone")); + lora_Tone(1000, 3000, 10); //Transmit an FM tone, 1000hz, 3000ms + delay(2000); +} + + +void Setup_LoRaTrackerMode() +{ + //sets LoRa modem to Tracker mode + lora_SetFreq(TrackerMode_Frequency, CalibrationOffset); +} + + + +void led_FlashStart() +{ + byte i; + for (i = 0; i <= 4; i++) + { + digitalWrite(LED1, HIGH); + delay(250); + digitalWrite(LED1, LOW); + delay(250); + } +} + + +void systemerror() +{ + while (1) + { + digitalWrite(LED1, HIGH); + delay(100); + digitalWrite(LED1, LOW); + delay(100); + } +} + + + +void setup() +{ + Serial.begin(38400); //setup Serial console output + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + Serial.println(); + + pinMode(LED1, OUTPUT); //for PCB LED + led_FlashStart(); + + pinMode(lora_NReset, OUTPUT); //LoRa Device reset pin + pinMode (lora_NSS, OUTPUT); //LoRa Device select pin + digitalWrite(lora_NSS, HIGH); + digitalWrite(lora_NReset, HIGH); + + SPI.begin(); //initialize SPI + + SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + + if (lora_CheckDevice() == true) + { + lora_Setup(); //Do the initial LoRa Setup + Setup_LoRaTrackerMode(); + + Serial.println(); + } + else + { + Serial.println(F("LoRa Device Error")); + systemerror(); + } + + +} diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Memory_Test/I2C_Scanner.h b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Memory_Test/I2C_Scanner.h new file mode 100644 index 0000000..e1d3d08 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Memory_Test/I2C_Scanner.h @@ -0,0 +1,84 @@ + // -------------------------------------- + // i2c_scanner + // + // Version 1 + // This program (or code that looks like it) + // can be found in many places. + // For example on the Arduino.cc forum. + // The original author is not know. + // Version 2, Juni 2012, Using Arduino 1.0.1 + // Adapted to be as simple as possible by Arduino.cc user Krodal + // Version 3, Feb 26 2013 + // V3 by louarnold + // Version 4, March 3, 2013, Using Arduino 1.0.3 + // by Arduino.cc user Krodal. + // Changes by louarnold removed. + // Scanning addresses changed from 0...127 to 1...119, + // according to the i2c scanner by Nick Gammon + // http://www.gammon.com.au/forum/?id=10896 + // Version 5, March 28, 2013 + // As version 4, but address scans now to 127. + // A sensor seems to use address 120. + // Version 6, November 27, 2015. + // Added waiting for the Leonardo serial communication. + // + // + // This sketch tests the standard 7-bit addresses + // Devices with higher bit address might not be seen properly. + // + + + //#include + + + void setup_I2CScan() + { + Wire.begin(); + + //Serial.begin(9600); + Serial.println("I2C Scanner"); + } + + + void run_I2CScan() + { + byte error, address; + int nDevices; + + Serial.println("Scanning..."); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found"); + else + Serial.println("done"); + + Wire.endTransmission(); + } + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Memory_Test/Memory_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Memory_Test/Memory_Test.ino new file mode 100644 index 0000000..d945f4c --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Memory_Test/Memory_Test.ino @@ -0,0 +1,126 @@ +#define programname "Memory_Test" +#define programversion "V1.0" +#define dateproduced "04/10/2017" +#define aurthorname "Stuart Robinson" + +/* +******************************************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 04/10/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + This program tests the non-volatile memory. At reset it first reads a float stored in the first four memory locations. It then + increments the value, writes it to memory and reads it back in loop. Thus if you let the test run for a while and observe the last + printed float value, then power off or reset, on restart you can check if the values has been saved and survived power off correctly. + + After the first read the program multiplies the floats by a set value and write the new values out to memory. + + Note: If the floats calculated or retrieved are corrupted or exceed the limit then to may be print to serial terminal as; + + 'nan' = not a number + 'ovf' = overflow + +******************************************************************************************************************************** +*/ +#include + + +#include "I2CFRAM_MB85RC16PNF.h" //library file for MB85RC16PNF +//#include "EEPROM_Memory.h" //Library file for ATMEGA Internal EEPROM + +#include "Locator2_Board_Definitions.h" //include definitions file for board type + + +#include "Program_Definitions.h" +#include +#include "I2C_Scanner.h" + + +void loop() +{ + float data; + unsigned long cleartimemS; + + Serial.println(F("Testing Memory")); + Serial.println(); + Print_Memory(0, 255); + Serial.println(); + + data = Memory_ReadFloat(0); + + Serial.print(F("Memory at Reset ")); + Serial.println(data,6); + + Serial.print(F("Clearing first 256 bytes of Memory ")); + cleartimemS = millis(); + Memory_Set(0, 0xff, 0); + Serial.print(F(" - Done - ")); + cleartimemS = millis() - cleartimemS; + Serial.print(cleartimemS); + Serial.println(F("mS")); + Print_Memory(0, 255); + + data = 1; + + while (1) + { + data = data * 1.23456; + Serial.print(F("Writing Memory as ")); + Serial.print(data,6); + Memory_WriteFloat(0, data); + Serial.print(F(" Reading Memory as ")); + data = Memory_ReadFloat(0); + Serial.println(data,6); + delay(1000); + } + +} + +void led_FlashStart() +{ + byte i; + for (i = 0; i <= 1; i++) + { + digitalWrite(LED1, HIGH); + delay(100); + digitalWrite(LED1, LOW); + delay(100); + } +} + + + + + +void setup() +{ + pinMode(LED1, OUTPUT); //for PCB LED + Serial.println(F("LED Flash")); + led_FlashStart(); + + Serial.begin(38400); //setup Serial console ouput + Serial.println(F(programname)); + Serial.println(F(programversion)); + Serial.println(F(dateproduced)); + Serial.println(F(aurthorname)); + Serial.println(); + + setup_I2CScan(); + run_I2CScan(); + + Memory_Start(); + +} + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/SD1306_Display_Test/SD1306_Display_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/SD1306_Display_Test/SD1306_Display_Test.ino new file mode 100644 index 0000000..f760f72 --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/SD1306_Display_Test/SD1306_Display_Test.ino @@ -0,0 +1,61 @@ +//SD1306_Display_Test.ino +/* +************************************************************************************************** + + Easy Build LoRaTracker Programs for Arduino + + Copyright of the author Stuart Robinson - 05/10/2017 + + http://www.LoRaTracker.uk + + These programs may be used free of charge for personal, recreational and educational purposes only. + + This program, or parts of it, may not be used for or in connection with any commercial purpose without the explicit permission + of the author Stuart Robinson. + + The programs are supplied as is, it is up to individual to decide if the programs are suitable for the intended purpose and + free from errors. + + This test program uses the ASCII only SD1306 driver library; //https://github.com/greiman/SSD1306Ascii + ************************************************************************************************** + +*/ + + +#include "Display_SD1306_AVR.h" //LoRaTracker Library file that uses text only library for low memory footprint +unsigned int count = 0; + + +void loop(void) +{ + Serial.println(F("Running Display Test")); + Display_SetCurPos(0, 0); + Display_SetTextSize(1); + disp.print("www.LoRaTracker.uk"); + Display_SetCurPos(0, 1); + disp.print("Hello World!"); + Display_SetCurPos(0, 2); + disp.print("Small Text"); + Display_SetTextSize(2); + Display_SetCurPos(0, 5); + disp.print("Large Text"); + Display_Update(); + delay(2000); + Display_Clear(); + Display_Update(); + delay(1000); +} + + +void setup(void) +{ + Serial.begin(38400); + Serial.print("SD1306 Display Test"); + + Display_Setup(); +} + + + + + diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Serial_GPS_Echo_Test/Serial_GPS_Echo_Test.ino b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Serial_GPS_Echo_Test/Serial_GPS_Echo_Test.ino new file mode 100644 index 0000000..8eb464d --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/Programs/Test Programs/Serial_GPS_Echo_Test/Serial_GPS_Echo_Test.ino @@ -0,0 +1,39 @@ +/* + This is a very simpel program that will read characters from the GPS and put them on the serial monitor + If your ever having problems with a GPS (or just think you are) use this program first. + + If you get no data disaplayed on the serial monitor, the most likley cause is that you dont have the RX + pin connected properly. + + If the data displayed on the serial terminal appears to be random text its very likley you have the GPS + serial baud rate set incorrectly. +*/ + +#define GPSBAUD 9600 //this is the serial baud rate that will be used for the GPS +#define MONITORBAUD 115200 //this is the serial baud rate that will be used for the serial monitor + +#include "Locator2_Board_Definitions.h" + +#include //https://github.com/SlashDevin/NeoSWSerial +NeoSWSerial GPS(GPSRX, GPSTX); //this library is more relaible at GPS init than software serial + + +void loop() +{ + while (GPS.available()) + { + Serial.write(GPS.read()); + } +} + + +void setup() +{ + pinMode(GPSPOWER, OUTPUT); //setup pin for GPS power control, if fitted + digitalWrite(GPSPOWER, LOW); + + GPS.begin(GPSBAUD); + Serial.begin(MONITORBAUD); + Serial.println("Simple GPS Echo Starting"); + +} diff --git a/LoRa/LoRaTracker/Receiver1/Programs/Tracker Bind.doc b/LoRa/LoRaTracker/Receiver1/Programs/Tracker Bind.doc new file mode 100644 index 0000000..0d43ec2 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Programs/Tracker Bind.doc differ diff --git a/LoRa/LoRaTracker/Receiver1/README.md b/LoRa/LoRaTracker/Receiver1/README.md new file mode 100644 index 0000000..5cd70dd --- /dev/null +++ b/LoRa/LoRaTracker/Receiver1/README.md @@ -0,0 +1,33 @@ +This repository contains the current version of the LoRaTracker Receiver1 programs. + +See the Programs folder for the details of the programs and how to configure them. + +The ‘basic’ receiver programs are a cut down versions of the Receiver2 program (designed for ATMEGA1284P) +that will run on simple ATMEGA328P hardware such as the very low cost Arduino Pro Mini 3.3V. + +The terminal receiver program provides the remote control interface to the HAB tracker that allows it to +be controlled and configured whilst it is in flight. + +The portable receiver program displays the tracker location on a display and if a local GPS is fitted then +the receiver will show the distance and direction to the tracker. The receiver can switch between normal +tracker mode, and long distance search mode by pressing the receivers switch. The program will run on most +of the ATMEGA328P based LoRaTracker boards, including the trackers themselves, see examples in the pictures +folder. Currently supported displays are the SD1306 OLED and 20x4 LCD (3.3Version). Future display options +will be the ILI9341 TFT and Nokia 5110. + +The third version of the basic receiver software is for use with boards that have an SD card connected, +the receiver then acts as a logger, recording all received packets to a file on the SD card. + +Most of the LoRa Tracker boards can be used as a receiver, see the document; + +'LoRaTracker Receivers.doc' + +There are build instruction here for the LCD and Mikrobus based receiver. + +The receiver programs need the LoRaTracker Library installed see here; + +https://github.com/LoRaTracker/LoRaTracker-Library + +Stuart Robinson +www.LoRaTracker.uk +December 2017 diff --git a/LoRa/LoRaTracker/Receiver1/Schematic/LCD Receiver3 110818 Schematic.pdf b/LoRa/LoRaTracker/Receiver1/Schematic/LCD Receiver3 110818 Schematic.pdf new file mode 100644 index 0000000..64ce695 Binary files /dev/null and b/LoRa/LoRaTracker/Receiver1/Schematic/LCD Receiver3 110818 Schematic.pdf differ diff --git a/LoRa/Test Programs/LoRaLinkTest/LoRaLinkTest.ino b/LoRa/Test Programs/LoRaLinkTest/LoRaLinkTest.ino new file mode 100644 index 0000000..a69dc3e --- /dev/null +++ b/LoRa/Test Programs/LoRaLinkTest/LoRaLinkTest.ino @@ -0,0 +1,43 @@ +#include +#include + +//define the pins used by the transceiver module +#define ss 10 +#define rst 9 +#define dio0 5 + +void setup() { + //initialize Serial Monitor + Serial.begin(115200); + //while (!Serial); + Serial.println("LoRa Sender"); + + //setup LoRa transceiver module + LoRa.setPins(ss, rst, dio0); + LoRa.setTxPower(20); + LoRa.setSignalBandwidth(7.8E3); + LoRa.setSpreadingFactor(12); + LoRa.setCodingRate4(8); + while (!LoRa.begin(433E6)) { + Serial.println("."); + delay(500); + } + // Change sync word (0xF3) to match the receiver + LoRa.setSyncWord(0xF3); + Serial.println("LoRa Initializing OK!"); +} + +void loop() { + Serial.print("Sending packet: "); + Serial.println(counter); + + //Send LoRa packet to receiver + LoRa.beginPacket(); + LoRa.print("Packet "); + LoRa.print(counter); + LoRa.endPacket(); + + counter++; + + delay(10000); +} diff --git a/LoRa/Test Programs/LoRaLinkTest_-_Reciever/LoRaLinkTest_-_Reciever.ino b/LoRa/Test Programs/LoRaLinkTest_-_Reciever/LoRaLinkTest_-_Reciever.ino new file mode 100644 index 0000000..5c0a9ee --- /dev/null +++ b/LoRa/Test Programs/LoRaLinkTest_-_Reciever/LoRaLinkTest_-_Reciever.ino @@ -0,0 +1,52 @@ +#include +#include + +//define the pins used by the transceiver module +#define ss 10 +#define rst 9 +#define dio0 5 + +void setup() { + //initialize Serial Monitor + Serial.begin(115200); + while (!Serial); + Serial.println("LoRa Receiver"); + + //setup LoRa transceiver module + LoRa.setPins(ss, rst, dio0); + LoRa.setTxPower(20); + LoRa.setSignalBandwidth(7.8E3); + LoRa.setSpreadingFactor(12); + LoRa.setCodingRate4(8); + while (!LoRa.begin(433E6)) { + Serial.println("."); + delay(500); + } + // Change sync word (0xF3) to match the receiver + LoRa.setSyncWord(0xF3); + Serial.println("LoRa Initializing OK!"); +} + +void loop() { + // try to parse packet + int packetSize = LoRa.parsePacket(); + if (packetSize) { + // received a packet + Serial.print("Received packet '"); + + // read packet + while (LoRa.available()) { + String LoRaData = LoRa.readString(); + Serial.print(LoRaData); + } + + // print RSSI, SNR and Frequency Offset of packet + Serial.print("' with RSSI "); + Serial.println(LoRa.packetRssi()); + Serial.print(" with SNR "); + Serial.println(LoRa.packetSnr()); + Serial.print(" with Frequency error "); + Serial.println(LoRa.packetFrequencyError()); + + } +} diff --git a/LoRa/Test Programs/Readme.md b/LoRa/Test Programs/Readme.md new file mode 100644 index 0000000..32d29fd --- /dev/null +++ b/LoRa/Test Programs/Readme.md @@ -0,0 +1 @@ +This folder contains the code for testing the range of the LoRa boards using the arduino [LoRa library](https://github.com/sandeepmistry/arduino-LoRa) diff --git a/README.md b/README.md index e6bb203..9163af0 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -Code to parse output of serial. +This repo contains all the code we have used, and will use, to log sensor data on a raspberry pi and track the balloon using LoRa. +It also contains code for testing different Libraries and Modules.