first commit

This commit is contained in:
2021-05-11 20:43:42 +03:00
commit 9f3ffaba30
381 changed files with 69596 additions and 0 deletions

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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();
}

View File

@@ -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