first commit
This commit is contained in:
@@ -0,0 +1,408 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This program is an example of a basic GPS tracker. The program reads the GPS,
|
||||
waits for an updated fix and transmits location and altitude, number of satellites in view, the HDOP
|
||||
value, the fix time of the GPS and the battery voltage. This transmitter can be also be used to
|
||||
investigate GPS performance. At startup there should be a couple of seconds of recognisable text from
|
||||
the GPS printed to the serial monitor. If you see garbage or funny characters its likley the GPS baud
|
||||
rate is wrong. If the transmitter is turned on from cold, the receiver will pick up the cold fix time,
|
||||
which is an indication of GPS performance. The GPS will be powered on for around 4 seconds before the
|
||||
timing of the fix starts. Outside with a good view of the sky most GPSs should produce a fix in around
|
||||
45 seconds. The number of satellites and HDOP are good indications to how well a GPS is working.
|
||||
|
||||
The program writes direct to the LoRa devices internal buffer, no memory buffer is used.
|
||||
|
||||
The LoRa settings are configured in the Settings.h file.
|
||||
|
||||
The program has the option of using a pin to control the power to the GPS (GPSPOWER), if the GPS module
|
||||
or board being used has this feature. To not use this feature set the define for GPSPOWER in the
|
||||
Settings.h file to '#define GPSPOWER -1'. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic
|
||||
levels.
|
||||
|
||||
The program also has the option of using a logic pin to control the power to the lora and SD card
|
||||
devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
|
||||
powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
|
||||
|
||||
There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on
|
||||
and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON
|
||||
in 'Settings.h' to the pin used. If not using the feature set the pin number to -1.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
#define authorname "Stuart Robinson"
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX127XLT.h>
|
||||
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
SX127XLT LT;
|
||||
|
||||
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
|
||||
TinyGPSPlus gps; //create the TinyGPS++ object
|
||||
|
||||
|
||||
uint8_t TXStatus = 0; //used to store current status flag bits of Tracker transmitter (TX)
|
||||
uint8_t TXPacketL; //length of LoRa packet (TX)
|
||||
float TXLat; //Latitude from GPS on Tracker transmitter (TX)
|
||||
float TXLon; //Longitude from GPS on Tracker transmitter (TX)
|
||||
float TXAlt; //Altitude from GPS on Tracker transmitter (TX)
|
||||
uint8_t TXSats; //number of GPS satellites seen (TX)
|
||||
uint32_t TXHdop; //HDOP from GPS on Tracker transmitter (TX)
|
||||
uint16_t TXVolts; //Volts (battery) level on Tracker transmitter (TX)
|
||||
uint32_t TXGPSFixTime; //GPS fix time in hot fix mode of GPS on Tracker transmitter (TX)
|
||||
uint32_t TXPacketCount, TXErrorsCount; //keep count of OK packets and send errors
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (gpsWaitFix(WaitGPSFixSeconds))
|
||||
{
|
||||
sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime);
|
||||
Serial.println();
|
||||
Serial.print(F("Waiting "));
|
||||
Serial.print(Sleepsecs);
|
||||
Serial.println(F("s"));
|
||||
delay(Sleepsecs * 1000); //this sleep is used to set overall transmission cycle time
|
||||
}
|
||||
else
|
||||
{
|
||||
send_Command(NoFix); //send notification of no GPS fix.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool gpsWaitFix(uint16_t waitSecs)
|
||||
{
|
||||
//waits a specified number of seconds for a fix, returns true for good fix
|
||||
uint32_t endwaitmS, GPSonTime;
|
||||
bool GPSfix;
|
||||
float tempfloat;
|
||||
uint8_t GPSchar;
|
||||
|
||||
GPSonTime = millis();
|
||||
GPSserial.begin(9600); //start GPSserial
|
||||
|
||||
Serial.print(F("Wait GPS Fix "));
|
||||
Serial.print(waitSecs);
|
||||
Serial.println(F("s"));
|
||||
|
||||
endwaitmS = millis() + (waitSecs * 1000);
|
||||
|
||||
while (millis() < endwaitmS)
|
||||
{
|
||||
if (GPSserial.available() > 0)
|
||||
{
|
||||
GPSchar = GPSserial.read();
|
||||
gps.encode(GPSchar);
|
||||
}
|
||||
|
||||
if (gps.location.isUpdated() && gps.altitude.isUpdated())
|
||||
{
|
||||
GPSfix = true;
|
||||
Serial.print(F("Have GPS Fix "));
|
||||
TXGPSFixTime = millis() - GPSonTime;
|
||||
Serial.print(TXGPSFixTime);
|
||||
Serial.println(F("mS"));
|
||||
|
||||
TXLat = gps.location.lat();
|
||||
TXLon = gps.location.lng();
|
||||
TXAlt = gps.altitude.meters();
|
||||
TXSats = gps.satellites.value();
|
||||
TXHdop = gps.hdop.value();
|
||||
tempfloat = ( (float) TXHdop / 100);
|
||||
|
||||
Serial.print(TXLat, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXLon, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXAlt, 1);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXSats);
|
||||
Serial.print(F(","));
|
||||
Serial.print(tempfloat, 2);
|
||||
Serial.println();
|
||||
|
||||
break; //exit while loop reading GPS
|
||||
}
|
||||
}
|
||||
|
||||
//if here then there has either been a fix or no fix and a timeout
|
||||
|
||||
if (GPSfix)
|
||||
{
|
||||
setStatusByte(GPSFix, 1); //set status bit to flag a GPS fix
|
||||
}
|
||||
else
|
||||
{
|
||||
setStatusByte(GPSFix, 0); //set status bit to flag no fix
|
||||
Serial.println();
|
||||
Serial.println(F("Timeout - No GPSFix"));
|
||||
Serial.println();
|
||||
GPSfix = false;
|
||||
}
|
||||
|
||||
GPSserial.end(); //serial RX interrupts interfere with SPI, so stop GPSserial
|
||||
return GPSfix;
|
||||
}
|
||||
|
||||
|
||||
void sendLocation(float Lat, float Lon, float Alt, uint32_t Hdop, uint32_t fixtime)
|
||||
{
|
||||
uint8_t len;
|
||||
uint16_t IRQStatus;
|
||||
|
||||
Serial.print(F("Send Location"));
|
||||
|
||||
TXVolts = readSupplyVoltage(); //get the latest supply\battery volts
|
||||
|
||||
LT.startWriteSXBuffer(0); //initialise buffer write at address 0
|
||||
LT.writeUint8(LocationPacket); //indentify type of packet
|
||||
LT.writeUint8(Broadcast); //who is the packet sent too
|
||||
LT.writeUint8(ThisNode); //tells receiver where is packet from
|
||||
LT.writeFloat(Lat); //add latitude
|
||||
LT.writeFloat(Lon); //add longitude
|
||||
LT.writeFloat(Alt); //add altitude
|
||||
LT.writeUint8(TXSats); //add number of satellites
|
||||
LT.writeUint32(Hdop); //add hdop
|
||||
LT.writeUint8(TXStatus); //add tracker status
|
||||
LT.writeUint32(fixtime); //add GPS fix time in mS
|
||||
LT.writeUint16(TXVolts); //add tracker supply volts
|
||||
len = LT.endWriteSXBuffer(); //close buffer write
|
||||
|
||||
digitalWrite(LED1, HIGH);
|
||||
TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX);
|
||||
digitalWrite(LED1, LOW);
|
||||
|
||||
if (TXPacketL)
|
||||
{
|
||||
TXPacketCount++;
|
||||
Serial.println(F(" - Done "));
|
||||
Serial.print(F("SentOK,"));
|
||||
Serial.print(TXPacketCount);
|
||||
Serial.print(F(",Errors,"));
|
||||
Serial.println(TXErrorsCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if here there was an error transmitting packet
|
||||
TXErrorsCount++;
|
||||
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
|
||||
Serial.print(F(" SendError,"));
|
||||
Serial.print(F("Length,"));
|
||||
Serial.print(TXPacketL); //print transmitted packet length
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX); //print IRQ status
|
||||
LT.printIrqStatus(); //prints the text of which IRQs set
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setStatusByte(uint8_t bitnum, uint8_t bitval)
|
||||
{
|
||||
//program the status byte
|
||||
|
||||
if (bitval == 0)
|
||||
{
|
||||
bitClear(TXStatus, bitnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitSet(TXStatus, bitnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void send_Command(char cmd)
|
||||
{
|
||||
bool SendOK;
|
||||
uint8_t len;
|
||||
|
||||
Serial.print(F("Send Cmd "));
|
||||
Serial.write(cmd);
|
||||
|
||||
LT.startWriteSXBuffer(0);
|
||||
LT.writeUint8(cmd); //packet addressing used indentify type of packet
|
||||
LT.writeUint8(Broadcast); //who is the packet sent to
|
||||
LT.writeUint8(ThisNode); //where is packet from
|
||||
LT.writeUint16(TXVolts);
|
||||
len = LT.endWriteSXBuffer();
|
||||
|
||||
digitalWrite(LED1, HIGH);
|
||||
SendOK = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); //timeout set at 10 seconds
|
||||
digitalWrite(LED1, LOW);
|
||||
|
||||
if (SendOK)
|
||||
{
|
||||
Serial.println(F(" - Done"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F(" - Error"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t readSupplyVoltage()
|
||||
{
|
||||
//ESP32 uses the 3.3V VCC as reference
|
||||
|
||||
uint16_t temp;
|
||||
uint16_t volts = 0;
|
||||
byte index;
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit
|
||||
}
|
||||
|
||||
temp = analogRead(SupplyAD);
|
||||
|
||||
for (index = 0; index <= 4; index++) //sample AD 5 times
|
||||
{
|
||||
temp = analogRead(SupplyAD);
|
||||
volts = volts + temp;
|
||||
}
|
||||
volts = ((volts / 5) * ADMultiplier);
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit
|
||||
}
|
||||
|
||||
return volts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GPSON()
|
||||
{
|
||||
if (GPSPOWER >= 0)
|
||||
{
|
||||
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GPSOFF()
|
||||
{
|
||||
if (GPSPOWER)
|
||||
{
|
||||
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
uint32_t endmS;
|
||||
|
||||
if (VCCPOWER >= 0)
|
||||
{
|
||||
pinMode(VCCPOWER, OUTPUT); //this pin switches power for external devices, lora and SD card
|
||||
digitalWrite(VCCPOWER, LOW); //turn device power on
|
||||
}
|
||||
|
||||
if (GPSPOWER >= 0)
|
||||
{
|
||||
pinMode(GPSPOWER, OUTPUT);
|
||||
GPSON();
|
||||
}
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
pinMode(BATVREADON, OUTPUT);
|
||||
}
|
||||
|
||||
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
|
||||
led_Flash(2, 125); //two quick LED flashes to indicate program start
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.print(F(__TIME__));
|
||||
Serial.print(F(" "));
|
||||
Serial.println(F(__DATE__));
|
||||
Serial.println(F(Program_Version));
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("23_Simple_GPS_Tracker_Transmitter_ESP32 Starting"));
|
||||
|
||||
//SPI.begin();
|
||||
SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)
|
||||
|
||||
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
|
||||
{
|
||||
Serial.println(F("LoRa Device found"));
|
||||
led_Flash(2, 125);
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("No device responding"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
|
||||
|
||||
Serial.println();
|
||||
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
|
||||
Serial.println();
|
||||
LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check
|
||||
Serial.println();
|
||||
|
||||
TXVolts = readSupplyVoltage();
|
||||
|
||||
Serial.print(F("Supply "));
|
||||
Serial.print(TXVolts);
|
||||
Serial.println(F("mV"));
|
||||
|
||||
send_Command(PowerUp); //send power up command, includes supply mV
|
||||
|
||||
Serial.println(F("Startup GPS check"));
|
||||
|
||||
GPSserial.begin(9600);
|
||||
|
||||
endmS = millis() + echomS;
|
||||
|
||||
while (millis() < endmS)
|
||||
{
|
||||
while (GPSserial.available() > 0)
|
||||
Serial.write(GPSserial.read());
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("Wait for first GPS fix"));
|
||||
gpsWaitFix(WaitFirstGPSFixSeconds);
|
||||
|
||||
sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change
|
||||
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
|
||||
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and
|
||||
//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1.
|
||||
|
||||
|
||||
#define NSS 5 //select on LoRa device
|
||||
#define SCK 18 //SCK on SPI3
|
||||
#define MISO 19 //MISO on SPI3
|
||||
#define MOSI 23 //MOSI on SPI3
|
||||
|
||||
#define NRESET 27 //reset on LoRa device
|
||||
#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done
|
||||
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
|
||||
#define LED1 2 //On board LED, high for on
|
||||
#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used
|
||||
#define VCCPOWER 14 //controls power to lora and SD card, set to -1 if not used
|
||||
#define SupplyAD 36 //pin for reading supply\battery voltage
|
||||
#define BATVREADON 25 //turns on battery resistor divider, high for on
|
||||
#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV
|
||||
|
||||
#define RXpin 17 //pin number for GPS RX input into Arduino - TX from GPS
|
||||
#define TXpin 16 //pin number for GPS TX output from Arduino- RX into GPS
|
||||
|
||||
#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
|
||||
#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER
|
||||
#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER
|
||||
#define GPSserial Serial2 //define GPSserial as ESP32 Serial2
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
|
||||
|
||||
//******* Setup LoRa Test Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor
|
||||
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
|
||||
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
|
||||
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
|
||||
|
||||
#define ThisNode 'T' //a character that identifies this tracker
|
||||
|
||||
//**************************************************************************************************
|
||||
// GPS Settings
|
||||
//**************************************************************************************************
|
||||
|
||||
#define GPSBaud 9600 //GPS Baud rate
|
||||
|
||||
#define WaitGPSFixSeconds 30 //time in seconds to wait for a new GPS fix
|
||||
#define WaitFirstGPSFixSeconds 1800 //time to seconds to wait for the first GPS fix at startup
|
||||
#define Sleepsecs 5 //seconds between transmissions, this delay is used to set overall transmission cycle time
|
||||
|
||||
#define echomS 2000 //number of mS to run GPS echo at startup
|
||||
|
||||
|
||||
@@ -0,0 +1,624 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - TThis program is an example of a functional GPS tracker receiver using lora.
|
||||
It is capable of picking up the trackers location packets from many kilometres away with only basic antennas.
|
||||
|
||||
The program receives the location packets from the remote tracker transmitter and writes them on an OLED
|
||||
display and also prints the information to the Arduino IDE serial monitor. The program can read a locally
|
||||
attached GPS and when that has a fix, will display the distance and direction to the remote tracker.
|
||||
|
||||
The program writes direct to the lora devices internal buffer, no memory buffer is used. The lora settings
|
||||
are configured in the Settings.h file.
|
||||
|
||||
The receiver recognises two types of tracker packet, the one from the matching program '23_GPS_Tracker_Transmitter'
|
||||
(LocationPacket, 27 bytes) which causes these fields to be printed to the serial monitor;
|
||||
|
||||
Latitude, Longitude, Altitude, Satellites, HDOP, TrackerStatusByte, GPS Fixtime, Battery mV, Distance, Direction,
|
||||
Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, PacketLength, IRQRegister.
|
||||
|
||||
This is a long packet which at the long range LoRa settings takes just over 3 seconds to transmit.
|
||||
|
||||
The receiver also recognises a much shorter location only packet (LocationBinaryPacket, 11 bytes) and when
|
||||
received this is printed to the serial monitor;
|
||||
|
||||
Latitude, Longitude, Altitude, TrackerStatusByte, Distance, Direction, PacketRSSI, PacketSNR, NumberPackets,
|
||||
PacketLength, IRQRegister.
|
||||
|
||||
Most of the tracker information (for both types of packet) is shown on the OLED display. If there has been a
|
||||
tracker transmitter GPS fix the number\identifier of that tracker is shown on row 0 right of screen and if there
|
||||
is a recent local (receiver) GPS fix an 'R' is displayed row 1 right of screen.
|
||||
|
||||
When the tracker transmitter starts up or is reset its sends a power up message containing the battery voltage
|
||||
which is shown on the OLED and printer to the serial monitor.
|
||||
|
||||
The program has the option of using a pin to control the power to the GPS, if the GPS module being used has this
|
||||
feature. To use the option change the define in Settings.h;
|
||||
|
||||
'#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE defines to
|
||||
the appropriate logic levels.
|
||||
|
||||
The program by default uses software serial to read the GPS, you can use hardware serial by commenting out this
|
||||
line in the Settings.h file;
|
||||
|
||||
#define USE_SOFTSERIAL_GPS
|
||||
|
||||
And then defining the hardware serial port you are using, which defaults to Serial1.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
#define Program_Version "V1.1"
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX127XLT.h>
|
||||
SX127XLT LT;
|
||||
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
#include <U8x8lib.h> //https://github.com/olikraus/u8g2
|
||||
U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306
|
||||
//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306
|
||||
|
||||
|
||||
#include <TinyGPS++.h> //http://arduiniana.org/libraries/tinygpsplus/
|
||||
TinyGPSPlus gps; //create the TinyGPS++ object
|
||||
|
||||
#ifdef USE_SOFTSERIAL_GPS
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial GPSserial(RXpin, TXpin);
|
||||
#else
|
||||
#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file
|
||||
#endif
|
||||
|
||||
uint32_t RXpacketCount; //count of received packets
|
||||
uint8_t RXPacketL; //length of received packet
|
||||
int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet
|
||||
int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet
|
||||
uint8_t PacketType; //for packet addressing, identifies packet type
|
||||
uint8_t Destination; //for packet addressing, identifies the destination (receiving) node
|
||||
uint8_t Source; //for packet addressing, identifies the source (transmiting) node
|
||||
uint8_t TXStatus; //status byte from tracker transmitter
|
||||
uint8_t TXSats; //number of sattelites in use
|
||||
float TXLat; //latitude
|
||||
float TXLon; //longitude
|
||||
float TXAlt; //altitude
|
||||
float RXLat; //latitude
|
||||
float RXLon; //longitude
|
||||
float RXAlt; //altitude
|
||||
uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good
|
||||
uint32_t TXGPSFixTime; //time in mS for fix
|
||||
uint16_t TXVolts; //supply\battery voltage
|
||||
uint16_t RXVolts; //supply\battery voltage
|
||||
float TXdistance; //calculated distance to tracker
|
||||
uint16_t TXdirection; //calculated direction to tracker
|
||||
uint16_t RXerrors;
|
||||
uint32_t TXupTimemS; //up time of TX in mS
|
||||
|
||||
uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix
|
||||
|
||||
bool TXLocation = false; //set to true when at least one tracker location packet has been received
|
||||
bool RXGPSfix = false; //set to true if the local GPS has a recent fix
|
||||
|
||||
uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); //returns 0 if packet error of some sort
|
||||
|
||||
while (!digitalRead(DIO0))
|
||||
{
|
||||
readGPS(); //If the DIO pin is low, no packet arrived, so read the GPS
|
||||
}
|
||||
|
||||
//something has happened in receiver
|
||||
digitalWrite(LED1, HIGH);
|
||||
|
||||
if (BUZZER > 0)
|
||||
{
|
||||
digitalWrite(BUZZER, HIGH);
|
||||
}
|
||||
|
||||
RXPacketL = LT.readRXPacketL();
|
||||
PacketRSSI = LT.readPacketRSSI();
|
||||
PacketSNR = LT.readPacketSNR();
|
||||
|
||||
|
||||
if (RXPacketL == 0)
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_OK();
|
||||
}
|
||||
|
||||
digitalWrite(LED1, LOW);
|
||||
|
||||
if (BUZZER > 0)
|
||||
{
|
||||
digitalWrite(BUZZER, LOW);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void readGPS()
|
||||
{
|
||||
if (GPSserial.available() > 0)
|
||||
{
|
||||
gps.encode(GPSserial.read());
|
||||
}
|
||||
|
||||
|
||||
if ( millis() > (LastRXGPSfixCheck + NoRXGPSfixms))
|
||||
{
|
||||
RXGPSfix = false;
|
||||
LastRXGPSfixCheck = millis();
|
||||
dispscreen1();
|
||||
}
|
||||
|
||||
|
||||
if (gps.location.isUpdated() && gps.altitude.isUpdated())
|
||||
{
|
||||
RXGPSfix = true;
|
||||
RXLat = gps.location.lat();
|
||||
RXLon = gps.location.lng();
|
||||
RXAlt = gps.altitude.meters();
|
||||
printRXLocation();
|
||||
LastRXGPSfixCheck = millis();
|
||||
|
||||
if ( FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1
|
||||
{
|
||||
FixCount = DisplayRate;
|
||||
dispscreen1();
|
||||
}
|
||||
FixCount--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool readTXStatus(byte bitnum)
|
||||
{
|
||||
return bitRead(TXStatus, bitnum);
|
||||
}
|
||||
|
||||
|
||||
void printRXLocation()
|
||||
{
|
||||
Serial.print(F("LocalGPS "));
|
||||
Serial.print(RXLat, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(RXLon, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(RXAlt, 1);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void readPacketAddressing()
|
||||
{
|
||||
LT.startReadSXBuffer(0);
|
||||
PacketType = LT.readUint8();
|
||||
Destination = LT.readUint8();
|
||||
Source = LT.readUint8();
|
||||
LT.endReadSXBuffer();
|
||||
}
|
||||
|
||||
|
||||
void packet_is_OK()
|
||||
{
|
||||
//uint16_t IRQStatus;
|
||||
float tempfloat;
|
||||
|
||||
RXpacketCount++;
|
||||
|
||||
readPacketAddressing();
|
||||
|
||||
if (PacketType == PowerUp)
|
||||
{
|
||||
LT.startReadSXBuffer(0);
|
||||
LT.readUint8(); //read byte from SXBuffer, not used
|
||||
LT.readUint8(); //read byte from SXBuffer, not used
|
||||
LT.readUint8(); //read byte from SXBuffer, not used
|
||||
TXVolts = LT.readUint16(); //read tracker transmitter voltage
|
||||
LT.endReadSXBuffer();
|
||||
Serial.print(F("Tracker Powerup - Battery "));
|
||||
Serial.print(TXVolts);
|
||||
Serial.println(F("mV"));
|
||||
dispscreen2();
|
||||
}
|
||||
|
||||
if (PacketType == LocationPacket)
|
||||
{
|
||||
//packet has been received, now read from the SX12XX FIFO in the correct order.
|
||||
Serial.print(F("LocationPacket "));
|
||||
TXLocation = true;
|
||||
LT.startReadSXBuffer(0); //start the read of received packet
|
||||
PacketType = LT.readUint8(); //read in the PacketType
|
||||
Destination = LT.readUint8(); //read in the Packet destination address
|
||||
Source = LT.readUint8(); //read in the Packet source address
|
||||
TXLat = LT.readFloat(); //read in the tracker latitude
|
||||
TXLon = LT.readFloat(); //read in the tracker longitude
|
||||
TXAlt = LT.readFloat(); //read in the tracker altitude
|
||||
TXSats = LT.readUint8(); //read in the satellites in use by tracker GPS
|
||||
TXHdop = LT.readUint32(); //read in the HDOP of tracker GPS
|
||||
TXStatus = LT.readUint8(); //read in the tracker status byte
|
||||
TXGPSFixTime = LT.readUint32(); //read in the last fix time of tracker GPS
|
||||
TXVolts = LT.readUint16(); //read in the tracker supply\battery volts
|
||||
TXupTimemS = LT.readUint32(); //read in the TX uptime in mS
|
||||
RXPacketL = LT.endReadSXBuffer(); //end the read of received packet
|
||||
|
||||
|
||||
if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation
|
||||
{
|
||||
TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon);
|
||||
TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXdistance = 0;
|
||||
TXdirection = 0;
|
||||
}
|
||||
|
||||
Serial.write(PacketType);
|
||||
Serial.write(Destination);
|
||||
Serial.write(Source);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXLat, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXLon, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXAlt, 1);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXSats);
|
||||
Serial.print(F(","));
|
||||
|
||||
tempfloat = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display
|
||||
Serial.print(tempfloat, 2);
|
||||
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXStatus);
|
||||
Serial.print(F(","));
|
||||
|
||||
Serial.print(TXGPSFixTime);
|
||||
Serial.print(F("mS,"));
|
||||
Serial.print(TXVolts);
|
||||
Serial.print(F("mV,"));
|
||||
Serial.print((TXupTimemS/1000));
|
||||
Serial.print(F("s,"));
|
||||
|
||||
Serial.print(TXdistance, 0);
|
||||
Serial.print(F("m,"));
|
||||
Serial.print(TXdirection);
|
||||
Serial.print(F("d"));
|
||||
printpacketDetails();
|
||||
dispscreen1(); //and show the packet detail it on screen
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (PacketType == LocationBinaryPacket)
|
||||
{
|
||||
//packet from locator has been received, now read from the SX12XX FIFO in the correct order.
|
||||
TXLocation = true;
|
||||
Serial.print(F("LocationBinaryPacket "));
|
||||
LT.startReadSXBuffer(0);
|
||||
PacketType = LT.readUint8();
|
||||
Destination = LT.readUint8();
|
||||
Source = LT.readUint8();
|
||||
TXLat = LT.readFloat();
|
||||
TXLon = LT.readFloat();
|
||||
TXAlt = LT.readInt16();
|
||||
TXStatus = LT.readUint8();
|
||||
RXPacketL = LT.endReadSXBuffer();
|
||||
|
||||
if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation
|
||||
{
|
||||
TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon);
|
||||
TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon);
|
||||
}
|
||||
else
|
||||
{
|
||||
TXdistance = 0;
|
||||
TXdirection = 0;
|
||||
}
|
||||
|
||||
Serial.write(PacketType);
|
||||
Serial.write(Destination);
|
||||
Serial.write(Source);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXLat, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXLon, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXAlt, 0);
|
||||
Serial.print(F("m,"));
|
||||
Serial.print(TXStatus);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXdistance, 0);
|
||||
Serial.print(F("m,"));
|
||||
Serial.print(TXdirection);
|
||||
Serial.print(F("d"));
|
||||
printpacketDetails();
|
||||
dispscreen1();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printpacketDetails()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
Serial.print(F(",RSSI,"));
|
||||
Serial.print(PacketRSSI);
|
||||
Serial.print(F("dBm,SNR,"));
|
||||
Serial.print(PacketSNR);
|
||||
Serial.print(F("dB,Packets,"));
|
||||
Serial.print(RXpacketCount);
|
||||
|
||||
Serial.print(F(",Length,"));
|
||||
Serial.print(RXPacketL);
|
||||
IRQStatus = LT.readIrqStatus();
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
|
||||
if (BUZZER >= 0)
|
||||
{
|
||||
digitalWrite(BUZZER, LOW);
|
||||
delay(100);
|
||||
digitalWrite(BUZZER, HIGH);
|
||||
}
|
||||
|
||||
IRQStatus = LT.readIrqStatus(); //get the IRQ status
|
||||
RXerrors++;
|
||||
Serial.print(F("PacketError,RSSI"));
|
||||
|
||||
Serial.print(PacketRSSI);
|
||||
Serial.print(F("dBm,SNR,"));
|
||||
Serial.print(PacketSNR);
|
||||
|
||||
Serial.print(F("dB,Length,"));
|
||||
Serial.print(LT.readRXPacketL()); //get the real packet length
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
LT.printIrqStatus();
|
||||
digitalWrite(LED1, LOW);
|
||||
|
||||
if (BUZZER >= 0)
|
||||
{
|
||||
digitalWrite(BUZZER, LOW);
|
||||
delay(100);
|
||||
digitalWrite(BUZZER, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
unsigned int index;
|
||||
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dispscreen1()
|
||||
{
|
||||
//show received packet data on display
|
||||
float tempfloat;
|
||||
disp.clearLine(0);
|
||||
disp.setCursor(0, 0);
|
||||
disp.print(TXLat, 5);
|
||||
disp.clearLine(1);
|
||||
disp.setCursor(0, 1);
|
||||
disp.print(TXLon, 5);
|
||||
disp.clearLine(2);
|
||||
disp.setCursor(0, 2);
|
||||
disp.print(TXAlt,0);
|
||||
disp.print(F("m"));
|
||||
disp.clearLine(3);
|
||||
disp.setCursor(0, 3);
|
||||
|
||||
disp.print(F("RSSI "));
|
||||
disp.print(PacketRSSI);
|
||||
disp.print(F("dBm"));
|
||||
disp.clearLine(4);
|
||||
disp.setCursor(0, 4);
|
||||
disp.print(F("SNR "));
|
||||
|
||||
if (PacketSNR > 0)
|
||||
{
|
||||
disp.print(F("+"));
|
||||
}
|
||||
|
||||
if (PacketSNR == 0)
|
||||
{
|
||||
disp.print(F(" "));
|
||||
}
|
||||
|
||||
if (PacketSNR < 0)
|
||||
{
|
||||
disp.print(F("-"));
|
||||
}
|
||||
|
||||
disp.print(PacketSNR);
|
||||
disp.print(F("dB"));
|
||||
|
||||
if (PacketType == LocationPacket)
|
||||
{
|
||||
disp.clearLine(5);
|
||||
disp.setCursor(0, 5);
|
||||
tempfloat = ((float) TXVolts / 1000);
|
||||
disp.print(F("Batt "));
|
||||
disp.print(tempfloat, 2);
|
||||
disp.print(F("v"));
|
||||
}
|
||||
|
||||
disp.clearLine(6);
|
||||
disp.setCursor(0, 6);
|
||||
disp.print(F("Packets "));
|
||||
disp.print(RXpacketCount);
|
||||
|
||||
disp.clearLine(7);
|
||||
|
||||
if (RXGPSfix)
|
||||
{
|
||||
disp.setCursor(15, 1);
|
||||
disp.print(F("R"));
|
||||
}
|
||||
else
|
||||
{
|
||||
disp.setCursor(15, 1);
|
||||
disp.print(F(" "));
|
||||
disp.setCursor(0, 7);
|
||||
disp.print(F("No Local Fix"));
|
||||
}
|
||||
|
||||
if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix
|
||||
{
|
||||
disp.clearLine(7);
|
||||
disp.setCursor(0, 7);
|
||||
disp.print(TXdistance, 0);
|
||||
disp.print(F("m "));
|
||||
disp.print(TXdirection);
|
||||
disp.print(F("d"));
|
||||
}
|
||||
|
||||
if (readTXStatus(GPSFix))
|
||||
{
|
||||
disp.setCursor(15, 0);
|
||||
disp.write(Source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void dispscreen2()
|
||||
{
|
||||
//show tracker powerup data on display
|
||||
float tempfloat;
|
||||
disp.clear();
|
||||
disp.setCursor(0, 0);
|
||||
disp.print(F("Tracker Powerup"));
|
||||
disp.setCursor(0, 1);
|
||||
disp.print(F("Battery "));
|
||||
tempfloat = ((float) TXVolts / 1000);
|
||||
disp.print(tempfloat, 2);
|
||||
disp.print(F("v"));
|
||||
}
|
||||
|
||||
|
||||
void GPSON()
|
||||
{
|
||||
if (GPSPOWER >= 0)
|
||||
{
|
||||
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GPSOFF()
|
||||
{
|
||||
if (GPSPOWER >= 0)
|
||||
{
|
||||
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
uint32_t endmS;
|
||||
|
||||
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
|
||||
led_Flash(2, 125); //two quick LED flashes to indicate program start
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.print(F(__TIME__));
|
||||
Serial.print(F(" "));
|
||||
Serial.println(F(__DATE__));
|
||||
Serial.println(F(Program_Version));
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32 Starting"));
|
||||
|
||||
if (BUZZER >= 0)
|
||||
{
|
||||
pinMode(BUZZER, OUTPUT);
|
||||
}
|
||||
|
||||
SPI.begin();
|
||||
|
||||
disp.begin();
|
||||
disp.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
Serial.print(F("Checking LoRa device - ")); //Initialize LoRa
|
||||
disp.setCursor(0, 0);
|
||||
|
||||
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
|
||||
{
|
||||
Serial.println(F("Receiver ready"));
|
||||
disp.print(F("Receiver ready"));
|
||||
led_Flash(2, 125);
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("No LoRa device responding"));
|
||||
disp.print(F("No LoRa device"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
|
||||
|
||||
Serial.println();
|
||||
Serial.println(F("Startup GPS check"));
|
||||
|
||||
endmS = millis() + echomS;
|
||||
|
||||
//now startup GPS
|
||||
if (GPSPOWER >= 0)
|
||||
{
|
||||
pinMode(GPSPOWER, OUTPUT);
|
||||
}
|
||||
|
||||
GPSON();
|
||||
GPSserial.begin(GPSBaud);
|
||||
|
||||
while (millis() < endmS)
|
||||
{
|
||||
while (GPSserial.available() > 0)
|
||||
Serial.write(GPSserial.read());
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("Receiver ready"));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
|
||||
//be sure to change the definitiosn to match your own setup. Some pins such as DIO1,
|
||||
//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be
|
||||
//connected and should be set to -1.
|
||||
|
||||
#define NSS 5 //select on LoRa device
|
||||
#define NRESET 27 //reset on LoRa device
|
||||
#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done
|
||||
#define LED1 82 //On board LED, high for on
|
||||
#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used
|
||||
|
||||
#define RXpin 16 //pin number for GPS RX input into Arduino - TX from GPS
|
||||
#define TXpin 17 //pin number for GPS TX output from Arduino- RX into GPS
|
||||
|
||||
#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
|
||||
#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER
|
||||
#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
|
||||
|
||||
//******* Setup LoRa Test Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor
|
||||
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
|
||||
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
|
||||
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
|
||||
|
||||
//**************************************************************************************************
|
||||
// GPS Settings
|
||||
//**************************************************************************************************
|
||||
|
||||
//#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS
|
||||
#define HardwareSerialPort Serial2 //if using hardware serial enable this define for hardware serial port
|
||||
|
||||
#define GPSBaud 9600 //GPS Baud rate
|
||||
#define WaitGPSFixSeconds 30 //time to wait for a new GPS fix
|
||||
#define echomS 2000 //number of mS to run GPS echo for at startup
|
||||
|
||||
#define NoRXGPSfixms 15000 //max number of mS to allow before no local fix flagged
|
||||
#define DisplayRate 7 //when working OK the GPS will get a new fix every second or so
|
||||
//this rate defines how often the display should be updated
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This is a test program for using the LoRa device to transmit upper side band FSK
|
||||
RTTY. With the LoRa device in FSK direct mode, the frequency of the generated carrier is shifted up
|
||||
or down at the correct baud rate depending on whether a logic 0 or 1 is being sent.
|
||||
|
||||
The desired shift in frequency is defined in the Settings.h file as 'FrequencyShift'. When the program
|
||||
starts the actual frequency shift will be calculated according to the discrete frequency steps the
|
||||
LoRa device can be set to. There are settings for number of data bits, number of start bits and the
|
||||
value of parity which can be ParityNone, ParityOdd, ParityEven, ParityZero or ParityOne.
|
||||
|
||||
Before the actual data transmission starts you can send a series of marker pips which are short bursts
|
||||
of up shifted carrier which will be heard as beeps in a correctly tuned receiver. These pips can aid
|
||||
in setting the receiver decode frequemcy to match the transmission. on some LoRa devices, such as the SX127x
|
||||
series there can be considerable temperature induced frequency drift. This drift can be caused by outside
|
||||
temperature changes or the RF device self heating when transmit is turned on. The duration of the pips,
|
||||
the gaps between them and the period of leadin carrier before the data starts can all be set. To send no
|
||||
pips just set the number to 0.
|
||||
|
||||
The FSK RTTY routines use the micros() function for timing, and a check is made at the begging of a
|
||||
character to send to see if micros() migh overflow during the transmission of the character. This check
|
||||
assumes the lowest baud rate of 45baud, and if an overflow is likley, there will be a short in transmission
|
||||
pause to allow the overflow to occur.
|
||||
|
||||
|
||||
Serial monitor baud rate is set at 9600
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
|
||||
#include <SPI.h> //the lora device is SPI based
|
||||
#include <SX127XLT.h> //include the appropriate SX12XX library
|
||||
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
|
||||
|
||||
SX127XLT LT; //create a library class instance called LT
|
||||
|
||||
//Choose whichever test pattern takes your fancy
|
||||
//uint8_t testBuffer[] = "0123456789* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"; //This string is sent as AFSK RTTY, 7 bit, 2 Stop bit, no parity, 300 baud.
|
||||
//uint8_t testBuffer[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789";
|
||||
//uint8_t testBuffer[] = "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU";
|
||||
uint8_t testBuffer[] = "$$MyFlight1,2213,14:54:37,51.48230,-3.18136,15,6,3680,23,66,3,0*2935";
|
||||
|
||||
uint8_t freqShiftRegs[3]; //to hold returned registers that set frequency
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint8_t index;
|
||||
|
||||
printRegisterSetup(FrequencyShift);
|
||||
Serial.println();
|
||||
|
||||
LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS);
|
||||
|
||||
if (micros() > 0xF8000000)
|
||||
{
|
||||
Serial.print(F("Waiting micros()"));
|
||||
while(micros() < 0xFFFB6000);
|
||||
}
|
||||
|
||||
Serial.print(F("Start RTTY micros() = "));
|
||||
Serial.println(micros(),HEX);
|
||||
|
||||
LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return
|
||||
LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed
|
||||
for (index = 0; index < (sizeof(testBuffer)-1); index++)
|
||||
{
|
||||
LT.transmitFSKRTTY(testBuffer[index], DataBits, StopBits, Parity, BaudPerioduS, LED1);
|
||||
Serial.write(testBuffer[index]);
|
||||
}
|
||||
LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return
|
||||
LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed
|
||||
|
||||
Serial.println();
|
||||
Serial.print(F("END RTTY micros() = "));
|
||||
Serial.println(micros(),HEX);
|
||||
digitalWrite(LED1, LOW);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println(micros(),HEX);
|
||||
|
||||
LT.setMode(MODE_STDBY_RC);
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
|
||||
void printRegisterSetup(uint32_t shift)
|
||||
{
|
||||
|
||||
uint32_t nonShiftedFreq, ShiftedFreq;
|
||||
uint32_t freqShift;
|
||||
float exactfreqShift;
|
||||
|
||||
LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set
|
||||
LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values
|
||||
nonShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2];
|
||||
Serial.print(F("NoShift Registers 0x"));
|
||||
Serial.println(nonShiftedFreq, HEX);
|
||||
|
||||
LT.setRfFrequency((Frequency + shift), Offset); //set shifted frequecy
|
||||
LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values
|
||||
ShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2];
|
||||
Serial.print(F("Shifted Registers 0x"));
|
||||
Serial.println(ShiftedFreq, HEX);
|
||||
|
||||
freqShift = ShiftedFreq - nonShiftedFreq;
|
||||
exactfreqShift = freqShift * FREQ_STEP;
|
||||
Serial.print(F("FSKRTTY register shift "));
|
||||
Serial.println(freqShift,HEX);
|
||||
Serial.print(F("FSKRTTY frequency shift "));
|
||||
Serial.print(exactfreqShift, 8);
|
||||
Serial.println(F("hZ"));
|
||||
|
||||
LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set
|
||||
}
|
||||
|
||||
|
||||
void printRegisterBuffer()
|
||||
{
|
||||
Serial.print(freqShiftRegs[0],HEX);
|
||||
Serial.print(F(" "));
|
||||
Serial.print(freqShiftRegs[1],HEX);
|
||||
Serial.print(F(" "));
|
||||
Serial.print(freqShiftRegs[2],HEX);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
uint16_t index;
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
|
||||
led_Flash(2, 125); //two quick LED flashes to indicate program start
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.print(F(__TIME__));
|
||||
Serial.print(F(" "));
|
||||
Serial.println(F(__DATE__));
|
||||
Serial.println(F(Program_Version));
|
||||
Serial.println();
|
||||
Serial.println(F("71_FSKRTTY_Transmitter_Test_ESP32 Starting"));
|
||||
|
||||
SPI.begin();
|
||||
|
||||
//SPI beginTranscation is normally part of library routines, but if it is disabled in library
|
||||
//a single instance is needed here, so uncomment the program line below
|
||||
//SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
//setup hardware pins used by device, then check if device is found
|
||||
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
|
||||
{
|
||||
Serial.println(F("LoRa Device found"));
|
||||
led_Flash(2, 125); //two further quick LED flashes to indicate device found
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("No device responding"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed LED flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupDirect(Frequency, Offset);
|
||||
Serial.print(F("Transmitter ready"));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions needed. You will also need to connect up the pins for the SPI bus, which
|
||||
//are SCK on pin 18, MISO on pin 19 and MOSI on pin 23.
|
||||
|
||||
#define NSS 5 //select pin on LoRa device
|
||||
#define NRESET 27 //reset pin on LoRa device
|
||||
#define LED1 2 //on board LED, high for on
|
||||
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
|
||||
|
||||
//******* Setup Direct Modem Parameters Here ! ***************
|
||||
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
const uint16_t deviation = 10000; //deviation, total frequency shift low to high
|
||||
const float adjustfreq = 0.9; //adjustment to tone frequency
|
||||
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
|
||||
|
||||
//******* Setup FSKRTTY Settings here ! ***************
|
||||
|
||||
uint32_t FrequencyShift = 400; //hertz frequency shift, approx, in 61.03515625hz steps
|
||||
uint8_t NumberofPips = 2; //number of marker pips to send
|
||||
uint16_t PipDelaymS = 500; //mS between pips, carrier off
|
||||
uint16_t PipPeriodmS = 100; //mS length of pip
|
||||
uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud
|
||||
uint16_t LeadinmS = 1000; //ms of leadin, shifted carrier
|
||||
uint8_t DataBits = 7; //number of databits, normally 7 or 8
|
||||
uint8_t StopBits = 2; //number of stopbits, normally 1 or 2
|
||||
uint8_t Parity = ParityNone; //parity on data bits, ParityNone, ParityOdd, ParityEven, ParityZero, ParityOne
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,898 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 08/06/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This is a tracker intended for use as a high altitude balloon (HAB) tracker. The
|
||||
program sends out a standard format payload with LoRa that is compatible with the HABHUB online tracking
|
||||
system.
|
||||
|
||||
The HAB payload is constructed thus;
|
||||
|
||||
PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,Status,Errors,TXGPSfixms,Checksum
|
||||
Field 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
|
||||
The LoRa and frequency settings can be changed in the Settings.h file. There is the option of sending
|
||||
out a much shorter Search mode binary location only payload. This is intended for ground based searching
|
||||
and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker
|
||||
mode used by the HAB payload. There is also the option of sending the HAB payload in FSK RTTY format,
|
||||
see the Settings.h file for all the options. FSK RTTY gets sent at the same frequency as the Tracker mode
|
||||
HAB packet.
|
||||
|
||||
There is a matching Balloon Tracker Receiver program which writes received data to the Serial monitor as well
|
||||
as a small OLED display.
|
||||
|
||||
In the Settings.h file you can set the configuration for either a Ublox GPS or a Quectel L70\L80. The GPSs
|
||||
are configured for high altitude balloon mode.
|
||||
|
||||
It is strongly recommended that a FRAM option is fitted for this transmitter. The sequence, resets and error
|
||||
nembers are stred in non-volatile memory. This defaults to EEPROM which has a limited endurance of only
|
||||
100,000 writes, so in theory the limt is reached after the transmission of 100,000 hab packets. The use of
|
||||
a FRAM will extend the life of the tracker to circa 100,000,000,000,000 transmissions.
|
||||
|
||||
Changes:
|
||||
240420 - Change to work with Easy Pro Mini style modules
|
||||
300420 - Improve error detection for UBLOX GPS library
|
||||
|
||||
ToDo:
|
||||
|
||||
Serial monitor baud rate is set at 115200
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.1"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SX127XLT.h> //include the appropriate library
|
||||
|
||||
SX127XLT LT; //create a library class instance called LT
|
||||
|
||||
#include "Settings.h"
|
||||
#include "ProgramLT_Definitions.h"
|
||||
|
||||
//**************************************************************************************************
|
||||
// HAB tracker data - these are the variables transmitted in payload
|
||||
//**************************************************************************************************
|
||||
uint32_t TXSequence; //sequence number of payload
|
||||
uint8_t TXHours; //Hours
|
||||
uint8_t TXMinutes; //Minutes
|
||||
uint8_t TXSeconds; //Seconds
|
||||
float TXLat; //latitude from GPS
|
||||
float TXLon; //longitude from GPS
|
||||
uint16_t TXAlt; //altitude from GPS
|
||||
uint8_t TXSatellites; //satellites used by GPS
|
||||
uint16_t TXVolts; //measured tracker supply volts
|
||||
int8_t TXTemperature; //measured temperature
|
||||
uint16_t TXResets; //number of tracker resets
|
||||
uint8_t TXStatus = 0; //used to store current status flag bits
|
||||
uint16_t TXErrors; //number of tracker Errors
|
||||
uint32_t TXGPSfixms; //fix time of GPS
|
||||
uint32_t TXGPSHdop; //HDOP value of GPS
|
||||
uint8_t hours, mins, secs, day, month;
|
||||
uint16_t year;
|
||||
//**************************************************************************************************
|
||||
|
||||
uint8_t TXPacketL; //length of LoRa packet sent
|
||||
uint8_t TXBUFFER[TXBUFFER_SIZE]; //buffer for packet to send
|
||||
|
||||
#include Memory_Library
|
||||
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
File logFile;
|
||||
char filename[] = "/LOG0000.txt"; //filename used as base for creating logfile, 0000 replaced with numbers
|
||||
bool SDfound;
|
||||
|
||||
#include <TinyGPS++.h> //http://arduiniana.org/libraries/tinygpsplus/
|
||||
TinyGPSPlus gps; //create the TinyGPS++ object
|
||||
#define GPSserial HARDWARESERIALPORT
|
||||
|
||||
#include GPS_Library //include previously defined GPS Library
|
||||
|
||||
#include <OneWire.h> //get library here > https://github.com/PaulStoffregen/OneWire
|
||||
OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library
|
||||
#include <DallasTemperature.h> //get library here > https://github.com/milesburton/Arduino-TXTemperature-Control-Library
|
||||
DallasTemperature sensor(&oneWire); //create instance of dallas library
|
||||
|
||||
uint32_t GPSstartms; //start time waiting for GPS to get a fix
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.println(F("Start Loop"));
|
||||
|
||||
GPSstartms = millis();
|
||||
|
||||
if (!gpsWaitFix(WaitGPSFixSeconds))
|
||||
{
|
||||
GPS_OutputOff();
|
||||
sendCommand(NoFix); //report a GPS fix error
|
||||
delay(1000); //give receiver enough time to report NoFix
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
if (SDfound)
|
||||
{
|
||||
Serial.print(F("Write data to "));
|
||||
Serial.print(filename);
|
||||
|
||||
if (logGPSfix(filename)) //log fix data to SD card
|
||||
{
|
||||
setStatusByte(SDError, 0); //write to SD OK, clear error flag
|
||||
}
|
||||
else
|
||||
{
|
||||
cardFail(2);
|
||||
setStatusByte(SDError, 1); //flag SD card error
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
do_Transmissions(); //do the transmissions
|
||||
|
||||
Serial.println(F("Sleep"));
|
||||
LT.setSleep(CONFIGURATION_RETENTION); //put LoRa device to sleep, preserve lora register settings
|
||||
Serial.flush(); //make sure no serial output pending before goint to sleep
|
||||
|
||||
delay(SleepTimesecs * 1000);
|
||||
|
||||
Serial.println(F("Wake"));
|
||||
LT.wake(); //wake the LoRa device from sleep
|
||||
}
|
||||
|
||||
|
||||
void do_Transmissions()
|
||||
{
|
||||
//this is where all the transmisions get sent
|
||||
uint32_t startTimemS;
|
||||
uint8_t index;
|
||||
|
||||
incMemoryUint32(addr_SequenceNum); //increment Sequence number
|
||||
|
||||
if (readConfigByte(SearchEnable))
|
||||
{
|
||||
setSearchMode();
|
||||
TXPacketL = buildLocationOnly(TXLat, TXLon, TXAlt, TXStatus); //put location data in SX12xx buffer
|
||||
Serial.print(F("Search packet > "));
|
||||
Serial.print(TXLat, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXLon, 5);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXAlt);
|
||||
Serial.print(F(","));
|
||||
Serial.print(TXStatus);
|
||||
digitalWrite(LED1, HIGH);
|
||||
startTimemS = millis();
|
||||
TXPacketL = LT.transmitSXBuffer(0, TXPacketL, 10000, SearchTXpower, WAIT_TX);
|
||||
printTXtime(startTimemS, millis());
|
||||
reportCompletion();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(1000); //gap between transmissions
|
||||
|
||||
setTrackerMode();
|
||||
|
||||
TXPacketL = buildHABPacket();
|
||||
Serial.print(F("HAB Packet > "));
|
||||
printBuffer(TXBUFFER, (TXPacketL + 1)); //print the buffer (the packet to send) as ASCII
|
||||
digitalWrite(LED1, HIGH);
|
||||
startTimemS = millis();
|
||||
TXPacketL = LT.transmit(TXBUFFER, (TXPacketL + 1), 10000, TrackerTXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error
|
||||
digitalWrite(LED1, LOW);
|
||||
printTXtime(startTimemS, millis());
|
||||
reportCompletion();
|
||||
Serial.println();
|
||||
|
||||
delay(1000); //gap between transmissions
|
||||
|
||||
if (readConfigByte(FSKRTTYEnable))
|
||||
{
|
||||
LT.setupDirect(TrackerFrequency, Offset);
|
||||
LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS);
|
||||
|
||||
startTimemS = millis() - LeadinmS;
|
||||
|
||||
Serial.print(F("FSK RTTY > $$"));
|
||||
Serial.flush();
|
||||
LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync
|
||||
LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync
|
||||
|
||||
for (index = 0; index <= (TXPacketL - 1); index++) //its TXPacketL-1 since we dont want to send the null at the end
|
||||
{
|
||||
LT.transmitFSKRTTY(TXBUFFER[index], BaudPerioduS, LED1);
|
||||
Serial.write(TXBUFFER[index]);
|
||||
}
|
||||
|
||||
LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return
|
||||
LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed
|
||||
LT.endFSKRTTY(); //stop transmitting carrier
|
||||
digitalWrite(LED1, LOW); //LED off
|
||||
printTXtime(startTimemS, millis());
|
||||
TXPacketL += 4; //add the two $ at beginning and CR/LF at end
|
||||
reportCompletion();
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printTXtime(uint32_t startmS, uint32_t endmS)
|
||||
{
|
||||
Serial.print(F(" "));
|
||||
Serial.print(endmS - startmS);
|
||||
Serial.print(F("mS"));
|
||||
}
|
||||
|
||||
|
||||
void reportCompletion()
|
||||
{
|
||||
Serial.print(F(" "));
|
||||
if (TXPacketL == 0)
|
||||
{
|
||||
Serial.println();
|
||||
reporttransmitError();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(TXPacketL);
|
||||
Serial.print(F("bytes"));
|
||||
setStatusByte(LORAError, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printBuffer(uint8_t *buffer, uint8_t size)
|
||||
{
|
||||
uint8_t index;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
{
|
||||
Serial.write(buffer[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t buildHABPacket()
|
||||
{
|
||||
//build the HAB tracker payload
|
||||
uint16_t index, j, CRC;
|
||||
uint8_t Count, len;
|
||||
char LatArray[12], LonArray[12];
|
||||
|
||||
TXSequence = readMemoryUint32(addr_SequenceNum); //Sequence number is kept in non-volatile memory so it survives TXResets
|
||||
TXResets = readMemoryUint16(addr_ResetCount); //reset count is kept in non-volatile memory so it survives TXResets
|
||||
TXVolts = readSupplyVoltage();
|
||||
TXTemperature = (int8_t) readTempDS18B20();
|
||||
TXErrors = readMemoryUint16(addr_TXErrors);
|
||||
|
||||
dtostrf(TXLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER);
|
||||
dtostrf(TXLon, 7, 5, LonArray); //converts float to character array
|
||||
|
||||
len = sizeof(TXBUFFER);
|
||||
memset(TXBUFFER, 0, len); //clear array to 0s
|
||||
Count = snprintf((char*) TXBUFFER,
|
||||
TXBUFFER_SIZE,
|
||||
"$$%s,%u,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%u,%u,%u,%u",
|
||||
FlightID,
|
||||
TXSequence,
|
||||
TXHours,
|
||||
TXMinutes,
|
||||
TXSeconds,
|
||||
LatArray,
|
||||
LonArray,
|
||||
TXAlt,
|
||||
TXSatellites,
|
||||
TXVolts,
|
||||
TXTemperature,
|
||||
TXResets,
|
||||
TXStatus,
|
||||
TXErrors,
|
||||
TXGPSfixms
|
||||
);
|
||||
|
||||
CRC = 0xffff; //start value for CRC16
|
||||
|
||||
for (index = 2; index < Count; index++) //element 2 is first character after $$ at start (for LoRa)
|
||||
{
|
||||
CRC ^= (((uint16_t)TXBUFFER[index]) << 8);
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
if (CRC & 0x8000)
|
||||
CRC = (CRC << 1) ^ 0x1021;
|
||||
else
|
||||
CRC <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
TXBUFFER[Count++] = '*';
|
||||
TXBUFFER[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end
|
||||
TXBUFFER[Count++] = Hex((CRC >> 8) & 15);
|
||||
TXBUFFER[Count++] = Hex((CRC >> 4) & 15);
|
||||
TXBUFFER[Count] = Hex(CRC & 15);
|
||||
return Count;
|
||||
}
|
||||
|
||||
|
||||
char Hex(uint8_t lchar)
|
||||
{
|
||||
//used in CRC calculation in buildHABPacket
|
||||
char Table[] = "0123456789ABCDEF";
|
||||
return Table[lchar];
|
||||
}
|
||||
|
||||
|
||||
uint8_t buildLocationOnly(float Lat, float Lon, uint16_t Alt, uint8_t stat)
|
||||
{
|
||||
uint8_t len;
|
||||
LT.startWriteSXBuffer(0); //initialise buffer write at address 0
|
||||
LT.writeUint8(LocationBinaryPacket); //identify type of packet
|
||||
LT.writeUint8(Broadcast); //who is the packet sent too
|
||||
LT.writeUint8(ThisNode); //tells receiver where is packet from
|
||||
LT.writeFloat(Lat); //add latitude
|
||||
LT.writeFloat(Lon); //add longitude
|
||||
LT.writeInt16(Alt); //add altitude
|
||||
LT.writeUint8(stat); //add tracker status
|
||||
len = LT.endWriteSXBuffer(); //close buffer write
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void reporttransmitError()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
|
||||
Serial.print(F("TXError,"));
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX); //print IRQ status
|
||||
LT.printIrqStatus(); //prints the text of which IRQs set
|
||||
incMemoryUint16(addr_TXErrors); //increase the error count
|
||||
setStatusByte(LORAError, 1);
|
||||
}
|
||||
|
||||
|
||||
void incMemoryUint32(uint32_t addr)
|
||||
{
|
||||
uint32_t val = readMemoryUint32(addr);
|
||||
val++;
|
||||
writeMemoryUint32(addr, val);
|
||||
}
|
||||
|
||||
|
||||
void incMemoryUint16(uint32_t addr)
|
||||
{
|
||||
uint16_t val = readMemoryUint16(addr);
|
||||
val++;
|
||||
writeMemoryUint16(addr, val);
|
||||
}
|
||||
|
||||
|
||||
void setStatusByte(uint8_t bitnum, uint8_t bitval)
|
||||
{
|
||||
//program the status byte
|
||||
|
||||
if (bitval == 0)
|
||||
{
|
||||
bitClear(TXStatus, bitnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitSet(TXStatus, bitnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t readConfigByte(uint8_t bitnum)
|
||||
{
|
||||
return bitRead(Default_config1, bitnum);
|
||||
}
|
||||
|
||||
|
||||
void setTrackerMode()
|
||||
{
|
||||
Serial.println(F("setTrackerMode"));
|
||||
LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation);
|
||||
}
|
||||
|
||||
|
||||
void setSearchMode()
|
||||
{
|
||||
Serial.println(F("setSearchMode"));
|
||||
LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation);
|
||||
}
|
||||
|
||||
|
||||
uint8_t sendCommand(char cmd)
|
||||
{
|
||||
uint8_t len;
|
||||
TXVolts = readSupplyVoltage();
|
||||
Serial.print(F("Send Cmd "));
|
||||
Serial.write(cmd);
|
||||
Serial.println();
|
||||
|
||||
LT.startWriteSXBuffer(0); //start the write packet to buffer process
|
||||
LT.writeUint8(cmd); //this byte defines the packet type
|
||||
LT.writeUint8(Broadcast); //destination address of the packet, the receivers address
|
||||
LT.writeUint8(ThisNode); //source address of this node
|
||||
LT.writeUint16(TXVolts); //add the battery voltage
|
||||
LT.writeUint8(TXStatus); //add the status byte
|
||||
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
|
||||
|
||||
//now transmit the packet, set a timeout of 5000mS, wait for it to complete sending
|
||||
|
||||
digitalWrite(LED1, HIGH); //turn on LED as an indicator
|
||||
TXPacketL = LT.transmitSXBuffer(0, len, 5000, TrackerTXpower, WAIT_TX);
|
||||
digitalWrite(LED1, LOW); //turn off indicator LED
|
||||
|
||||
return TXPacketL; //TXPacketL will be 0 if there was an error sending
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clearAllMemory()
|
||||
{
|
||||
//clears the whole of non-volatile
|
||||
Serial.println(F("Clear Memory"));
|
||||
fillMemory(addr_StartMemory, addr_EndMemory, 0);
|
||||
}
|
||||
|
||||
|
||||
float readTempDS18B20()
|
||||
{
|
||||
float DS18B20TXTemperature;
|
||||
sensor.requestTemperatures();
|
||||
DS18B20TXTemperature = sensor.getTempCByIndex(0);
|
||||
return DS18B20TXTemperature;
|
||||
}
|
||||
|
||||
|
||||
void printTempDS18B20()
|
||||
{
|
||||
float DS18B20TXTemperature;
|
||||
DS18B20TXTemperature = readTempDS18B20();
|
||||
Serial.print(F("Temperature "));
|
||||
Serial.print(DS18B20TXTemperature, 1);
|
||||
Serial.println(F("c"));
|
||||
}
|
||||
|
||||
|
||||
void printSupplyVoltage()
|
||||
{
|
||||
//get and display supply volts on terminal or monitor
|
||||
Serial.print(F("Volts "));
|
||||
Serial.print(readSupplyVoltage());
|
||||
Serial.println(F("mV"));
|
||||
}
|
||||
|
||||
|
||||
uint16_t readSupplyVoltage()
|
||||
{
|
||||
//relies on 1V1 internal reference and 91K & 11K resistor divider
|
||||
//returns supply in mV @ 10mV per AD bit read
|
||||
uint16_t temp;
|
||||
uint16_t volts = 0;
|
||||
uint8_t index;
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit
|
||||
}
|
||||
|
||||
temp = analogRead(SupplyAD);
|
||||
|
||||
for (index = 0; index <= 4; index++) //sample AD 5 times
|
||||
{
|
||||
temp = analogRead(SupplyAD);
|
||||
volts = volts + temp;
|
||||
}
|
||||
volts = ((volts / 5) * ADMultiplier);
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
digitalWrite(BATVREADON, LOW); //turn MOSFET connection resitor divider in circuit
|
||||
}
|
||||
|
||||
return volts;
|
||||
}
|
||||
|
||||
|
||||
//***********************************************************
|
||||
// Start GPS Functions
|
||||
//***********************************************************
|
||||
|
||||
void GPSTest()
|
||||
{
|
||||
uint32_t endmS;
|
||||
|
||||
endmS = millis() + 2000; //run GPS echo for 2000mS
|
||||
|
||||
while (millis() < endmS)
|
||||
{
|
||||
while (GPSserial.available() > 0)
|
||||
Serial.write(GPSserial.read());
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
|
||||
bool gpsWaitFix(uint16_t waitSecs)
|
||||
{
|
||||
//waits a specified number of seconds for a fix, returns true for good fix
|
||||
|
||||
uint32_t endwaitmS, millistowait, currentmillis;
|
||||
uint8_t GPSchar;
|
||||
|
||||
Serial.flush();
|
||||
|
||||
Serial.print(F("Wait GPS Fix "));
|
||||
Serial.print(waitSecs);
|
||||
Serial.print(F("s "));
|
||||
Serial.flush();
|
||||
|
||||
GPS_OutputOn();
|
||||
Serial.flush();
|
||||
|
||||
currentmillis = millis();
|
||||
millistowait = waitSecs * 1000;
|
||||
endwaitmS = currentmillis + millistowait;
|
||||
|
||||
while (GPSserial.read() >= 0); //clear the GPS serial input buffer
|
||||
|
||||
while (millis() < endwaitmS)
|
||||
{
|
||||
|
||||
if (GPSserial.available() > 0)
|
||||
{
|
||||
GPSchar = GPSserial.read();
|
||||
gps.encode(GPSchar);
|
||||
}
|
||||
|
||||
if (gps.location.isUpdated() && gps.altitude.isUpdated())
|
||||
{
|
||||
TXLat = gps.location.lat();
|
||||
TXLon = gps.location.lng();
|
||||
TXAlt = (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 (TXAlt > 60000)
|
||||
{
|
||||
TXAlt = 0;
|
||||
}
|
||||
|
||||
TXHours = gps.time.hour(),
|
||||
TXMinutes = gps.time.minute(),
|
||||
TXSeconds = gps.time.second(),
|
||||
TXSatellites = gps.satellites.value();
|
||||
TXGPSHdop = gps.hdop.value();
|
||||
|
||||
hours = gps.time.hour();
|
||||
mins = gps.time.minute();
|
||||
secs = gps.time.second();
|
||||
day = gps.date.day();
|
||||
month = gps.date.month();
|
||||
year = gps.date.year();
|
||||
|
||||
setStatusByte(GPSFix, 1);
|
||||
|
||||
TXGPSfixms = millis() - GPSstartms;
|
||||
|
||||
Serial.print(F("Have GPS Fix "));
|
||||
Serial.print(TXGPSfixms);
|
||||
Serial.print(F("mS"));
|
||||
Serial.println();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if here then there has been no fix and a timeout
|
||||
GPS_OutputOff();
|
||||
setStatusByte(GPSFix, 0); //set status bit to flag no fix
|
||||
incMemoryUint16(addr_TXErrors);
|
||||
Serial.println(F("Error No GPS Fix"));
|
||||
return false;
|
||||
}
|
||||
|
||||
//***********************************************************
|
||||
// End GPS Functions
|
||||
//***********************************************************
|
||||
|
||||
|
||||
//*******************************************************************************
|
||||
// Start SD card routines
|
||||
//*******************************************************************************
|
||||
|
||||
bool logGPSfix(char *buf )
|
||||
{
|
||||
float tempfloat;
|
||||
|
||||
logFile = SD.open(buf, FILE_APPEND);
|
||||
|
||||
if (!logFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tempfloat = ( (float) TXGPSHdop / 100);
|
||||
|
||||
if (hours < 10)
|
||||
{
|
||||
logFile.print(F("0"));
|
||||
}
|
||||
|
||||
logFile.print(hours);
|
||||
logFile.print(F(":"));
|
||||
|
||||
if (mins < 10)
|
||||
{
|
||||
logFile.print(F("0"));
|
||||
}
|
||||
|
||||
logFile.print(mins);
|
||||
logFile.print(F(":"));
|
||||
|
||||
if (secs < 10)
|
||||
{
|
||||
logFile.print(F("0"));
|
||||
}
|
||||
|
||||
logFile.print(secs);
|
||||
logFile.print(F(","));
|
||||
|
||||
logFile.print(day);
|
||||
logFile.print(F("/"));
|
||||
logFile.print(month);
|
||||
logFile.print(F("/"));
|
||||
logFile.print(year);
|
||||
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXLat, 6);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXLon, 6);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXAlt, 1);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXSatellites);
|
||||
logFile.print(F(","));
|
||||
logFile.print(tempfloat, 2);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXVolts);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXTemperature);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXResets);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXStatus);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXErrors);
|
||||
logFile.print(F(","));
|
||||
logFile.print(TXGPSfixms);
|
||||
logFile.println();
|
||||
logFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t setupSDLOG(char *buf)
|
||||
{
|
||||
//creats a new filename
|
||||
|
||||
uint16_t index;
|
||||
|
||||
for (index = 1; index <= 9999; index++) {
|
||||
buf[4] = index / 1000 + '0';
|
||||
buf[5] = ((index % 1000) / 100) + '0';
|
||||
buf[6] = ((index % 100) / 10) + '0';
|
||||
buf[7] = index % 10 + '0' ;
|
||||
if (! SD.exists(filename)) {
|
||||
// only open a new file if it doesn't exist
|
||||
logFile = SD.open(buf, FILE_WRITE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setStatusByte(SDError, 0); //SD card write OK
|
||||
return index; //return number of logfile created
|
||||
}
|
||||
|
||||
|
||||
void cardFail(uint8_t num)
|
||||
{
|
||||
Serial.print(num); //so we can tell where crd failed
|
||||
Serial.println(" Card failed, or not present");
|
||||
led_Flash(100, 25);
|
||||
}
|
||||
|
||||
//*******************************************************************************
|
||||
// End SD card routines
|
||||
//*******************************************************************************
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
uint32_t i;
|
||||
uint16_t j;
|
||||
|
||||
Serial.begin(115200); //Setup Serial console ouput
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println(F("75_Balloon_Tracker_Transmitter_SDLogger_ESP32 Starting"));
|
||||
|
||||
memoryStart(Memory_Address); //setup the memory
|
||||
j = readMemoryUint16(addr_ResetCount);
|
||||
j++;
|
||||
writeMemoryUint16(addr_ResetCount, j);
|
||||
j = readMemoryUint16(addr_ResetCount);
|
||||
|
||||
Serial.print(F("TXResets "));
|
||||
Serial.println(j);
|
||||
|
||||
if (GPSPOWER >= 0) //if GPS needs power switching, turn it on
|
||||
{
|
||||
pinMode(GPSPOWER, OUTPUT);
|
||||
digitalWrite(GPSPOWER, GPSONSTATE);
|
||||
}
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
pinMode(BATVREADON, OUTPUT); //for MOSFET controlling battery volts resistor divider
|
||||
}
|
||||
|
||||
#ifdef QUECTELINUSE
|
||||
Serial.println(F("Quectel GPS library"));
|
||||
#endif
|
||||
|
||||
#ifdef UBLOXINUSE
|
||||
Serial.println(F("UBLOX GPS library"));
|
||||
#endif
|
||||
|
||||
#ifdef ClearAllMemory
|
||||
clearAllMemory();
|
||||
#endif
|
||||
|
||||
SPI.begin(); //initialize SPI
|
||||
|
||||
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
|
||||
{
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("LoRa Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
setTrackerMode();
|
||||
|
||||
Serial.print(F("Config "));
|
||||
Serial.println(Default_config1, BIN);
|
||||
|
||||
j = readMemoryUint16(addr_TXErrors);
|
||||
Serial.print(F("TXErrors "));
|
||||
Serial.println(j);
|
||||
|
||||
Serial.print(F("TXSequence "));
|
||||
i = readMemoryUint32(addr_SequenceNum);
|
||||
Serial.println(i);
|
||||
|
||||
Serial.print(F("ThisNode "));
|
||||
Serial.println(ThisNode);
|
||||
|
||||
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
|
||||
|
||||
Serial.println();
|
||||
printSupplyVoltage();
|
||||
printTempDS18B20();
|
||||
Serial.println();
|
||||
|
||||
j = readSupplyVoltage(); //get supply mV
|
||||
TXStatus = 0; //clear all TX status bits
|
||||
|
||||
sendCommand(PowerUp); //send power up command, includes supply mV and config, on tracker settings
|
||||
|
||||
|
||||
Serial.println();
|
||||
Serial.println("Initializing SD card");
|
||||
|
||||
if (!SD.begin(SDCS))
|
||||
{
|
||||
cardFail(1);
|
||||
Serial.println();
|
||||
SDfound = false;
|
||||
setStatusByte(SDError, 1); //flag SD card error
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Card initialized");
|
||||
setupSDLOG(filename); //setup logfile name for writing
|
||||
Serial.print(F("Write file to "));
|
||||
Serial.println(filename);
|
||||
SDfound = true;
|
||||
}
|
||||
|
||||
|
||||
GPS_OutputOn();
|
||||
GPSTest();
|
||||
GPS_Setup(); //GPS should have had plenty of time to initialise by now
|
||||
|
||||
delay(2000);
|
||||
|
||||
if (GPS_CheckConfiguration()) //Check that GPS is configured for high altitude mode
|
||||
{
|
||||
Serial.println();
|
||||
GPS_OutputOff(); //GPS interrupts cause problems with lora device, so turn off for now
|
||||
setStatusByte(GPSError, 0);
|
||||
setStatusByte(GPSConfigError, 0);
|
||||
|
||||
//Alert user to GPS OK, turn LED on and send a FM tone.
|
||||
digitalWrite(LED1, HIGH);
|
||||
Serial.println(F("GPS Config OK")); //check tone indicates navigation model 6 set
|
||||
Serial.println();
|
||||
Serial.flush();
|
||||
LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones
|
||||
LT.toneFM(1500, 500, deviation, adjustfreq, TrackerTXpower); //Transmit an FM tone, 1000hz, 3000ms
|
||||
delay(1000);
|
||||
digitalWrite(LED1, LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
setStatusByte(GPSConfigError, 1);
|
||||
incMemoryUint16(addr_TXErrors);
|
||||
Serial.println(F("GPS Error"));
|
||||
Serial.println();
|
||||
setTrackerMode();
|
||||
sendCommand(NoGPS); //make sure receiver knows about GPS error
|
||||
led_Flash(100, 25); //long very rapid flash for GPS error
|
||||
}
|
||||
|
||||
GPSstartms = millis();
|
||||
|
||||
setTrackerMode(); //so that commands indicating wait for a GPS go out
|
||||
|
||||
while (!gpsWaitFix(5)) //wait for the initial GPS fix, this could take a while
|
||||
{
|
||||
sendCommand(NoFix);
|
||||
led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix
|
||||
}
|
||||
|
||||
LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones
|
||||
digitalWrite(LED1, HIGH);
|
||||
LT.toneFM(500, 2000, deviation, adjustfreq, TrackerTXpower);
|
||||
digitalWrite(LED1, LOW);
|
||||
GPS_OutputOn();
|
||||
delay(2000); //GPS may be in software backup allow time for it to wakeup
|
||||
GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled
|
||||
GPS_OutputOff();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 08/06/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
//**************************************************************************************************
|
||||
// 1) Hardware related definitions and options - specify lora board type and pins here
|
||||
//**************************************************************************************************
|
||||
|
||||
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
|
||||
//be sure to change the definitions to match your own setup.
|
||||
|
||||
#define NSS 5 //select on LoRa device
|
||||
#define SCK 18 //SCK on SPI3
|
||||
#define MISO 19 //MISO on SPI3
|
||||
#define MOSI 23 //MOSI on SPI3
|
||||
|
||||
#define NRESET 27 //reset on LoRa device
|
||||
#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done
|
||||
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
|
||||
#define LED1 2 //On board LED, high for on
|
||||
#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used
|
||||
#define ONE_WIRE_BUS 32 //for DS18B20 temperature sensor
|
||||
#define SupplyAD 36 //pin for reading supply\battery voltage
|
||||
#define BATVREADON 2 //turns on battery resistor divider, high for on
|
||||
#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV
|
||||
#define SDCS 13 //microSD card select
|
||||
|
||||
#define RXpin 17 //pin number for GPS RX input into Arduino - TX from GPS
|
||||
#define TXpin 16 //pin number for GPS TX output from Arduino- RX into GPS
|
||||
|
||||
#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
|
||||
#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER
|
||||
#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
|
||||
|
||||
//**************************************************************************************************
|
||||
// 2) Program Options
|
||||
//**************************************************************************************************
|
||||
|
||||
#define ClearAllMemory //Clears memory of stored tracker information, counts, errors etc
|
||||
|
||||
//**************************************************************************************************
|
||||
// 3) LoRa modem settings
|
||||
//**************************************************************************************************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
//Tracker mode
|
||||
const uint32_t TrackerFrequency = 434000000; //frequency of transmissions
|
||||
const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth
|
||||
const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor
|
||||
const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate
|
||||
const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting
|
||||
const int8_t TrackerTXpower = 10; //LoRa TX power in dBm
|
||||
|
||||
//Search mode
|
||||
const uint32_t SearchFrequency = 434000000; //frequency of transmissionsconst
|
||||
uint8_t SearchBandwidth = LORA_BW_062; //LoRa bandwidth
|
||||
const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor
|
||||
const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate
|
||||
const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting
|
||||
const int8_t SearchTXpower = 10; //LoRa TX power in dBm
|
||||
|
||||
const uint16_t deviation = 10000; //deviation in hz for FM tones
|
||||
const float adjustfreq = 0.9; //adjustment to tone frequency
|
||||
|
||||
const byte TXBUFFER_SIZE = 128; //defines the maximum size of the trasnmit buffer;
|
||||
|
||||
|
||||
//**************************************************************************************************
|
||||
// 4) GPS Options
|
||||
//**************************************************************************************************
|
||||
|
||||
#define GPSBaud 9600 //GPS Baud rate
|
||||
|
||||
#define HARDWARESERIALPORT Serial2 //if your using hardware serial for the GPS, define it here
|
||||
|
||||
const uint16_t WaitGPSFixSeconds = 60; //when in flight the time to wait for a new GPS fix
|
||||
|
||||
#define GPS_Library <UBLOXSerialGPS.h> //use library file for UBLOX GPS
|
||||
//#define GPS_Library <QuectelSerialGPS.h> //use library file for Quectel GPS
|
||||
|
||||
|
||||
//**************************************************************************************************
|
||||
// 5) FSK RTTY Settings
|
||||
//**************************************************************************************************
|
||||
|
||||
uint32_t FrequencyShift = 500; //hertz frequency shift for audio
|
||||
uint8_t NumberofPips = 4; //number of marker pips to send
|
||||
uint16_t PipDelaymS = 1000; //mS between pips when carrier is off
|
||||
uint16_t PipPeriodmS = 100; //mS length of pip
|
||||
uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud
|
||||
uint16_t LeadinmS = 1000; //ms of leadin constant shifted carrier
|
||||
|
||||
|
||||
//****************************************************************************************************
|
||||
// 6) Program Default Option settings - This section determines which options are on or off by default,
|
||||
// these are saved in the Default_config1 byte. These options are set in this way so that it is
|
||||
// possible (in future program changes) to alter the options remotly.
|
||||
//**************************************************************************************************
|
||||
|
||||
uint8_t OptionOff = 0;
|
||||
uint8_t OptionOn = 1;
|
||||
|
||||
const char option_SearchEnable = OptionOff; //set to OptionOn to enable transmit of Search mode packet
|
||||
const char option_FSKRTTYEnable = OptionOff; //set to OptionOn to enable transmit of FSKRTTY
|
||||
|
||||
#define option_SearchEnable_SUM (option_SearchEnable*1)
|
||||
#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4)
|
||||
|
||||
const unsigned int Default_config1 = (option_SearchEnable_SUM + option_FSKRTTYEnable_SUM);
|
||||
//const unsigned int Default_config1 = 0x05; //Phew, the default config can always be set manually........
|
||||
//0x05 would turn on transmit of search mode and FSKRTTY
|
||||
|
||||
|
||||
//**************************************************************************************************
|
||||
// 7) Memory settings - define the type of memory to use for non-Volatile storage.
|
||||
// The ESP32 version of the HAB tracker transmitter only supports the use of FRAM here.
|
||||
//**************************************************************************************************
|
||||
|
||||
//#define Memory_Library <FRAM_MB85RC16PNF.h>
|
||||
#define Memory_Library <FRAM_FM24CL64.h>
|
||||
|
||||
int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM
|
||||
|
||||
//**************************************************************************************************
|
||||
// 8) HAB Flight Settings
|
||||
//**************************************************************************************************
|
||||
|
||||
char FlightID[] = "Flight1"; //flight ID for HAB packet
|
||||
|
||||
const unsigned int SleepTimesecs = 13; //sleep time in seconds after each TX loop
|
||||
|
||||
const char ThisNode = '1'; //tracker number for search packet
|
||||
|
||||
|
||||
Reference in New Issue
Block a user