first commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/19
|
||||
|
||||
This programs is supplied as is, it is up to the user of the program to decide if the programs are
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This program blinks an LED connected the pin number defined below. The blinks
|
||||
should be close to one per second. messages are sent to the Serial Monitor also.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define LED1 2 //pin number for LED, set logic level high for on
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
|
||||
uint16_t seconds; //used to display time elapsed on Serial Monitor
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(seconds);
|
||||
Serial.println(F(" Seconds")); //this message should print on console at close to once per second
|
||||
seconds++;
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(890); //should give approx 1 second flash
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
//general purpose routine for flashing LED as indicator
|
||||
uint16_t index;
|
||||
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH); //LED on
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW); //LED off
|
||||
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(__TIME__);
|
||||
Serial.print(F(" "));
|
||||
Serial.println(__DATE__);
|
||||
Serial.println(F(Program_Version));
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("1_LED_Blink_ESP32 Starting"));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
/*******************************************************************************************************
|
||||
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/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 stand alone, it is not necessary to install the SX12XX-LoRa library
|
||||
to use it.
|
||||
|
||||
The program checks that a SX127X LoRa device can be accessed by doing a test register write and read.
|
||||
If there is no device found a message is printed on the serial monitor. The contents of the registers
|
||||
from 0x00 to 0x7F are printed, there is a copy of a typical printout below. Note that the read back
|
||||
changed frequency may be slightly different to the programmed frequency, there is a rounding error due
|
||||
to the use of floats to calculate the frequency.
|
||||
|
||||
The Arduino pin numbers that the NSS and NRESET pins on the LoRa device are connected to must be
|
||||
specified in the hardware definitions section below. The LoRa device type in use, SX1272, SX1276,
|
||||
SX1277, SX1278 or SX1279 must be specified also.
|
||||
|
||||
Typical printout;
|
||||
|
||||
2_Register_Test Starting
|
||||
SX1276-79 Selected
|
||||
LoRa Device found
|
||||
Device version 0x12
|
||||
|
||||
Frequency at reset 434000000
|
||||
Registers at reset
|
||||
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x00 00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A
|
||||
0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
|
||||
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
|
||||
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40
|
||||
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
|
||||
0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78
|
||||
0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B
|
||||
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
Changed Frequency 434099968
|
||||
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x00 00 09 1A 0B 00 52 6C 86 66 4F 09 2B 20 08 02 0A
|
||||
0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
|
||||
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
|
||||
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40
|
||||
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
|
||||
0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78
|
||||
0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B
|
||||
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
const uint8_t REG_FRMSB = 0x06; //register number for setting setting and reading frequency, high byte
|
||||
const uint8_t REG_FRMID = 0x07; //register number for setting setting and reading frequency, mid byte
|
||||
const uint8_t REG_FRLSB = 0x08; //register number for setting setting and reading frequency, low byte
|
||||
const uint8_t REG_VERSION = 0x42; //register containg version number of device
|
||||
|
||||
const uint8_t DEVICE_SX1272 = 0x10; //SX1272
|
||||
const uint8_t DEVICE_SX1276 = 0x11; //SX1276
|
||||
const uint8_t DEVICE_SX1277 = 0x12; //SX1277
|
||||
const uint8_t DEVICE_SX1278 = 0x13; //SX1278
|
||||
const uint8_t DEVICE_SX1279 = 0x14; //SX1279
|
||||
|
||||
//********* Setup hardware 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.
|
||||
|
||||
#define NSS 5 //SX127X device select
|
||||
#define NRESET 27 //SX127X reset pin
|
||||
#define DIO0 -1 //DIO0 pin on LoRa device, not used here so set to -1
|
||||
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //defines the type of LoRa device used, needed for correct program operation
|
||||
|
||||
//**************************************************************/
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
Serial.println(F("2_Register_Test_ESP32 Starting"));
|
||||
|
||||
SPI.begin();
|
||||
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
//The begin function setups the hardware pins used by device and then checks if device is found
|
||||
//the DIO0, DIO1 and DIO2 pins are not used in this example so are set to -1
|
||||
//the LT.begin fuction can define the pins and device type directly in this way (for SX1278);
|
||||
//LT.begin(10, 9, -1, -1, -1, DEVICE_SX1278)
|
||||
|
||||
if (begin(NSS, NRESET, -1, -1, -1, LORA_DEVICE))
|
||||
{
|
||||
Serial.println(F("LoRa Device found"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("No device responding"));
|
||||
}
|
||||
|
||||
Serial.print(F("Device version 0x"));
|
||||
uint8_t deviceversion = readRegister(REG_VERSION);
|
||||
if (deviceversion < 0x10)
|
||||
{
|
||||
Serial.print(F("0"));
|
||||
}
|
||||
Serial.println(deviceversion, HEX);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint32_t frequency;
|
||||
|
||||
frequency = getFreqInt(); //read the set frequency following a reset
|
||||
Serial.print(F("Frequency at reset "));
|
||||
Serial.println(frequency);
|
||||
|
||||
Serial.println(F("Registers at reset")); //show the all registers following a reset
|
||||
printRegisters(0x00, 0x7F);
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
setRfFrequency(434100000, 0); //change the frequency at reset, in hertz
|
||||
frequency = getFreqInt(); //read back the changed frequency
|
||||
Serial.print(F("Changed Frequency "));
|
||||
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
|
||||
printRegisters(0x00, 0x7F); //show the registers after frequency change
|
||||
Serial.println();
|
||||
delay(5000);
|
||||
resetDevice(LORA_DEVICE); //reset the device and start again
|
||||
}
|
||||
|
||||
|
||||
uint8_t readRegister(uint8_t address)
|
||||
{
|
||||
uint8_t regdata;
|
||||
digitalWrite(NSS, LOW); //set NSS low
|
||||
SPI.transfer(address & 0x7F); //mask address for read
|
||||
regdata = SPI.transfer(0); //read the byte
|
||||
digitalWrite(NSS, HIGH); //set NSS high
|
||||
return regdata;
|
||||
}
|
||||
|
||||
|
||||
void writeRegister(uint8_t address, uint8_t value)
|
||||
{
|
||||
digitalWrite(NSS, LOW); //set NSS low
|
||||
SPI.transfer(address | 0x80); //mask address for write
|
||||
SPI.transfer(value); //write the byte
|
||||
digitalWrite(NSS, HIGH); //set NSS high
|
||||
}
|
||||
|
||||
|
||||
uint32_t getFreqInt()
|
||||
{
|
||||
//get the current set LoRa device frequency, return as long integer
|
||||
|
||||
uint8_t Msb, Mid, Lsb;
|
||||
uint32_t uinttemp;
|
||||
float floattemp;
|
||||
Msb = readRegister(REG_FRMSB);
|
||||
Mid = readRegister(REG_FRMID);
|
||||
Lsb = readRegister(REG_FRLSB);
|
||||
floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb);
|
||||
floattemp = ((floattemp * 61.03515625) / 1000000ul);
|
||||
uinttemp = (uint32_t)(floattemp * 1000000);
|
||||
return uinttemp;
|
||||
}
|
||||
|
||||
|
||||
void printRegisters(uint16_t Start, uint16_t End)
|
||||
{
|
||||
//prints the contents of SX127x registers to serial monitor
|
||||
|
||||
uint16_t Loopv1, Loopv2, RegData;
|
||||
|
||||
Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F"));
|
||||
Serial.println();
|
||||
|
||||
for (Loopv1 = Start; Loopv1 <= End;)
|
||||
{
|
||||
Serial.print(F("0x"));
|
||||
if (Loopv1 < 0x10)
|
||||
{
|
||||
Serial.print(F("0"));
|
||||
}
|
||||
Serial.print((Loopv1), HEX);
|
||||
Serial.print(F(" "));
|
||||
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
|
||||
{
|
||||
RegData = readRegister(Loopv1);
|
||||
if (RegData < 0x10)
|
||||
{
|
||||
Serial.print(F("0"));
|
||||
}
|
||||
Serial.print(RegData, HEX);
|
||||
Serial.print(F(" "));
|
||||
Loopv1++;
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setRfFrequency(uint64_t freq64, int32_t offset)
|
||||
{
|
||||
freq64 = freq64 + offset;
|
||||
freq64 = ((uint64_t)freq64 << 19) / 32000000;
|
||||
writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16));
|
||||
writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8));
|
||||
writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0));
|
||||
}
|
||||
|
||||
|
||||
void resetDevice(uint8_t device)
|
||||
{
|
||||
if (device == DEVICE_SX1272)
|
||||
{
|
||||
digitalWrite(NRESET, HIGH);
|
||||
delay(2);
|
||||
digitalWrite(NRESET, LOW);
|
||||
delay(20);
|
||||
Serial.println(F("SX1272 Selected"));
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(NRESET, LOW);
|
||||
delay(2);
|
||||
digitalWrite(NRESET, HIGH);
|
||||
delay(20);
|
||||
Serial.println(F("SX1276-79 Selected"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device)
|
||||
{
|
||||
pinMode(pinNSS, OUTPUT);
|
||||
digitalWrite(pinNSS, HIGH);
|
||||
pinMode(pinNRESET, OUTPUT);
|
||||
digitalWrite(pinNRESET, LOW);
|
||||
|
||||
if (pinDIO0 >= 0)
|
||||
{
|
||||
pinMode( pinDIO0, INPUT);
|
||||
}
|
||||
|
||||
if (pinDIO1 >= 0)
|
||||
{
|
||||
pinMode( pinDIO1, INPUT);
|
||||
}
|
||||
|
||||
if (pinDIO2 >= 0)
|
||||
{
|
||||
pinMode( pinDIO2, INPUT);
|
||||
}
|
||||
|
||||
resetDevice(device);
|
||||
|
||||
if (checkDevice())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool checkDevice()
|
||||
{
|
||||
//check there is a device out there, writes a register and reads back
|
||||
|
||||
uint8_t Regdata1, Regdata2;
|
||||
Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting
|
||||
writeRegister(REG_FRMID, (Regdata1 + 1));
|
||||
Regdata2 = readRegister(REG_FRMID); //read changed value back
|
||||
writeRegister(REG_FRMID, Regdata1); //restore register to original value
|
||||
|
||||
if (Regdata2 == (Regdata1 + 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/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 simple LoRa test transmitter for an ESP32 device. A packet containing
|
||||
ASCII text is sent according to the frequency and LoRa settings specified in the 'Settings.h' file.
|
||||
The pins to access the SX127X need to be defined in the 'Settings.h' file also.
|
||||
|
||||
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.
|
||||
|
||||
The details of the packet sent and any errors are shown on the Serial Monitor, together with the transmit
|
||||
power used, the packet length and the CRC of the packet. The matching receive program, '4_LoRa_Receive'
|
||||
can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h)
|
||||
must be the same for the Transmit and Receive program. Sample Serial Monitor output;
|
||||
|
||||
10dBm Packet> {packet contents*} BytesSent,23 CRC,DAAB TransmitTime,54mS PacketsSent,1
|
||||
|
||||
Serial monitor baud rate is set at 9600
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
|
||||
#include <SPI.h> //the SX127X device is SPI based so load the SPI library
|
||||
#include <SX127XLT.h> //include the appropriate library
|
||||
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
|
||||
|
||||
SX127XLT LT; //create a library class instance called LT
|
||||
|
||||
uint8_t TXPacketL;
|
||||
uint32_t TXPacketCount, startmS, endmS;
|
||||
|
||||
uint8_t buff[] = "Hello World 1234567890";
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(TXpower); //print the transmit power defined
|
||||
Serial.print(F("dBm "));
|
||||
Serial.print(F("Packet> "));
|
||||
Serial.flush();
|
||||
|
||||
TXPacketL = sizeof(buff); //set TXPacketL to length of array
|
||||
buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver
|
||||
|
||||
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
|
||||
|
||||
digitalWrite(LED1, HIGH);
|
||||
startmS = millis(); //start transmit timer
|
||||
if (LT.transmit(buff, TXPacketL, 5000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
|
||||
{
|
||||
endmS = millis(); //packet sent, note end time
|
||||
TXPacketCount++;
|
||||
packet_is_OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_Error(); //transmit packet returned 0, there was an error
|
||||
}
|
||||
|
||||
digitalWrite(LED1, LOW);
|
||||
Serial.println();
|
||||
delay(packet_delay); //have a delay between packets
|
||||
}
|
||||
|
||||
|
||||
void packet_is_OK()
|
||||
{
|
||||
//if here packet has been sent OK
|
||||
uint16_t localCRC;
|
||||
|
||||
Serial.print(F(" BytesSent,"));
|
||||
Serial.print(TXPacketL); //print transmitted packet length
|
||||
localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF);
|
||||
Serial.print(F(" CRC,"));
|
||||
Serial.print(localCRC, HEX); //print CRC of sent packet
|
||||
Serial.print(F(" TransmitTime,"));
|
||||
Serial.print(endmS - startmS); //print transmit time of packet
|
||||
Serial.print(F("mS"));
|
||||
Serial.print(F(" PacketsSent,"));
|
||||
Serial.print(TXPacketCount); //print total of packets sent OK
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
//if here there was an error transmitting packet
|
||||
uint16_t IRQStatus;
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
if (VCCPOWER >= 0)
|
||||
{
|
||||
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
|
||||
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
|
||||
}
|
||||
|
||||
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("3_LoRa_Transmitter_ESP32 Starting"));
|
||||
|
||||
//SPI.begin(); //default setup can be used be used
|
||||
SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)
|
||||
|
||||
//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, DIO1, DIO2, 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
|
||||
}
|
||||
}
|
||||
|
||||
//The function call list below shows the complete setup for the LoRa device using the information defined in the
|
||||
//Settings.h file.
|
||||
//The 'Setup LoRa device' list below can be replaced with a single function call;
|
||||
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
|
||||
|
||||
//***************************************************************************************************
|
||||
//Setup LoRa device
|
||||
//***************************************************************************************************
|
||||
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
|
||||
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
|
||||
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
|
||||
LT.calibrateImage(0); //run calibration after setting frequency
|
||||
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
|
||||
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
|
||||
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
|
||||
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
|
||||
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
|
||||
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done
|
||||
//***************************************************************************************************
|
||||
|
||||
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();
|
||||
Serial.println();
|
||||
LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Transmitter ready"));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/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 pin 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 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 DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
|
||||
#define VCCPOWER 14 //pin controls power to external devices
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
|
||||
|
||||
|
||||
//******* Setup LoRa Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF7; //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, normally set to auto
|
||||
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
|
||||
const uint16_t packet_delay = 1000; //mS delay between packets
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 20/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 - The program listens for incoming packets using the LoRa settings in the 'Settings.h'
|
||||
file. The pins to access the SX127X need to be defined in the 'Settings.h' file also.
|
||||
|
||||
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 a printout of the valid packets received, the packet is assumed to be in ASCII printable text,
|
||||
if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor.
|
||||
The LED will flash for each packet received and the buzzer will sound, if fitted.
|
||||
|
||||
Sample serial monitor output;
|
||||
|
||||
1109s Hello World 1234567890*,CRC,DAAB,RSSI,-61dBm,SNR,9dB,Length,23,Packets,1026,Errors,0,IRQreg,50
|
||||
|
||||
If there is a packet error it might look like this, which is showing a CRC error,
|
||||
|
||||
1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
|
||||
#include <SPI.h> //the SX127X device is SPI based so load the SPI library
|
||||
#include <SX127XLT.h> //include the appropriate library
|
||||
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
|
||||
|
||||
SX127XLT LT; //create a library class instance called LT
|
||||
|
||||
uint32_t RXpacketCount;
|
||||
uint32_t errors;
|
||||
|
||||
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
|
||||
|
||||
uint8_t RXPacketL; //stores length of packet received
|
||||
int8_t PacketRSSI; //stores RSSI of received packet
|
||||
int8_t PacketSNR; //stores signal to noise ratio of received packet
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
|
||||
|
||||
digitalWrite(LED1, HIGH); //something has happened
|
||||
|
||||
if (BUZZER > 0) //turn buzzer on
|
||||
{
|
||||
digitalWrite(BUZZER, HIGH);
|
||||
}
|
||||
|
||||
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
|
||||
PacketSNR = LT.readPacketSNR(); //read the received SNR value
|
||||
|
||||
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_OK();
|
||||
}
|
||||
|
||||
if (BUZZER > 0)
|
||||
{
|
||||
digitalWrite(BUZZER, LOW); //buzzer off
|
||||
}
|
||||
|
||||
digitalWrite(LED1, LOW); //LED off
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void packet_is_OK()
|
||||
{
|
||||
uint16_t IRQStatus, localCRC;
|
||||
|
||||
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
|
||||
|
||||
RXpacketCount++;
|
||||
|
||||
printElapsedTime(); //print elapsed time to Serial Monitor
|
||||
Serial.print(F(" "));
|
||||
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
|
||||
|
||||
localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER
|
||||
Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC
|
||||
Serial.print(localCRC, HEX);
|
||||
Serial.print(F(",RSSI,"));
|
||||
Serial.print(PacketRSSI);
|
||||
Serial.print(F("dBm,SNR,"));
|
||||
Serial.print(PacketSNR);
|
||||
Serial.print(F("dB,Length,"));
|
||||
Serial.print(RXPacketL);
|
||||
Serial.print(F(",Packets,"));
|
||||
Serial.print(RXpacketCount);
|
||||
Serial.print(F(",Errors,"));
|
||||
Serial.print(errors);
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
|
||||
|
||||
printElapsedTime(); //print elapsed time to Serial Monitor
|
||||
|
||||
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
|
||||
{
|
||||
Serial.print(F(" RXTimeout"));
|
||||
}
|
||||
else
|
||||
{
|
||||
errors++;
|
||||
Serial.print(F(" PacketError"));
|
||||
Serial.print(F(",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(",Packets,"));
|
||||
Serial.print(RXpacketCount);
|
||||
Serial.print(F(",Errors,"));
|
||||
Serial.print(errors);
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
LT.printIrqStatus(); //print the names of the IRQ registers set
|
||||
}
|
||||
|
||||
delay(250); //gives a longer buzzer and LED flash for error
|
||||
|
||||
}
|
||||
|
||||
|
||||
void printElapsedTime()
|
||||
{
|
||||
float seconds;
|
||||
seconds = millis() / 1000;
|
||||
Serial.print(seconds, 0);
|
||||
Serial.print(F("s"));
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
if (VCCPOWER >= 0)
|
||||
{
|
||||
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
|
||||
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
|
||||
}
|
||||
|
||||
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("4_LoRa_Receiver_ESP32 Starting"));
|
||||
Serial.println();
|
||||
|
||||
if (BUZZER > 0)
|
||||
{
|
||||
pinMode(BUZZER, OUTPUT);
|
||||
digitalWrite(BUZZER, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(BUZZER, LOW);
|
||||
}
|
||||
|
||||
//SPI.begin(); //default setup can be used be used
|
||||
SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)
|
||||
|
||||
//SPI beginTranscation is normally part of library routines, but if it is disabled in the 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, 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 LED flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
//The function call list below shows the complete setup for the LoRa device using the information defined in the
|
||||
//Settings.h file.
|
||||
//The 'Setup LoRa device' list below can be replaced with a single function call;
|
||||
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
|
||||
|
||||
//***************************************************************************************************
|
||||
//Setup LoRa device
|
||||
//***************************************************************************************************
|
||||
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
|
||||
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
|
||||
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
|
||||
LT.calibrateImage(0); //run calibration after setting frequency
|
||||
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
|
||||
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
|
||||
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
|
||||
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
|
||||
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
|
||||
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done
|
||||
//***************************************************************************************************
|
||||
|
||||
|
||||
Serial.println();
|
||||
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
|
||||
Serial.println();
|
||||
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
|
||||
Serial.println(RXBUFFER_SIZE);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 15/01/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 pin 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 pin on LoRa device
|
||||
#define RFBUSY 25 //busy line
|
||||
|
||||
#define LED1 2 //on board LED, high for on
|
||||
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
|
||||
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
|
||||
#define BUZZER -1 //pin for buzzer, set to -1 if not used
|
||||
#define VCCPOWER 14 //pin controls power to external devices
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
|
||||
|
||||
|
||||
//******* Setup LoRa Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF7; //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, normally set to auto
|
||||
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
|
||||
const uint16_t packet_delay = 1000; //mS delay between packets
|
||||
|
||||
#define RXBUFFER_SIZE 32 //RX buffer size
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 26/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 - This is a program that can be used to test the throughput of a LoRa transmitter.
|
||||
Whilst the various LoRa calculators tell you the on air data rate, in practice the achievable data
|
||||
rate will be less than that due to the overhead of the software routines to load and send a packet
|
||||
and internal delays in the LoRa device itself.
|
||||
|
||||
A buffer is filled with characters and that buffer is then transmitted. The total time for a number of
|
||||
transmissions is recorded and the bit rate calculated. The packet size (1 - 255 bytes) and the number of
|
||||
packets to send in the test are specified in the 'Settings.h' file, see the 'Setup packet parameters Here !'
|
||||
section. The setting file also has the lora settings to use. A lower spreading factors and higher
|
||||
bandwidths will result in higher bitrates.
|
||||
|
||||
There is the option of turning on an a requirement for an acknowledgement from a remote receiver, before
|
||||
the transmitter sends the next packet, set this; 'const bool waitforACK = true;' definition in the
|
||||
settings file.
|
||||
|
||||
The results of the test are printed out thus;
|
||||
|
||||
SX1278,434000000hz,SF7,BW500000,CR4:5,LDRO_Off,SyncWord_0x12,IQNormal,Preamble_8
|
||||
Total Transmit time 50 packets = 567mS
|
||||
Average 10 byte packet transmit time = 11.34mS
|
||||
Bits per packet sent = 80
|
||||
Data rate = 7055bps
|
||||
|
||||
|
||||
Serial monitor baud rate is set at 9600
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
|
||||
#include <SPI.h> //the lora device is SPI based so load the SPI library
|
||||
#include <SX127XLT.h> //include the appropriate library
|
||||
#include <ProgramLT_Definitions.h>
|
||||
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
|
||||
|
||||
SX127XLT LT; //create a library class instance called LT
|
||||
|
||||
uint32_t startmS, endmS, sendtimemS, bitspersecond, bitsPerpacket;
|
||||
uint32_t TXPacketCount;
|
||||
float averagePacketTime;
|
||||
uint8_t packetNumber;
|
||||
uint8_t RXPacketL; //length of received packet
|
||||
uint8_t PacketType; //for packet addressing, identifies packet type received
|
||||
uint32_t packetCheck;
|
||||
bool loopFail = false;
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t index, index2;
|
||||
uint8_t TXBUFFER[TXPacketL + 1]; //create buffer for transmitted packet
|
||||
loopFail = false;
|
||||
|
||||
Serial.println(F("Start transmit test"));
|
||||
|
||||
startmS = millis(); //start transmit timer
|
||||
|
||||
for (index = 0; index < numberPackets; index++)
|
||||
{
|
||||
//fill the buffer
|
||||
for (index2 = 0; index2 < TXPacketL; index2++)
|
||||
{
|
||||
TXBUFFER[index2] = index2;
|
||||
}
|
||||
|
||||
TXBUFFER[0] = TestPacket; //set first byte to identify this test packet
|
||||
TXBUFFER[1] = index; //put the index as packet number in second byte of packet
|
||||
Serial.print(index); //print number of packet sent
|
||||
|
||||
if (waitforACK)
|
||||
{
|
||||
packetCheck = ( (uint32_t) TXBUFFER[4] << 24) + ( (uint32_t) TXBUFFER[3] << 16) + ( (uint32_t) TXBUFFER[2] << 8) + (uint32_t) TXBUFFER[1];
|
||||
Serial.print(F(",Checkvalue,"));
|
||||
Serial.print(packetCheck, HEX);
|
||||
Serial.print(F(","));
|
||||
}
|
||||
|
||||
digitalWrite(LED1, HIGH);
|
||||
|
||||
if (LT.transmit(TXBUFFER, TXPacketL, 2000, TXpower, WAIT_TX)) //will return 0 if transmit error
|
||||
{
|
||||
digitalWrite(LED1, LOW);
|
||||
|
||||
if (waitforACK)
|
||||
{
|
||||
if (!waitAck(packetCheck))
|
||||
{
|
||||
Serial.print(F("NoACKreceived,"));
|
||||
loopFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_Error(); //transmit packet returned 0, there was an error
|
||||
loopFail = true;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
}
|
||||
|
||||
if (!loopFail)
|
||||
{
|
||||
endmS = millis(); //all packets sent, note end time
|
||||
digitalWrite(LED1, LOW);
|
||||
Serial.println();
|
||||
LT.printModemSettings();
|
||||
sendtimemS = endmS - startmS;
|
||||
Serial.println();
|
||||
Serial.print(F("Total transmit time "));
|
||||
Serial.print(numberPackets);
|
||||
Serial.print(F(" packets = "));
|
||||
Serial.print(sendtimemS);
|
||||
Serial.println(F("mS"));
|
||||
|
||||
averagePacketTime = (float) (endmS - startmS) / numberPackets;
|
||||
|
||||
if (waitforACK)
|
||||
{
|
||||
Serial.print(F("Average "));
|
||||
Serial.print(TXPacketL);
|
||||
Serial.print(F(" byte packet transmit and acknowledge time = "));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("Average "));
|
||||
Serial.print(TXPacketL);
|
||||
Serial.print(F(" byte packet transmit time = "));
|
||||
}
|
||||
|
||||
Serial.print(averagePacketTime, 2);
|
||||
Serial.println(F("mS"));
|
||||
|
||||
bitsPerpacket = (uint32_t) (TXPacketL * 8);
|
||||
Serial.print(F("Bits per packet sent = "));
|
||||
Serial.println(bitsPerpacket);
|
||||
|
||||
Serial.print(F("Data rate = "));
|
||||
Serial.print((bitsPerpacket / (averagePacketTime / 1000)), 0);
|
||||
Serial.print(F("bps"));
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
delay(10000); //have a delay between loops so we can see result
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Transmit test failed, trying again"));
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool waitAck(uint32_t TXnum)
|
||||
{
|
||||
uint32_t RXnum;
|
||||
uint16_t IRQStatus;
|
||||
|
||||
RXPacketL = LT.receiveSXBuffer(0, 1000, WAIT_RX); //returns 0 if packet error of some sort
|
||||
|
||||
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
|
||||
|
||||
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
|
||||
{
|
||||
Serial.print(F("RXTimeout,"));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("ACKRX,"));
|
||||
}
|
||||
|
||||
LT.startReadSXBuffer(0);
|
||||
PacketType = LT.readUint8();
|
||||
RXnum = LT.readUint32();
|
||||
RXPacketL = LT.endReadSXBuffer();
|
||||
|
||||
if ( (PacketType != ACK) || (RXnum != TXnum))
|
||||
{
|
||||
Serial.print(F("NotValidACK,"));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(RXnum, HEX);
|
||||
Serial.print(F(",OK"));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
//if here there was an error transmitting packet
|
||||
uint16_t IRQStatus;
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
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("42_LoRa_Data_Throughput_Transmitter_Test_ESP32 Starting"));
|
||||
|
||||
SPI.begin();
|
||||
|
||||
//setup hardware pins used by device, then check if device is found
|
||||
if (LT.begin(NSS, NRESET, DIO1, 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.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();
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Transmitter ready"));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 26/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.
|
||||
*******************************************************************************************************/
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions for one of my own boards, the an ESP32 shield base.
|
||||
|
||||
#define SCK 18 //SCK on SPI3
|
||||
#define MISO 19 //MISO on SPI3
|
||||
#define MOSI 23 //MOSI on SPI3
|
||||
|
||||
#define NSS 5 //select pin on LoRa device
|
||||
#define NRESET 27 //reset pin on LoRa device
|
||||
#define RFBUSY 25 //busy line
|
||||
#define DIO1 35 //DIO1 pin on LoRa device, used for RX and TX done
|
||||
|
||||
#define LED1 2 //on board LED, high for on
|
||||
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
|
||||
|
||||
|
||||
//******* Setup LoRa Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF7; //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, normally set to auto
|
||||
|
||||
const int8_t TXpower = 14; //LoRa transmit power in dBm
|
||||
|
||||
|
||||
//******* Setup packet parameters Here ! ***************
|
||||
const uint8_t numberPackets = 100; //number of packets to send in transmit loop
|
||||
const uint8_t TXPacketL = 255; //length of packet to send
|
||||
const bool waitforACK = false; //set to true to have transmit wait for ack before continuing
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 209 KiB |
111
lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/ReadMe.md
Normal file
111
lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/ReadMe.md
Normal file
@@ -0,0 +1,111 @@
|
||||
## ESP32 - SX12XX Library Example Programs
|
||||
|
||||
Having originally tested the SX127X part of the library on a ATMega328P based micro controller I decided to check that the library was code compatible with another popular processor that can be programmed in the Arduino IDE, the ESP32.
|
||||
|
||||
Unfortunately there is frequently a misunderstanding about what an 'ESP32' is. The ESP32 is a single surface mountable module to which you need to add various components to make a usable board. However the many different types of 'ESP32' boards may use different types of components and connections which could conflict with the pins used in the library examples here. It is not practical to test the examples on all possible permutations of 'ESP32' assembled boards, there are over 60 different boards supported by the Arduino IDE and I would go poor buying them all.
|
||||
|
||||
Thus the ESP32 examples presented here have been tested against a known standard which is an actual ESP32 Wroom module with no additional hardware, apart from the components shown in the schematic below. It is possible that the examples will not work against your particular 'ESP32' assembled board. If the example programs do not work for you, it is not an issue with the library but a difference between the reference hardware and your particular setup. I am not in a position to assist in resolving issues with particular ESP32 board versions.
|
||||
|
||||

|
||||
|
||||
|
||||
As well as testing against the bare bones ESP32 schematic shown above, some of the examples will have been tested on a small portable unit I built which follows the same principles of the bare bones schematic. This PCB was developed to create a PCB that could be used for a small ESP32 based GPS tracker node, initially for use on The Things Network. The board has a GPS, I2C SSD1306 OLED and RFM98 lora device. There are options for a micro SD card, DS18B20 temperature sensor and a I2C FRAM. With it all assembled, the node consumes around 31uA in deep sleep with all devices connected. The 'Micro\_Node' contains additional circuitry to power off devices such as the lora module and GPS. Its highly unlikely that a standard ESP32 board will achieve a sleep current anywhere near the 'Micro_Node', this unit is pictured below;
|
||||
|
||||

|
||||
|
||||
|
||||
### ESP32 Deep Sleep
|
||||
|
||||
The ESP32 does some things with I\O pins when going into deep sleep that you might not expect. There are functions in this SX12XX library for putting the LoRa device into deep sleep, whilst still preserving register settings. The current then taken by the lora device is circa 0.5uA. However these functions will likely not work directly with most ESP32 boards due to the way the ESP32 handles the I\O pins in deep sleep mode.
|
||||
|
||||
When designing a board where a very low deep sleep current it is important, you need to build the design in stages, checking the deep sleep current after adding each component. Debugging a high deep sleep current on a fully assembled board can be from extremely difficult to impossible. Achieving a low deep sleep current for particular ESP32 boards is well outside the scope of this SX12xx library.
|
||||
|
||||
<br>
|
||||
|
||||
**3\_LoRa\_Transmitter and 4\_LoRa\_Receiver example programs**
|
||||
|
||||
These example programs work when used with the ESP32 'bare bones' schematic shown earlier and the 'ESP32 Dev Module' board type selected in the Arduino IDE.
|
||||
|
||||
The pins used for SPI were;
|
||||
|
||||
SCK 18
|
||||
MISO 19
|
||||
MOSI 23
|
||||
NSS 5
|
||||
NRESET 27
|
||||
RFBUSY 25 (SX126X and SX128X devices only)
|
||||
DIOX 35 (DIOX is DIO0 on the SX127X devices and DIO1 on SX126X and SX128X devices)
|
||||
|
||||
In the example programs for ESP32, you can start the SPI with;
|
||||
|
||||
SPI.begin();
|
||||
|
||||
And the default SPI pin outs for the ESP32 module shown above will be used.
|
||||
|
||||
Alternatively you can uses this format to start SPI;
|
||||
|
||||
SPI.begin(SCK, MISO, MOSI, NSS);
|
||||
|
||||
And the pin definitions will be taken from those specified in the 'Settings.h' file. If you change these pin allocations from the defaults given you will need to be sure they are valid for your particular ESP32 board.
|
||||
|
||||
|
||||
The SX12XX example programs are specifically written for and and tested on ATmega processors such as 328,1284 and 2560. However most will work, with minor modification, on the ESP32.
|
||||
|
||||
This is a run through of the changes that were needed to have the tracker receiver examples; **25\_GPS\_Tracker\_Receiver\_With\_Display\_and\_GPS**, written for the ATmega328P run on the ESP32 bare bones type boards described above.
|
||||
|
||||
The original SX12XX tracker program uses the SPI interface to talk to the lora device, I2C to talk to the OLED display and software serial to talk to the GPS.
|
||||
|
||||
The pins used for SPI were;
|
||||
|
||||
SCK 18
|
||||
MISO 19
|
||||
MOSI 23
|
||||
NSS 5
|
||||
NRESET 27
|
||||
RFBUSY 25 (SX126X and SX128X devices only)
|
||||
DIOX 35 (DIOX is DIO0 on the SX127X devices and DIO1 on SX126X and SX128X devices)
|
||||
|
||||
The ESP32 I2C pin connections were;
|
||||
|
||||
SDA 21
|
||||
SCL 22
|
||||
|
||||
There is no need for software serial on the ESP32 as it has an available hardware serial port. These are the pin connections used;
|
||||
|
||||
GPSTX 16 //this is data out from the GPS into the ESP32
|
||||
GPSRX 17 //this is data out from the ESP32 into the GPS
|
||||
|
||||
The other pins used were;
|
||||
|
||||
LED1 2 //On board indicator LED, logic high for on
|
||||
GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
|
||||
|
||||
The only software changes required were to change the lines in the Settings.h file from;
|
||||
|
||||
#define USE_SOFTSERIAL_GPS
|
||||
#define HardwareSerialPort Serial2
|
||||
|
||||
to;
|
||||
|
||||
//#define USE_SOFTSERIAL_GPS
|
||||
#define HardwareSerialPort Serial2
|
||||
|
||||
This removes the definition USE\_SOFTSERIAL\_GPS from the sketch and the effect of this change is then to remove these two lines from the Sketch;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial GPSserial(RXpin, Txpin);
|
||||
|
||||
And include this one;
|
||||
|
||||
#define GPSserial HardwareSerialPort
|
||||
|
||||
Which sets the commands to read data from the GPS such as GPSserial.read() to be in effect Serial2.read(), which is the ESP32 hardware serial port used.
|
||||
|
||||
|
||||
**Note:** The provided lora settings (in the Settings.h file) may not be optimised for long distance. See the 'What is LoRa' document for information on how LoRa settings affect range.
|
||||
|
||||
|
||||
### Stuart Robinson
|
||||
|
||||
### April 2020
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
/*******************************************************************************************************
|
||||
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 - The program transmits a LoRa packet without using a processor buffer, the LoRa
|
||||
devices internal buffer is filled directly with variables.
|
||||
|
||||
The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There
|
||||
is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end.
|
||||
|
||||
Although the LoRa packet transmitted and received has its own internal CRC error checking, you could
|
||||
still receive packets of the same length from another source. If this valid packet were to be used
|
||||
to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet
|
||||
is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet.
|
||||
This CRC value is read by the receiver and used to check that the received CRC matches the supposed
|
||||
sensor data in the packet. As an additional check there is some addressing information at the beginning
|
||||
of the packet which is also checked for validity. Thus we can be relatively confident when reading the
|
||||
received packet that its genuine and from this transmitter. The packet is built and sent in the
|
||||
sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to
|
||||
the packet.
|
||||
|
||||
Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of
|
||||
8 seconds using the Atmel processor internal watchdog.
|
||||
|
||||
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
|
||||
|
||||
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.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX127XLT.h>
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
SX127XLT LT;
|
||||
|
||||
#include <Seeed_BME280.h> //get library here; https://github.com/Seeed-Studio/Grove_BME280
|
||||
BME280 bme280; //create an instance of the BME280 senosor
|
||||
#include <Wire.h>
|
||||
|
||||
uint32_t TXpacketCount;
|
||||
uint8_t TXPacketL;
|
||||
|
||||
float temperature; //the BME280 temperature value
|
||||
float pressure; //the BME280 pressure value
|
||||
uint16_t humidity; //the BME280 humididty value
|
||||
uint16_t voltage; //the battery voltage value
|
||||
uint8_t statusbyte; //a status byte, not currently used
|
||||
uint16_t CRCvalue; //the CRC value of the packet data up to this point
|
||||
uint8_t packetlength; //the packet length that was sent, checked against length received
|
||||
|
||||
|
||||
#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds
|
||||
|
||||
void loop()
|
||||
{
|
||||
TXpacketCount++;
|
||||
Serial.print(TXpacketCount); //print the numbers of sends
|
||||
Serial.print(F(" Sending > "));
|
||||
|
||||
readSensors(); //read the sensor values
|
||||
printSensorValues(); //print the sensor values
|
||||
|
||||
if (sendSensorPacket())
|
||||
{
|
||||
Serial.println(F("SentOK"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("Send Error - IRQreg,"));
|
||||
Serial.println(LT.readIrqStatus(), HEX);
|
||||
}
|
||||
|
||||
Serial.print(F("Sleeping zzzz"));
|
||||
Serial.flush(); //make sure all serial output has gone
|
||||
|
||||
//now put the sensor, LoRa device and processor to sleep
|
||||
sleepBME280(); //sleep the BME280
|
||||
|
||||
digitalWrite(VCCPOWER, HIGH); //VCCOUT off. lora device off
|
||||
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
|
||||
esp_deep_sleep_start();
|
||||
|
||||
//wait a bit ................
|
||||
Serial.println(F("Why are we here, ESP32 should re-start on wakeup ?")); //the processor has woken up ?
|
||||
Serial.println();
|
||||
normalBME280(); //BME280 sensor to normal mode
|
||||
}
|
||||
|
||||
|
||||
uint8_t sendSensorPacket()
|
||||
{
|
||||
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
|
||||
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
|
||||
uint8_t len;
|
||||
|
||||
LT.startWriteSXBuffer(0); //start the write packet to buffer process
|
||||
|
||||
LT.writeUint8(Sensor1); //this byte defines the packet type
|
||||
LT.writeUint8('B'); //this byte identifies the destination node of the packet
|
||||
LT.writeUint8(1); //this byte identifies the source node of the packet
|
||||
|
||||
/************************************************************************
|
||||
Highlighted section - this is where the actual sensor data is added to the packet
|
||||
************************************************************************/
|
||||
LT.writeFloat(temperature); //add the BME280 temperature
|
||||
LT.writeFloat(pressure); //add the BME280 pressure
|
||||
LT.writeUint16(humidity); //add the BME280 humididty
|
||||
LT.writeUint16(voltage); //add the battery voltage
|
||||
LT.writeUint8(statusbyte); //add the status byte
|
||||
/************************************************************************/
|
||||
|
||||
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
|
||||
|
||||
addPacketErrorCheck(len); //add the additional CRC error checking to the packet end
|
||||
|
||||
//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 + 2), 5000, TXpower, WAIT_TX);
|
||||
digitalWrite(LED1, LOW); //turn off indicator LED
|
||||
|
||||
return TXPacketL; //TXPacketL will be 0 if there was an error sending
|
||||
}
|
||||
|
||||
|
||||
void addPacketErrorCheck(uint8_t len)
|
||||
{
|
||||
//calculate the CRC of packet sensor data
|
||||
CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF);
|
||||
|
||||
Serial.print(F("Calculated CRC value "));
|
||||
Serial.println(CRCvalue, HEX);
|
||||
|
||||
LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data
|
||||
LT.writeUint16(CRCvalue); //add the actual CRC value
|
||||
LT.endWriteSXBuffer(); //close the packet
|
||||
}
|
||||
|
||||
|
||||
void readSensors()
|
||||
{
|
||||
//read the sensor values into the global variables
|
||||
temperature = bme280.getTemperature();
|
||||
pressure = bme280.getPressure();
|
||||
humidity = bme280.getHumidity();
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
voltage = readBatteryVoltage(); //read resistor divider across battery
|
||||
}
|
||||
else
|
||||
{
|
||||
voltage = 9999; //set a default value
|
||||
}
|
||||
statusbyte = 0x55; //manually set this for now, its a test
|
||||
}
|
||||
|
||||
|
||||
void printSensorValues()
|
||||
{
|
||||
Serial.print(F("Temperature,"));
|
||||
Serial.print(temperature, 1);
|
||||
Serial.print(F("c,Pressure,"));
|
||||
Serial.print(pressure, 0);
|
||||
Serial.print(F("Pa,Humidity,"));
|
||||
Serial.print(humidity);
|
||||
Serial.print(F("%,Voltage,"));
|
||||
Serial.print(voltage);
|
||||
Serial.print(F("mV,Status,"));
|
||||
Serial.print(statusbyte, HEX);
|
||||
Serial.print(F(" "));
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
|
||||
void sleepBME280()
|
||||
{
|
||||
//write this register value to BME280 to put it to sleep
|
||||
writeBME280reg(BME280_REGISTER_CONTROL, B01111100);
|
||||
}
|
||||
|
||||
|
||||
void normalBME280()
|
||||
{
|
||||
//write this register value to BME280 to put it to read mode
|
||||
writeBME280reg(BME280_REGISTER_CONTROL, B01111111);
|
||||
}
|
||||
|
||||
|
||||
void writeBME280reg(byte reg, byte regvalue)
|
||||
{
|
||||
//write a register value to the BME280
|
||||
Wire.beginTransmission((uint8_t) BME280_ADDRESS);
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.write((uint8_t)regvalue);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
uint16_t readBatteryVoltage()
|
||||
{
|
||||
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(BATTERYAD);
|
||||
|
||||
for (index = 0; index <= 4; index++) //sample AD 5 times
|
||||
{
|
||||
temp = analogRead(BATTERYAD);
|
||||
volts = volts + temp;
|
||||
}
|
||||
volts = ((volts / 5) * ADMultiplier);
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit
|
||||
}
|
||||
|
||||
return volts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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); //for PCB LED
|
||||
led_Flash(2, 125);
|
||||
|
||||
if (VCCPOWER >= 0)
|
||||
{
|
||||
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
|
||||
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
|
||||
}
|
||||
|
||||
if (BATVREADON >= 0)
|
||||
{
|
||||
pinMode(BATVREADON, OUTPUT);
|
||||
}
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.println(F("Reset"));
|
||||
|
||||
SPI.begin();
|
||||
|
||||
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
|
||||
{
|
||||
Serial.println(F("lora Device pins initialised"));
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates LoRa device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
|
||||
Serial.println(F("Setup lora device"));
|
||||
|
||||
if (!bme280.init())
|
||||
{
|
||||
Serial.println("BME280 Device error!");
|
||||
led_Flash(100, 15); //long very fast speed flash indicates BME280 device error
|
||||
}
|
||||
|
||||
Serial.println(F("Initialised BME280"));
|
||||
|
||||
Serial.println();
|
||||
Serial.println(F("Transmitter ready"));
|
||||
Serial.println();
|
||||
|
||||
readSensors(); //do an initial sensor read
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************************************
|
||||
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 pin 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 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 DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
|
||||
#define BUZZER -1 //pin for buzzer, set to -1 if not used
|
||||
#define VCCPOWER 14 //pin controls power to external devices
|
||||
#define BATTERYAD 36 //pin for reading supply voltage
|
||||
#define BATVREADON 25 //when high turns on the resistor divider to measure voltage, -1 if not used
|
||||
#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV
|
||||
|
||||
#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_125; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF7; //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 = 14; //LoRa transmit power in dBm
|
||||
|
||||
#define BME280_ADDRESS 0x76 //I2C bus address of BME280
|
||||
#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control
|
||||
|
||||
const uint16_t TIME_TO_SLEEP = 16; //Time ESP32 will go to sleep (in seconds)
|
||||
@@ -0,0 +1,358 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 21/01/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 - The program receives a LoRa packet without using a processor buffer, the LoRa devices
|
||||
internal buffer is read direct for the received sensor data.
|
||||
|
||||
The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity,
|
||||
and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status
|
||||
value at the end of the packet.
|
||||
|
||||
When a packet is received its printed and assuming the packet is validated, the sensor results are printed
|
||||
to the serial monitor and screen.
|
||||
|
||||
For the sensor data to be accepted as valid the folowing need to match;
|
||||
|
||||
The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet.
|
||||
The packet must start with a byte that matches the packet type sent, 'Sensor1'
|
||||
The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node'
|
||||
|
||||
In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid
|
||||
packet is acted on and erroneous values displayed.
|
||||
|
||||
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX127XLT.h>
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
SX127XLT LT;
|
||||
|
||||
#include <U8x8lib.h> //get library here > https://github.com/olikraus/u8g2
|
||||
U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306
|
||||
//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306
|
||||
|
||||
uint32_t RXpacketCount; //count of all packets received
|
||||
uint32_t ValidPackets; //count of packets received with valid data
|
||||
uint32_t RXpacketErrors; //count of all packets with errors received
|
||||
bool packetisgood;
|
||||
|
||||
uint8_t RXPacketL; //length of received packet
|
||||
int8_t PacketRSSI; //RSSI of received packet
|
||||
int8_t PacketSNR; //signal to noise ratio of received packet
|
||||
|
||||
uint8_t RXPacketType;
|
||||
uint8_t RXDestination;
|
||||
uint8_t RXSource;
|
||||
float temperature; //the BME280 temperature value
|
||||
float pressure; //the BME280 pressure value
|
||||
uint16_t humidity; //the BME280 humididty value
|
||||
uint16_t voltage; //the battery voltage value
|
||||
uint8_t statusbyte; //a status byte, not currently used
|
||||
uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set
|
||||
|
||||
digitalWrite(LED1, HIGH); //something has happened
|
||||
|
||||
PacketRSSI = LT.readPacketRSSI();
|
||||
PacketSNR = LT.readPacketSNR();
|
||||
|
||||
if (RXPacketL == 0)
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want
|
||||
}
|
||||
|
||||
digitalWrite(LED1, LOW);
|
||||
Serial.println();
|
||||
//SPI.endTransaction();
|
||||
}
|
||||
|
||||
|
||||
void packet_Received_OK()
|
||||
{
|
||||
//a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from
|
||||
//an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data
|
||||
|
||||
uint8_t len;
|
||||
uint8_t contenterrors; //keep a count of errors found in packet
|
||||
|
||||
RXpacketCount++;
|
||||
Serial.print(RXpacketCount);
|
||||
Serial.print(F(",PacketsReceived,"));
|
||||
|
||||
LT.startReadSXBuffer(0);
|
||||
RXPacketType = LT.readUint8();
|
||||
RXDestination = LT.readUint8();
|
||||
RXSource = LT.readUint8();
|
||||
|
||||
/************************************************************************
|
||||
Highlighted section - this is where the actual sensor data is read from
|
||||
the packet
|
||||
************************************************************************/
|
||||
temperature = LT.readFloat(); //the BME280 temperature value
|
||||
pressure = LT.readFloat(); //the BME280 pressure value
|
||||
humidity = LT.readUint16(); //the BME280 humididty value
|
||||
voltage = LT.readUint16(); //the battery voltage value
|
||||
statusbyte = LT.readUint8(); //a status byte, not currently used
|
||||
/************************************************************************/
|
||||
|
||||
len = LT.endReadSXBuffer(); //note len is bytes read from packet, may be different to actual packet length
|
||||
|
||||
printreceptionDetails(); //print details of reception, RSSI etc
|
||||
Serial.println();
|
||||
|
||||
contenterrors = checkPacketValid(len); //pass length of packet to check routine
|
||||
|
||||
if (contenterrors == 0)
|
||||
{
|
||||
Serial.println(F(" Packet is good"));
|
||||
ValidPackets++;
|
||||
printSensorValues(); //print the sensor values
|
||||
Serial.println();
|
||||
printPacketCounts(); //print count of valid packets and errors
|
||||
displayscreen1();
|
||||
Serial.println();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F(" Packet is not valid"));
|
||||
RXpacketErrors++;
|
||||
disp.clearLine(7);
|
||||
disp.setCursor(0, 7);
|
||||
disp.print(F("Errors "));
|
||||
disp.print(RXpacketErrors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t checkPacketValid(uint8_t len)
|
||||
{
|
||||
//this function checks if the packet is valid and will be displayed
|
||||
|
||||
uint8_t errors = 0;
|
||||
|
||||
if (RXPacketType != Sensor1) //is it a Sensor1 type packet
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (RXDestination != This_Node) //was the packet sent to this receiver node ?
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ?
|
||||
{
|
||||
errors++;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.print(F("Error Check Count = "));
|
||||
Serial.print(errors);
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
bool checkCRCvalue(uint8_t len)
|
||||
{
|
||||
uint16_t CRCSensorData;
|
||||
//uint8_t msb, lsb;
|
||||
|
||||
CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data
|
||||
|
||||
Serial.print(F("(CRC of Received sensor data "));
|
||||
Serial.print(CRCSensorData, HEX);
|
||||
Serial.print(F(")" ));
|
||||
|
||||
//SPI.endTransaction();
|
||||
|
||||
TXCRCvalue = ((LT.getByteSXBuffer(17) << 8) + (LT.getByteSXBuffer(16)));
|
||||
|
||||
Serial.print(F("(CRC transmitted "));
|
||||
Serial.print(TXCRCvalue, HEX);
|
||||
Serial.print(F(")" ));
|
||||
|
||||
if (TXCRCvalue != CRCSensorData)
|
||||
{
|
||||
Serial.print(F(" Sensor Data Not Valid"));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F(" Sensor Data is Valid"));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void printSensorValues()
|
||||
{
|
||||
Serial.print(F("Temperature,"));
|
||||
Serial.print(temperature, 1);
|
||||
Serial.print(F("c,Pressure,"));
|
||||
Serial.print(pressure, 0);
|
||||
Serial.print(F("Pa,Humidity,"));
|
||||
Serial.print(humidity);
|
||||
Serial.print(F("%,Voltage,"));
|
||||
Serial.print(voltage);
|
||||
Serial.print(F("mV,Status,"));
|
||||
Serial.print(statusbyte, HEX);
|
||||
Serial.print(F(",CRC,"));
|
||||
Serial.print(TXCRCvalue, HEX);
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
|
||||
void printreceptionDetails()
|
||||
{
|
||||
Serial.print(F("RSSI"));
|
||||
Serial.print(PacketRSSI);
|
||||
Serial.print(F("dBm,SNR,"));
|
||||
Serial.print(PacketSNR);
|
||||
Serial.print(F("dB,Length,"));
|
||||
Serial.print(LT.readRXPacketL());
|
||||
}
|
||||
|
||||
|
||||
void printPacketCounts()
|
||||
{
|
||||
Serial.print(F("ValidPackets,"));
|
||||
Serial.print(ValidPackets);
|
||||
Serial.print(F(",Errors,"));
|
||||
Serial.print(RXpacketErrors);
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
|
||||
RXpacketErrors++;
|
||||
IRQStatus = LT.readIrqStatus();
|
||||
|
||||
if (IRQStatus & IRQ_RX_TIMEOUT)
|
||||
{
|
||||
Serial.print(F("RXTimeout "));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("PacketError "));
|
||||
printreceptionDetails();
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
LT.printIrqStatus();
|
||||
Serial.println();
|
||||
disp.clearLine(7);
|
||||
disp.setCursor(0, 7);
|
||||
disp.print(F("Errors "));
|
||||
disp.print(RXpacketErrors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void displayscreen1()
|
||||
{
|
||||
//show sensor data on display
|
||||
disp.clearLine(0);
|
||||
disp.setCursor(0, 0);
|
||||
disp.print(F("Sensor "));
|
||||
disp.print(RXSource);
|
||||
disp.clearLine(1);
|
||||
disp.setCursor(0, 1);
|
||||
disp.print(temperature, 1);
|
||||
disp.print(F("c"));
|
||||
disp.clearLine(2);
|
||||
disp.setCursor(0, 2);
|
||||
disp.print(pressure, 0);
|
||||
disp.print(F("Pa"));
|
||||
disp.clearLine(3);
|
||||
disp.setCursor(0, 3);
|
||||
disp.print(humidity);
|
||||
disp.print(F("%"));
|
||||
disp.clearLine(4);
|
||||
disp.setCursor(0, 4);
|
||||
disp.print(voltage);
|
||||
disp.print(F("mV"));
|
||||
disp.clearLine(6);
|
||||
disp.setCursor(0, 6);
|
||||
disp.print(F("ValidPkts "));
|
||||
disp.print(ValidPackets);
|
||||
disp.setCursor(0, 7);
|
||||
disp.print(F("Errors "));
|
||||
disp.print(RXpacketErrors);
|
||||
}
|
||||
|
||||
|
||||
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(VCCPOWER, OUTPUT); //this pin switches power for external devices, lora and SD card
|
||||
digitalWrite(VCCPOWER, LOW); //turn power on
|
||||
|
||||
pinMode(LED1, OUTPUT);
|
||||
led_Flash(2, 125);
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
disp.begin();
|
||||
disp.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
disp.clear();
|
||||
disp.setCursor(0, 0);
|
||||
disp.print(F("Check LoRa"));
|
||||
disp.setCursor(0, 1);
|
||||
|
||||
SPI.begin();
|
||||
|
||||
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
|
||||
{
|
||||
disp.print(F("LoRa OK"));
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
disp.print(F("Device error"));
|
||||
Serial.println(F("Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
|
||||
|
||||
Serial.println(F("Receiver ready"));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 17/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 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 pin 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 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 DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
|
||||
#define BUZZER -1 //pin for buzzer, set to -1 if not used
|
||||
#define VCCPOWER 14 //pin controls power to external devices
|
||||
#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_125; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF7; //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 = 2; //LoRa TX power
|
||||
|
||||
#define packet_delay 1000 //mS delay between packets
|
||||
#define This_Node 'B' //this is the node that the remote sensors send data to
|
||||
|
||||
//**************** Setup Display Parameters Here ****************
|
||||
|
||||
//const uint8_t dispfont = u8x8_font_chroma48medium8_r; //display font from u8g2 library
|
||||
@@ -0,0 +1,268 @@
|
||||
/*******************************************************************************************************
|
||||
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 tests the sleep mode and register retention of the SX127X in sleep mode,
|
||||
it assumes an ESP32 processor module. The LoRa settings to use are specified in the 'Settings.h' file.
|
||||
To retain the program memory, so that the program restarts after sleep at the next instructions after
|
||||
going into sleep mode the ESP32 light sleep function is used.
|
||||
|
||||
A packet is sent, containing the text 'Before Device Sleep' and the LoRa device and ESP32 are put to sleep.
|
||||
The ESP32 internal RTC timer should wakeup the processor in 15 seconds (approx) and lora register
|
||||
values should be retained. The device then attempts to transmit another packet 'After Device Sleep'
|
||||
without re-loading all the lora settings. The receiver should see 'After Device Sleep' for the first
|
||||
packet and 'After Device Sleep' for the second.
|
||||
|
||||
For unknown reasons the ESP32 pulses the pin used by NRESET when going into sleep modes, so the program
|
||||
turns it into an input for the duration of the sleep to avoid resetting the lora device.
|
||||
|
||||
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.
|
||||
|
||||
Tested on a 'bare bones' ESP32 the current in light sleep mode was 1670uA.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define Program_Version "V1.0"
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX127XLT.h>
|
||||
#include "Settings.h"
|
||||
|
||||
SX127XLT LT;
|
||||
|
||||
boolean SendOK;
|
||||
int8_t TestPower;
|
||||
uint8_t TXPacketL;
|
||||
|
||||
/***********************************************************
|
||||
//ESP32 specific settings
|
||||
***********************************************************/
|
||||
#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds
|
||||
#define TIME_TO_SLEEP 15 //Time ESP32 will go to sleep (in seconds)
|
||||
RTC_DATA_ATTR int16_t bootCount = 0;
|
||||
RTC_DATA_ATTR uint16_t sleepcount = 0;
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print(F("Bootcount "));
|
||||
Serial.println(bootCount);
|
||||
Serial.print(F("Sleepcount "));
|
||||
Serial.println(sleepcount);
|
||||
|
||||
Serial.println();
|
||||
LT.printRegisters(0x00, 0x7F);
|
||||
Serial.println();
|
||||
|
||||
digitalWrite(LED1, HIGH);
|
||||
Serial.print(TXpower);
|
||||
Serial.print(F("dBm "));
|
||||
Serial.print(F("TestPacket1> "));
|
||||
Serial.flush();
|
||||
|
||||
if (Send_Test_Packet1())
|
||||
{
|
||||
packet_is_OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
Serial.println();
|
||||
delay(packet_delay);
|
||||
|
||||
pinMode(NRESET, INPUT); //change NRESET pin to INPUT mode
|
||||
|
||||
|
||||
LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep.
|
||||
|
||||
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
|
||||
Serial.println(F("Start Sleep"));
|
||||
Serial.flush();
|
||||
sleepcount++;
|
||||
|
||||
esp_light_sleep_start();
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println(F("Awake !"));
|
||||
Serial.flush();
|
||||
digitalWrite(LED1, HIGH);
|
||||
|
||||
LT.wake();
|
||||
|
||||
digitalWrite(NRESET, HIGH); //set NRESET high before turning it back to an output
|
||||
pinMode(NRESET, INPUT); //set NRESET as an output
|
||||
|
||||
Serial.print(TXpower);
|
||||
Serial.print(F("dBm "));
|
||||
Serial.print(F("TestPacket2> "));
|
||||
Serial.flush();
|
||||
|
||||
if (Send_Test_Packet2())
|
||||
{
|
||||
packet_is_OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
Serial.println();
|
||||
delay(packet_delay);
|
||||
}
|
||||
|
||||
|
||||
void packet_is_OK()
|
||||
{
|
||||
Serial.print(F(" "));
|
||||
Serial.print(TXPacketL);
|
||||
Serial.print(F(" Bytes SentOK"));
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
IRQStatus = LT.readIrqStatus(); //get the IRQ status
|
||||
Serial.print(F("SendError,"));
|
||||
Serial.print(F("Length,"));
|
||||
Serial.print(TXPacketL);
|
||||
Serial.print(F(",IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
LT.printIrqStatus();
|
||||
digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error
|
||||
}
|
||||
|
||||
|
||||
bool Send_Test_Packet1()
|
||||
{
|
||||
uint8_t bufffersize;
|
||||
|
||||
uint8_t buff[] = "Before Device Sleep";
|
||||
TXPacketL = sizeof(buff);
|
||||
buff[TXPacketL - 1] = '*';
|
||||
|
||||
if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER
|
||||
{
|
||||
bufffersize = TXBUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufffersize = sizeof(buff);
|
||||
}
|
||||
|
||||
TXPacketL = bufffersize;
|
||||
|
||||
LT.printASCIIPacket( (uint8_t*) buff, bufffersize);
|
||||
digitalWrite(LED1, HIGH);
|
||||
|
||||
if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX))
|
||||
{
|
||||
digitalWrite(LED1, LOW);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Send_Test_Packet2()
|
||||
{
|
||||
uint8_t bufffersize;
|
||||
|
||||
uint8_t buff[] = "After Device Sleep";
|
||||
TXPacketL = sizeof(buff);
|
||||
buff[TXPacketL - 1] = '*';
|
||||
|
||||
if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER
|
||||
{
|
||||
bufffersize = TXBUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufffersize = sizeof(buff);
|
||||
}
|
||||
|
||||
TXPacketL = bufffersize;
|
||||
|
||||
LT.printASCIIPacket( (uint8_t*) buff, bufffersize);
|
||||
digitalWrite(LED1, HIGH);
|
||||
|
||||
if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX))
|
||||
{
|
||||
digitalWrite(LED1, LOW);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
if (VCCPOWER >= 0)
|
||||
{
|
||||
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
|
||||
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
|
||||
}
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
Serial.print(__TIME__);
|
||||
Serial.print(F(" "));
|
||||
Serial.println(__DATE__);
|
||||
Serial.println(F(Program_Version));
|
||||
Serial.println();
|
||||
Serial.println(F("5_LoRa_TX_Sleep_Timed_Wakeup_ESP32 Starting"));
|
||||
|
||||
SPI.begin();
|
||||
|
||||
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.print(F("Transmitter ready - TXBUFFER_SIZE "));
|
||||
Serial.println(TXBUFFER_SIZE);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************************************
|
||||
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 definitions to match your own setup. Some pins such as DIO1,
|
||||
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
|
||||
//connected and should be included and be set to -1.
|
||||
|
||||
#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 DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
|
||||
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
|
||||
#define VCCPOWER 14 //pin controls power to external devices
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
|
||||
|
||||
|
||||
//******* Setup lora Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
|
||||
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF7; //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, normally set to auto
|
||||
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
|
||||
const uint16_t packet_delay = 1000; //mS delay between packets
|
||||
|
||||
#define TXBUFFER_SIZE 32 //RX buffer size
|
||||
|
||||
|
||||
@@ -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