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

46
lib/README Normal file
View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

442
lib/SX12XX-LoRa/ReadMe.md Normal file
View File

@@ -0,0 +1,442 @@
# SX12XX Library
### Library installation
To install the library select the 'Clone or download' button on the main Github page, then select 'Download Zip'. In the Arduino IDE select 'Sketch' then 'Include Library'. Next select 'Add .ZIP library' and browse to and select the ZIP file you downloaded, it's called 'SX12xx-master.zip'.
### Warning
**The Semtech devices that this library supports are all 3.3V logic level devices so do not use directly with 5V logic level Arduinos, some form of logic level conversion is needed.** There are no specific logic level converters I could recommend.
<a href="https://www.buymeacoffee.com/stuartsprojects"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
This library supports the SX126x, SX127x and SX128x Semtech LoRa devices. There is a wide range of example programs for these devices. These Semtech devices are used to manufacture a range of LoRa modules sold by companies such as Hope, Dorji, NiceRF and others. The library does not support LoRa modules with a UART based interface such as those from Ebyte and Microchip.
The objective of the library was to allow the same program sketches to be used across the range of UHF lora modules SX126x and SX127x (UHF) as well as the 2.4Ghz SX128x modules. A sketch written for the SX1278 (for example) should then run with very minor changes on the SX1262 or SX1280. However, whilst the SX126x and SX128x modules use the same style of device programming, the SX127x programming is completely different. The function style used for the SX126x and SX128x devices has been copied to create a matching style for the SX127x.
A conventional lora library normally uses a buffer of data created within the Arduino sketch to contain the data that is sent as a packet. This library has those functions, see the example programs 3 and 4 in the 'Basics' folder. There are examples for sending\receiving a simple character buffer ("Hello World") and for sending\receiving a data structure which can also include a character buffer.
###Direct access to lora device internal data buffer
An additional library feature has been implemented to enable variables or character data to be written direct to the lora devices internal buffer. This has the benefit of not requiring a memory buffer in the Arduino and also lends itself to a simple way of sending and receiving packets. For instance this is the routine to create a packet for transmission taken from the 'LowMemory' folder;
LT.startWriteSXBuffer(0); //start the write at location 0
LT.writeBuffer(trackerID, sizeof(trackerID)); //= 13 bytes (12 characters plus null (0) at end)
LT.writeUint32(TXpacketCount); //+4 = 17 bytes
LT.writeFloat(latitude); //+4 = 21 bytes
LT.writeFloat(longitude); //+4 = 25 bytes
LT.writeUint16(altitude); //+2 = 27 bytes
LT.writeUint8(satellites); //+1 = 28 bytes
LT.writeUint16(voltage); //+2 = 30 bytes
LT.writeInt8(temperature); //+1 = 31 bytes total to send
len = LT.endWriteSXBuffer();
This is the matching code for the receiver;
LT.startReadSXBuffer(0); //start buffer read at location 0
LT.readBuffer(receivebuffer); //read in the character buffer
txcount = LT.readUint32(); //read in the TXCount
latitude = LT.readFloat(); //read in the latitude
longitude = LT.readFloat(); //read in the longitude
altitude = LT.readUint16(); //read in the altitude
satellites = LT.readUint8(); //read in the number of satellites
voltage = LT.readUint16(); //read in the voltage
temperature = LT.readInt8(); //read in the temperature
RXPacketL = LT.endReadSXBuffer();
Clearly as with other methods of sending data the order in which the packet data is created in the transmitter has to match the order that it is read in the receiver.
###Considerations for pin usage
Pins settings and usage must be set up the the 'Settings.h' file that is include in each sketch folder. Program **2\_Register\_Test** does not use a 'Settings.h' file however.
The library supports the SPI based LoRa modules and these all require that the SPI bus pins, SCK, MOSI and MISO are connected. All modules also need a NSS (chip select pin) and NRESET (reset) pin. In theory the NRESET pin could be omitted, but the programs would loose the ability to reset the device. All devices need the RFBUSY pin to be used also.
Of the DIO pins the library in standard form only uses DIO0 (SX127X) and DIO1 (SX126X and SX128X). The pin definitions for DIO1 and DIO2 (SX127x) and DIO2 and DIO3 (SX126x and SX128x) are not currently used by the library or examples so can be defined as -1 meaning they will not be configured.
The Dorji DRF1262 and DRF1268 modules has a SW pin which must be configured, it provides power to the antenna switch used on these modules.
Some SX126x modules may have RX or TX enable pins, these are currently not supported by the library.
Some of the SX128x modules do have RX or TX enable pins, such as the Ebyte modules, these are supported by the library, and you need to define the pins RX_EN and TX_EN pins used, otherwise leave unused by defining them as -1.
### Testing
For testing the library and the example programs I used a board of my own design, it uses a 3.3V/8Mhz Arduino Pro Mini which is soldered with a minimum amount of other components onto a board to which you can plug in a LoRa device as a Mikrobus style module. The board is small enough to be used for a GPS tracker application using the connections for a GPS and display as shown in the picture. The Pro Mini used includes a supply reverse protection diode and a fuse, so the board does not need these components. See the [**Easy Pro Mini**](https://github.com/StuartsProjects/Devices/tree/master/Easy%20Pro%20Mini) folder for details.
<br>
All example programs were checked against version 1.8.10 of the Arduino IDE, and the latest copies of any external libraries, as of 16/12/19. The operating system was Windows 10.
### Program examples
The Examples folder contains a number of practical working applications. There is an example for a very low sleep current sensor transmitter and matching receiver. There are examples for remote control of outputs and servos. There is a GPS tracker transmitter and receiver application. These applications utilise LoRa for the communications so even at low powers they can operate over several kilometres.
There are demonstrations on how to send data as a plain character array, as a structure and by writing variables direct to the LoRa devices internal buffer.
There are additional program examples for testing devices, antennas and long distance links.
The Settings.h file contains the settings for the LoRa device such as frequency, spreading factor, bandwidth and coding rate. The example programs use a frequency of 434.000Mhz or 2.445Ghz for the SX128x, you will need to check if that frequency is permitted in your part of the World. The radio frequency spectrum is not a free for all, which frequencies, transmitter powers and duty cycles you are permitted to use varies by region and country. By default CRC checking is added to transmitted packets and used to check for errors on reception.
The first program to test a layout and connections would be the Example program in the Basics folder **2\_Register_Test**, this just does a simple register print of the LoRa device. If this program does not work, then the rest of the example programs wont either. This program is self contained, it does not need the library installed to operate.
With an example program written and tested on this SX127x library the example should work with some minor changes with the SX126x and SX128x devices. Many of the example programs have already been tested and are working on SX126x, conversion typically takes less than a minute.
There are still some issues to attend to and changes to be made, see the section 'Changes Required to Library' at the bottom of this document.
# Library Functions
All of the library functions are public and can be accessed from users sketches.
The basic functions will be described in the order that example program **3\_LoRa\_Transmitter** uses them.
**SPI.begin()**
Standard Arduino library function. Sets up SPI. The library then internally uses;
**SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode))**
before every use of the SPI and this function after it;
**SPI.endTransaction()**
The parameters used are LTspeedMaximum, LTdataOrder and LTdataMode are defined in SX12XXLT_Definitions.h as;
LTspeedMaximum 8000000
LTdataOrder MSBFIRST
LTdataMode SPI_MODE0
The use of SPI.beginTransaction and SPI.endTransaction can be disabled by commenting out this define at the top of the relevant SX12XXLT.cpp file;
#define USE_SPI_TRANSACTION
**begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA\_DEVICE)** (SX127X library)
**begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, SW, LORA\_DEVICE)** (SX126X library)
**begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX\_EN, TX\_EN, LORA\_DEVICE)** (SX128X library)
The begin function initialises the hardware pins used by the device. The begin functions are slightly different for the SX127X, SX126X and SX128X libraries due to the different pins used. NSS, NRESET and DIO0 (SX127X) or DIO1 (SX126x and SX128X) are required, other DIOs are optional and when not used define as -1. The SX126X and SX128X devices have an RFBUSY pin. To ensure compatibility with Dorji SX1262 and SX1268 devices the SW pin needs to be defined. This pin turns on\off the antenna switch on Dorji devices. Set to -1 if not used. Some of the SX128X devices for example from eByte require TX and RX enable pins, set to -1 if your not using them.
The library examples for the SX128x do use the long form of the begin command (begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX\_EN, TX\_EN, LORA\_DEVICE) but if your device does not have TX and RX enable pins you can use the short form of the begin command;
**begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, LORA\_DEVICE)** (SX128X library)
**LoRA\_DEVICE** tells the library which actual LoRa RF IC is being used and in the case of the SX127x devices how the antenna is connected. The choices are for the SX127x part of the library are;
DEVICE_SX1272
DEVICE_SX1276
DEVICE_SX1277
DEVICE_SX1278
DEVICE_SX1279
DEVICE_SX1272_PABOOST
DEVICE_SX1277_PABOOST
DEVICE_SX1278_PABOOST
DEVICE_SX1279_PABOOST
DEVICE_SX1276_RFO
DEVICE_SX1277_RFO
DEVICE_SX1278_RFO
DEVICE_SX1279_RFO
Note that in the above list for the SXX127x part of the library only and there are new device types that allow the library to differentiate between devices that have the transmit output connected to the **PA\_BOOST** pin (which is the vast majority of SX127x devices) and those that use the **RFO LF\_ANT** or **RFO HF\_ANT** pins for RF output. These RFO connected devices are in the minority and are limited to 14dBm output. There is no library support for a SX1272 using the RFO outputs as I dont have one to test.
The old device types; DEVICE\_SX1272, DEVICE\_SX1276, DEVICE\_SX1277, DEVICE\_SX1278 and DEVICE\_SX1272 are retained for compatibility with old sketches and are the same device as those with the \_PABOOST identity.
Devices using the PABOOST output can be set to power levels from 2dBm to 20dBm, and operation at 20dBm is limited to a 1% duty cycle. Divices using the RFO outputs can be set to power levels from 0dBm to 14dBm.
The device types for the SX126X and SX128X part of the library are;
DEVICE_SX1261 //SX126X library
DEVICE_SX1262 //SX126X library
DEVICE_SX1268 //SX126X library
DEVICE_SX1280 //SX128X library
DEVICE_SX1281 //SX128X library
**setMode(MODE\_STDBY\_RC)**
Sets the operation mode of the LoRa device. Choices are;
MODE_SLEEP
MODE_STDBY
MODE_STDBY_RC
**setPacketType(PACKET\_TYPE\_LORA)**
Set the type of packet to use, currently only LORA is supported, choices are;
PACKET_TYPE_LORA
PACKET_TYPE_GFSK (not yet implemented)
PACKET_TYPE_FLRC (SX128X library only)
PACKET_TYPE_RANGING (SX128X library only)
PACKET_TYPE_BLE (SX128X library only) (not yet implemented)
PACKET_TYPE_NONE
**setRfFrequency(Frequency, Offset)**
Sets the operating frequency in hertz. A calibration offset also in hertz can be used if there is a calibration value known for a particular module.
**calibrateImage(0)**
Carries out an internal device calibration, normally carried out after setting the initial operating frequency.
**setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO)**
Sets the LoRa modem parameters for Spreading factor, Bandwidth, CodeRate and Optimisation. The options are;
//LoRa Spreading factors
LORA_SF5 (SX126X and SX128X libraries only)
LORA_SF6
LORA_SF7
LORA_SF8
LORA_SF9
LORA_SF10
LORA_SF11
LORA_SF12
//LoRa Bandwidths SX127X and SX126X libraries
LORA_BW_500 //actual 500000hz
LORA_BW_250 //actual 250000hz
LORA_BW_125 //actual 125000hz
LORA_BW_062 //actual 62500hz
LORA_BW_041 //actual 41670hz
LORA_BW_031 //actual 31250hz
LORA_BW_020 //actual 20830hz
LORA_BW_015 //actual 15630hz
LORA_BW_010 //actual 10420hz
LORA_BW_007 //actual 7810hz
//LoRa Bandwidths SX128X library
LORA_BW_0200 //actually 203125hz
LORA_BW_0400 //actually 406250hz
LORA_BW_0800 //actually 812500hz
LORA_BW_1600 //actually 1625000hz
//LoRa Coding rates
LORA_CR_4_5
LORA_CR_4_6
LORA_CR_4_7
LORA_CR_4_8
The SX126X and SX127X devices have an low data rate optimisation setting that needs to be set when the symbol time is greater than 16mS. You can manually turn it on or off or set it to LDRO\_AUTO and the library does the calculation for you.
//Low date rate optimisation, need to be set when symbol time > 16mS
LDRO_OFF
LDRO_ON
LDRO_AUTO //automatically calculated and set
**setBufferBaseAddress(0x00, 0x00)**
This sets the default address for the locations in the LoRa device buffer where transmitted and received packets start. The defaults of these locations are set in the transmit and receive functions, so this function is not normally required.
**setPacketParams(PreAmblelength, LORA\_PACKET\_VARIABLE\_LENGTH, PacketLength, LORA\_CRC\_ON, LORA\_IQ\_NORMAL)**
Set the packet parameters. PreAmblelength is normally 8. There is a choice of LORA\_PACKET\_VARIABLE\_LENGTH for variable length explicit packets or LORA\_PACKET\_FIXED\_LENGTH for implicit packets. PacketLength is 1 to 255, it can be set here but is normally handled within the transmitter and receiver functions. There is the option of using a packet CRC with LORA\_CRC\_ON or not using a CRC with LORA\_CRC\_OFF. IQ can be set to LORA\_IQ\_NORMAL or LORA\_IQ\_INVERTED.
**setSyncWord(LORA\_MAC\_PRIVATE\_SYNCWORD)**
You can define the syncword here, either a 8 bit value of your own choice or the standard values of LORA\_MAC\_PRIVATE\_SYNCWORD (0x12) or LORA\_MAC\_PUBLIC\_SYNCWORD (0x34). Take care with setting your own syncwords, some values may not be compatible with other LoRa devices or can give reduced sensitivity. There is no configurable syncword for SX128x devices.
**setHighSensitivity()**
Sets LoRa device for the highest sensitivity at expense of slightly higher LNA current. The alternative is setLowPowerReceive() for lower sensitivity with slightly reduced current.
**setDioIrqParams(MASK, DIO0\_MASK, DIO1\_MASK, DIO2\_MASK)** (SX127X library)
**setDioIrqParams(MASK, DIO0\_MASK, DIO1\_MASK, DIO2\_MASK)** (SX126X and SX128X libraries)
Sets up the how the device responds to internal events. This function is written for the SX127X to match the style used by the SX126X and SX128X devices. MASK is applied to the IRQ settings for DIO0, DIO1 and DIO2 (SX127X) and DIO1, DIO2 and DIO3 (SX126X and SX128X), its normally set to IRQ\_RADIO\_ALL (0xFFFF). Whilst the SX127X only has an 8 bit IRQ register the library has extended the function to provide additional IRQ detections that are used for the SX126X and SX127X.
In the case of the SX127X, the function maps the internal interrupts to the DIO0, DIO1 and DIO2 pins according to this table;
IRQ_RADIO_NONE 0x00
IRQ_CAD_ACTIVITY_DETECTED 0x01 //active on DIO1
IRQ_FSHS_CHANGE_CHANNEL 0x02 //active on DIO2
IRQ_CAD_DONE 0x04 //active on DIO0
IRQ_TX_DONE 0x08 //active on DIO0
IRQ_HEADER_VALID 0x10 //read from IRQ register only
IRQ_CRC_ERROR 0x20 //read from IRQ register only
IRQ_RX_DONE 0x40 //active on DIO0
IRQ_RADIO_ALL 0xFFFF
IRQ_TX_TIMEOUT 0x0100 //so that readIrqstatus can return additional detections
IRQ_RX_TIMEOUT 0x0200 //so that readIrqstatus can return additional detections
IRQ_NO_PACKET_CRC 0x0400 //so that readIrqstatus can return additional detections
The SX126X library has this table;
IRQ_RADIO_NONE 0x0000
IRQ_TX_DONE 0x0001
IRQ_RX_DONE 0x0002
IRQ_PREAMBLE_DETECTED 0x0004
IRQ_SYNCWORD_VALID 0x0008
IRQ_HEADER_VALID 0x0010
IRQ_HEADER_ERROR 0x0020
IRQ_CRC_ERROR 0x0040
IRQ_CAD_DONE 0x0080
IRQ_CAD_ACTIVITY_DETECTED 0x0100
IRQ_RX_TX_TIMEOUT 0x0200
IRQ_TX_TIMEOUT 0x0200
IRQ_RX_TIMEOUT 0x0200
IRQ_RADIO_ALL 0xFFFF
And the SX128X has this one;
IRQ_RADIO_NONE 0x0000
IRQ_TX_DONE 0x0001
IRQ_RX_DONE 0x0002
IRQ_SYNCWORD_VALID 0x0004
IRQ_SYNCWORD_ERROR 0x0008
IRQ_HEADER_VALID 0x0010
IRQ_HEADER_ERROR 0x0020
IRQ_CRC_ERROR 0x0040
IRQ_RANGING_SLAVE_RESPONSE_DONE 0x0080
IRQ_RANGING_SLAVE_REQUEST_DISCARDED 0x0100
IRQ_RANGING_MASTER_RESULT_VALID 0x0200
IRQ_RANGING_MASTER_RESULT_TIMEOUT 0x0400
IRQ_RANGING_SLAVE_REQUEST_VALID 0x0800
IRQ_CAD_DONE 0x1000
IRQ_CAD_ACTIVITY_DETECTED 0x2000
IRQ_RX_TX_TIMEOUT 0x4000
IRQ_TX_TIMEOUT 0x4000
IRQ_RX_TIMEOUT 0x4000
IRQ_PREAMBLE_DETECTED 0x8000
IRQ_RADIO_ALL 0xFFFF
**setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation)**
As an alternative to setting up the LoRa device with separate functions (as described above) you can use this function. The function first sets the Frequency of operation, the frequency is in hertz as a 32 bit unsigned integer. The actual programmed operating frequency is the sum of Frequency and Offset (also 32 bit integer).
SpreadingFactor, Bandwidth and CodeRate are the LoRa modem parameters and the choices are as given for the setModulationParams() described above.
When using setupLoRa() that library function then calls the following functions using these defaults;
setMode(MODE_STDBY_RC)
setPacketType(PACKET_TYPE_LORA);
setRfFrequency(Frequency, Offset);
calibrateImage(0);
setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO);
setBufferBaseAddress(0x00, 0x00);
setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);
setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);
LORA_MAC_PUBLIC_SYNCWORD = 0x34
setHighSensitivity();
setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0);
**printModemSettings()**
Prints the current modem settings to the serial monitor for diagnostic purposes. The parameters printed for lora are ; device\_type, frequency, spreading factor, bandwidth, coding\_rate, syncword, IQ\_Status, preamble\_length.
**printOperatingSettings()**
Prints the current operating settings to the serial monitor for diagnostic purposes. The settings printed are; device\_type, version\_number, packet\_mode, header\_mode, packet\_CRC\_on\_off, AGC\_auto\_on\_off, LNA\_gain, LNA\_boostHF, LNA\_boostLF.
**printRegisters(start, end)**
Print the device registers from start address to end address.
**printASCIIPacket(buff, length)**
Print as ASCII characters to the serial monitor the contents of the buffer name given, for the given length.
**transmit(buff, TXPacketL, timeout, TXpower, WAIT_TX)**
Transmit the contents of the buffer name given, for the given length. With a timeout in mS, with a TXpower in dBm and wait for the transmit to complete (a blocking command). To have the LoRa device start transmitting and continue as a no blocking command use NO_WAIT.
With **transmit** and WAIT\_TX the function returns the packet length if transmit detected no errors and 0 if errors were detected. If NO_WAIT is used you will need to check when pin DIO0 (SX127X) or DIO1 (SX126X and SX128X) goes high indicating transmission is completed.
**CRCCCITT(buff, TXPacketL, 0xFFFF)**
Calculates the 16 bit CRC of the buffer given for the length given. Specify the initialise value for the CRC, 0xFFFF in this case.
**readIrqStatus()**
Reads the value of the IRQ register flags.
## Receiving Packets
The **4\_LoRa\_Receiver** sketch is very similar, with the following differences;
**LT.receive(RXBUFFER, RXBUFFER\_SIZE, timeout, WAIT\_RX)**
Copy the received packet into the buffer address given with a maximum buffer size. If the RXBUFFER\_SIZE is smaller than the actual received packet then the packet will be truncated. If WAIT\_RX is selected then the program will wait for the time-out period (in mS) for a packet to arrive before signalling a timeout, this is a blocking command. To have the receiver wait continuously for a packet set the timeout to 0. To use the receiver in non-blocking mode set NO\_WAIT in which case you will need to check DIO0 (SX127X) or DIO1 (SX126X and SX128X) going high to indicate a packet has arrived.
**readPacketRSSI()**
Read the signal strength in dBm of the received packet.
**readPacketSNR()**
Read the signal to noise ratio in dB of the received packet. Typical values are +10dB for strong signals and -20dB for reception at the limit.
**printIrqStatus()**
Prints to the serial monitor the interrupt flags set.
<br>
## Packet Addressing
LoRa is a two way technology, each device is a transceiver. Most often on a particular frequency there will be one transmitter and one receiver. However, this may not always be the case and there could be several nodes in use on the same frequency.
In order to keep the software simple and allow for the receipt of signals from multiple receivers or directed commands to a particular node, a basic addressing scheme can be used and is implemented by some example programs, see '17_Sensor_Transmitter' for an example. There are library routines to send and receive packets in addressed and non-addressed format so you choose which to send. When using addressed mode regardless of the data content of the actual payload each packet sent has 3 control bytes at the beginning of the packet. In the case of the sensor example mentioned above, the use of the addressing allows the receiver to know from which sensor transmitter the packet came.
In general the control bytes have been restricted to ASCII printable characters so that they can be shown directly on a terminal monitor. The 3 bytes are;
**Packet type**. This either describes the content of the packet, which could be a GPS location payload or is a command to do something and there is no payload. Details of the packet types defined are in the library file 'ProgramLT_Definitions.h'
**Packet Destination**. The node number that the packet is destined for.
**Packet Source**. The node number that the packet was sent from.
The destination and source packet bytes mean that node 2 (could be your base station receiver) can send a command that only station 3 will respond to. This command could be a reset command, a request to turn on and off certain transmission types etc. Node 3 can be set-up so that it only accepts commands from a particular node.
In addressed mode the 3 control bytes are automatically stripped from each received packet.
An example of the 3 control bytes from a tracker would be;
T*2
Which means there is a test packet (T) its been sent as a broadcast (*) and its from node 2.
### Compatibility
**Fully tested on 3.3V 8Mhz ATMega328P and ATMega1284P only**.
It was not the intention to specifically support non-Atmel platforms with the library but several programs have been tested and work on an ESP32 WROOM board and an STM32 Xnucleo board. See the Readme for ESP32 and STM32 in the ESP32 and STM32 examples folders.
### Support
The examples do work, so if for you they do not, assume there is a problem with how you have wired the modules or that your modules are faulty or that your Arduino set-up or LoRa module is faulty or unsupported. You are best placed to diagnose these issues.
If you find a bug, or other error in the SX12xx library or examples, please let me know.
### Future Changes and Enhancements to Library
Add reliable packet send\receive code.
Add file transfer to and from SD card code.
<br>
### Stuart Robinson
### December 2020

View File

@@ -0,0 +1,20 @@
## Updates - 30/12/20
A number of updates have been applied to the SX127X part of the library, in part to cure some known issues and also to add additional functionality. A list of the changes made is below;
1. Correct a problem with LORA\_IQ\_INVERTED mode not working when configured.
2. Apply some of the SX1276\_77\_8\_ErrataNote\_1\_1 fixes. '2.1 Sensitivity Optimization with a 500 kHz Bandwidth'. Note that '2.3 Receiver Spurious Reception of a LoRa Signal' has not yet been implemented, although the code is present, further testing of this 'fix' is required.
3. Apply the revised RSSI and SNR value calculations to match the latest data sheet. The RSSI value was changed to be int16_t type since it can (now) go lower than -127dBm.
4. Remove the private variables _PacketRSSI and _PacketSNR, they are not needed since they can be recovered direct from a SX127x register.
5. Changes to the FSKRTTY transmit routines so that they automatically cope with transmission during a micros() roll-over.
6. Make changes to several of the example programs that use a GPS to be able to cope automatically with a millis() roll-over
7. Added support for SX127x devices that use the RFO\_LF or RFO\_HF ports for the transmit antenna. No support yet for an SX1272 using the RFO ports.
8. Added 'AFSKRTTY2.h' library file to be used as the standard AFSKRTTY library for upload of HAB payloads into a PC. This version uses micros() to toggle a pin for audio and has been tested on ATMega328, DUE and ESP32. The use of tone() would be preferred but some Arduino platforms don't support it.
9. Changed the GPS library programs 'UBLOXSerialGPS.h', 'UBLOXI2CGPS.h' and 'QuectelSerialGPS.h' so that they have compatible functions and that the same library file can be used for both softwareserial and hardware serial.
10. A function was added, doAFCPPM(); which adjusts the LoRa devices internal oscillator PPM offset.
11. Adjusted the calibrateImage(); function to operate correctly with fast processors.
12. Add function to read current RSSI.
13. Add an overloaded begin(int8\_t pinNSS, uint8\_t device); function for use with ESP32CAM.
14. Change Receive and Transmit functions to allow for millis() roll-over at 50days.
### Stuart Robinson

View File

@@ -0,0 +1,136 @@
## What is LoRa?
LoRa is a type of chirp spread spectrum transmission that has been implemented by Semtech for use in low cost Industrial Scientific and Medical (ISM) band radio devices. The SX127x devices became available in 2014\2015. LoRa is short for Long Range.
As a general guide a LoRa device will have up to 10 times (or maybe more) the range \distance of other typical radio modules, when using the same frequencies, data rates, antennas and transmit powers.
The first LoRa devices were for the UHF bands and modules for 169Mhz, 434Mhz, 868Mhz and 915Mhz are available to match the ISM band requirements of a particular global location.
LoRa devices are programmed over an SPI interface. The older SX127x range of devices are the ones in common use and are register centric, they are programmed by changing the contents of 128 seperate single byte registers. Newer LoRa devices such as SX126x (UHF) and SX128x (2.4Ghz) are programmed through a command interface, you send a command byte followed by a series of parameter bytes across the SPI bus.
LoRa devices are packet based, you load a first in first out (FIFO) buffer with bytes of data and tell the device to transmit that packet of data. The packets can be up to 256 bytes long and can have an integral cyclic redundancy check (CRC) automatically added. When a packet is received it is loaded into the FIFO from where the bytes of data can be read out.
There are now several software libraries that allow LoRa devices to be used with a range of Arduino devices. Note that a library specifically for the SX1276 and SX1278 devices will not correctly drive an SX1272.
#### Comparison to FSK devices
With frequency shift keying (FSK) style transmitters and receivers such as the Hope RFM22B or RFM69 for reception to work the receiver needs to see a signal that is strong enough to be above the local radio frequency (RF) noise level. Noise levels in the ISM bands are a performance limiter and each device in use adds to the local RF noise level. The total noise a receiver sees is a combination of local RF noise and noise generated by the electronics inside the receiver.
A typical FSK receiver needs to see a signal that is at least 5dB above the receiver's noise level in order to decode it. In comparison LoRa technology allows for signals to be received that are as much as 20dB below noise level, thus the LoRa signal could be up to 25dB (5dB + 20dB) weaker than the FSK one and still be received correctly. If LoRa can decode a signal that is 25dB weaker, then the transmitter can be further away than in the FSK example.
So due in the main to the below noise level performance, LoRa devices are able to receive signals that are very much weaker and thus much further away than with previous technology ISM band modules.
#### Configuring a LoRa module
LoRa modules are straight forward to drive and flexible, the internal firmware takes care of internal adjustments and optimisations, although there is an extra optimisation flag to set for long range slow to transmit packets.
The parameters that need to be configured for LoRa are, Spreading Factor, Coding Rate, Bandwidth, frequency and transmit power. These parameters can be easily changed so that you can set-up for low data rate long range or high data rate shorter range.
The LoRa device itself is a single surface mount integrated circuit, these are built onto small, typically 15mm x 15mm, modules that contain the crystal (or oscillator) and antenna matching components the modules need. Examples of LoRa modules are the Hope RFM98 and Dorji DRF1278F.
LoRa is a two way technology, the transmitter device is a receiver too, so if you can pick-up signals from your transmitter you can send it commands or exchange data with it also.
#### Bandwidth
The LoRa bandwidth is the amount of frequency spread the signal occupies. The bandwidths LoRa can be set to are;
7.8kHz, 10.4kHz, 15.6kHz, 20.8kHz, 31.25kHz, 41.7kHz, 62.5kHz, 125kHz, 250kHz, 500kHz.
A low bandwidth signal, such as 7.8kHz will give the best (longest distance) performance, but with the low cost components used in the Hope and Dorji LoRa modules a transmitter and receiver may not talk to each other at this bandwidth. The receiver has a frequency capture range, this is the percentage difference allowable in relation to the bandwidth that the transmitter and receiver can be apart in frequency in order for the receiver to pick up the transmitters signal. This percentage is typically 25% of the bandwidth.
Lets assume the bandwidth in use is 10kHz, the allowable variation is 25% or 2.5kHz and the transmitter is on 434.000Mhz. For the link to work the receiver needs to be on or between 433.9975Mhz and 434.0025Mhz. This is an exacting requirement for a low cost crystal, even if transmitter and receiver are at the same temperature.
Low bandwidths of 20.8kHz have been used for long range trackers and they do give better performance, but care is needed as devices used at this bandwidth may not talk to each other unless a frequency calibration factor is measured and applied. Once communication is established at low bandwidth a form of automatic frequency control can be used to adjust the receivers base frequency to keep it within the capture range.
A bandwidth of 62.5kHz has been found to be reliable and allows for differences in manufacturing tolerance and temperature between transmitter and receiver devices. Applications such as The Things Network (see later) use a bandwidth of 125kHz.
Newer LoRa devices such as the SX1262 are designed to use temperature compensated crystal oscillators (TCXO). The TCXO is very stable in frequency and can allow LoRa devices to be used at the lowest bandwidth (7.8kHz) even when there are significant temperature differences between transmitting and receiving LoRa devices.
#### Spreading factor
This controls the amount of signal processing gain. The spreading factor can be set between 6 and 12. A setting of 6 can only be used with fixed length packets, so is not often used in applications.
The spreading factor defines the below noise performance. SF6 gives a -7.5dB below noise performance and SF12 a -20dB below noise performance.
The larger spreading factors therefore give more range, as it allows the reception of weaker signals, the trade off is that higher spreading factor packets take longer to transmit.
#### Coding rate
Additional data can be added to the packet to allow for error correction. This can result in small signal gains at the limit of reception. The coding rate can be varied between 4:5 and 4:8, the higher 4:8 rate will result in longer packets.
#### How the LoRa settings affect range
Having established a practical LoRa bandwidth, say 62.5kHz, we can use this base to look at how the spreading factor affects range and the time to transmit a 20 byte payload.
The lower spreading factors will give the highest data rates and the shortest packets in time terms which in turn is more battery efficient. The lowest spreading factor we will consider is 7.
Assume we are using a bandwidth of 62.5kHz and a spreading factor of 7, that will give an equivalent data rate of 2734bps, according Semtech's 'LoRa Calculator' tool. The time taken to transmit our 20 bytes is 98mS. Assume that is our base and that in a typical urban area the limit of reception is 500m.
If we switch to spreading factor 12 then the data rate drops to 146bps and the transmit time goes up to 2.2 seconds so this is a slow packet. The benefit of the higher spreading factor is significant, we now have an approximate 14dB of extra signal gain. This is equivalent to 5 times further range, so our 500m now extends to 2.5km. The 'LoRa Calculator' tool provides the signal gain figures for different combinations of spreading factor and bandwidth.
5 times longer distance may not seem a lot, but appreciate how much difference it can make to the transmit power required to cover the extra distance. If we were transmitting at 10mW and that gave us the 500m range, to cover 5 times further range just by increasing transmit power would require a transmitter putting out 25 times the 10mW or 250mW.
#### Data rates
The fastest data rate a SX127x UHF LoRa device is capable of is 37500bps. The lowest data rate is 18bps, but the bandwidth at this rate, 7.8kHz, would be difficult to use.
Low data rate optimisation
When receiving a packet of data the receiver locks onto the packet preamble in order to synchronise the decoding of the following data. For the duration of packet reception only a small frequency variation in the transmitted signal is permitted. If the transmitter frequency drifts by more than circa 1.5% of the LoRa bandwidth in use, then there can be packet reception errors.
Unfortunately there will be a small amount of frequency drift during transmission caused by the LoRa device in the transmitter heating as the device dissipates the power used by the transmitter. The heating causes a slight drift in the frequency of the quartz crystal oscillator. The higher the transmit power the more the heating and the more the frequency drift. In long range mode, where packets may take a second or more to send, then there is a greater heating effect.
Similar problems could occur when the frequency difference between transmitter and receiver occurs due to Doppler shift which can happen in communications between fast moving vehicles for instance.
To work around these issues, for packets that are slow to transmit and which have a symbol time of 12mS or longer, an optimisation flag is set. If you were using a bandwidth of 62.5kHz the optimisation flag needs to be set at spreading factor 10 and above.
#### RSSI versus SNR
LoRa devices can provide both the received signal strength indication (RSSI) and signal to noise ratio (SNR) of a received packet. Whilst you might be tempted to use RSSI as an indication of the strength of the received signal, for weak signals, i.e. those approaching failure, RSSI is a poor indicator.
In practice the SNR reported is a far more useful indicator of impending link failure. If the SNR limit for
the spreading factor you are using is -10dB then a received packet reporting as SNR -4dB, is within 6dB of failure. Simple to do distance measurements can show that with 6dB (10-4) of signal link margin remaining, you can expect to receive a packet at approximately twice distance.
SNR Limits for Spreading factor.
SF7 -7.5dB
SF8 -10dB
SF9 -12.5dB
SF10 -15dB
SF11 -17.5dB
SF12 -20dB
#### Phantom Packets
It is an artefact of a LoRa receiver that data and packets can appear as if from nowhere, they come from within the device itself. The rate of phantom packets depends on the bandwidth in use by the receiver and can be at the rate of around 5 to 10 phantom packets per hour. Care is needed in software libraries to ensure that these phantoms are identified and rejected.
#### 2.4Ghz LoRa
More recently 2.4Ghz LoRa modules have been available, based on the SX128x. Whilst they don't have the extreme range of the UHF modules, they do allow for higher data rates, up to 200kbps and no duty cycle restrictions,.
The 2.4Ghz LoRa modules include a ranging function which allows a suitably configured pair of modules to measure the distance between them. The ranging works best in clear open areas and can be used to measure distances from circa 50m to beyond 40km. Recent endeavours by the author have shown that 2.4GHz LoRa can work at up to 89km LOS, and the ranging at 85km LOS.
#### How far does LoRa go?
LoRa devices are capable of extreme long range at low data rates. The current distance record for standard modules is 766km, a ground based receiver tracking a high altitude balloon. This distance was achieved using only basic omnidirectional antennas, at 868Mhz and only 25mW transmit power. See **[here](https://www.hackster.io/news/a-new-lorawan-distance-record-577c8bc11d7b)**. Its interesting to note that at 434MHz and the full device power of 100mW (when permitted!), the distance covered could be up to 4 times greater than the 766km.
At the time of writing, June 2019, there are small Earth orbiting satellite launches planned that will utilise LoRa, so perhaps the 766km will indeed be beaten.
#### LoRa and LoRaWAN are different
LoRa devices are used for simple point to point communications. LoRaWAN is an extra software based network communication layer added to basic LoRa that allows sensors or nodes to communicate with gateway devices in a structured manner. These gateways can forward data received from nodes across the Internet to applications and data collection services running on remote servers. Internet services such as Cayenne allow you to view data from sensors on-line.
The Things Network (TTN) is a community based free to use network of LoRaWAN gateways. If you want to have a sensor monitor temperatures, water levels, or track the location of assets, you can use the TTN to do this, assuming a gateway is within range.
There is a fair access policy for using TTN, your restricted to 30 seconds of transmit time per day and can send 10 messages per day to the node from the gateway. If your node is close to a gateway and your node is using spreading factor 7 then you could transmit up to 14,000 bytes of data per day. Its best to plan for worst case where your node is a long distance from the gateway and spreading factor 12 needs to be used, in this case you can send only 600 bytes per day. TTN is not for applications that require large amounts of data to be sent.
<br>
### Stuart Robinson
### December 2019

View File

@@ -0,0 +1,112 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 26/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program tests the deep sleep mode and wakeup with a switch of an Atmel 328P or
1284P processor. The program starts, flashes the LED and then puts the processor into permanent sleep.
It can be woken up with a switch press. Used as a base test routine for checking the sleep current of
a board.
Tested on a 'bare bones' ATmega328P board, the current in sleep mode was 1.7uA with a 3.3V MCP1700
regulator being used.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <avr/sleep.h>
#define LED1 8 //on board LED, high for on
#define SWITCH1 2 //switch used to wake processor up, switch pin connected to
//ground to activate. Define as -1 if switch not used.
uint32_t sleeps;
void loop()
{
digitalWrite(LED1, HIGH);
delay(2000);
sleeps++;
Serial.print(sleeps);
Serial.println(F(" Sleeping zzzzz...."));
Serial.println();
Serial.flush(); //make sure serial out buffer is empty
digitalWrite(LED1, LOW);
attachInterrupt(digitalPinToInterrupt(SWITCH1), wakeUp, FALLING); //This is a hardware interrupt
sleep_permanent(); //goto sleep till woken up by switch press
detachInterrupt(digitalPinToInterrupt(SWITCH1));
Serial.println(F("Awake !"));
digitalWrite(LED1, HIGH);
}
void sleep_permanent()
{
ADCSRA = 0; //disable ADC
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
//turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE); //turn on brown-out enable select
MCUCR = bit (BODS); //this must be done within 4 clock cycles of above
interrupts (); //guarantees next instruction executed
sleep_cpu (); //sleep within 3 clock cycles of above
/* wake up here */
sleep_disable();
}
void wakeUp()
{
//handler for the interrupt
}
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(SWITCH1, INPUT_PULLUP); //setup switch pin, ground to activate
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
pinMode(SWITCH1, INPUT_PULLUP); //setup switch pin, connect to ground to activate
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("12_ATmel_Sleep_with_Switch_Wakeup Starting"));
}

View File

@@ -0,0 +1,46 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 24/12/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 program to test a GPS. It reads characters from the GPS using
software serial and sends them (echoes) to the IDE serial monitor. If your ever having problems with
a GPS (or just think you are) use this program first.
If you get no data displayed on the serial monitor, the most likely cause is that you have the receive
data pin into the Arduino (RX) pin connected incorrectly.
GPS baud rate set at 9600 baud, Serial monitor set at 115200 baud. If the data displayed on the serial
terminal appears to be random text with odd symbols its very likely you have the GPS serial baud rate
set incorrectly for the GPS.
Note that not all pins on all Arduinos will work with software serial, see here;
https://www.arduino.cc/en/Reference/softwareSerial
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define RXpin A3 //this is the pin that the Arduino will use to receive data from the GPS
#define TXpin A2 //this is the pin that the Arduino can use to send data (commands) to the GPS - not used
#include <SoftwareSerial.h>
SoftwareSerial GPS(RXpin, TXpin);
void loop()
{
while (GPS.available())
{
Serial.write(GPS.read());
}
}
void setup()
{
GPS.begin(9600);
Serial.begin(115200);
Serial.println("GPS_Echo Starting");
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 14/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a simple program to test a GPS. It reads characters from the GPS using
a hardware serial port, set to Serial1 as default, and then sends them (echoes) to the Arduino IDE
serial monitor. If your ever having problems with a GPS (or just think you are) use this program first.
If you get no data displayed on the serial monitor, the most likely cause is that you have the receive
data pin into the Arduino (RX) pin connected incorrectly.
At program start you should see '26A_GPS_Echo_Hardware_Serial Starting' in the serial monitor, if you
dont the serial monitor baud rate is probably incorrectly set. If you then see data displayed on the
serial terminal which appears to be random text with odd symbols its very likely you have the GPS
serial baud rate set incorrectly.
Change 'Serial1' in the program to match the hardware serial port you are using, for an Arduino Mega
this would normally be Serial1, Serila2 or Serial3.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
void loop()
{
while (Serial3.available())
{
Serial.write(Serial3.read());
}
}
void setup()
{
Serial3.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.println("26B_GPS_Echo_Hardware_Serial Starting");
}

View File

@@ -0,0 +1,45 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 14/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a simple program to test a UBLOX GPS. It reads characters from the GPS using
the I2C interface and sends them (echoes) to the IDE serial monitor. If your ever having problems with a
GPS (or just think you are) use this program first.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <Wire.h>
const uint16_t GPSI2CAddress = 0x42;
void loop()
{
uint8_t GPSByte;
do
{
Wire.requestFrom(GPSI2CAddress, 1);
GPSByte = Wire.read();
if (GPSByte != 0xFF)
{
Serial.write(GPSByte);
}
}
while (true);
}
void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.println();
Serial.println("26C_GPS_Echo_UBLOXI2C Starting");
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 14/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a simple program to test a GPS. It reads characters from the GPS using
software serial and sends them (echoes) to the IDE serial monitor. If your ever having problems with
a GPS (or just think you are) use this program first.
If you get no data displayed on the serial monitor, the most likely cause is that you have the receive
data pin into the Arduino (RX) pin connected incorrectly.
If the data displayed on the serial terminal appears to be random text with odd symbols its very
likely you have the GPS serial baud rate set incorrectly.
Note that not all pins on all Arduinos will work with software serial, see here;
https://www.arduino.cc/en/Reference/softwareSerial
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define RXpin A3 //this is the pin that the Arduino will use to receive data from the GPS
#define TXpin A2 //this is the pin that the Arduino can use to send data (commands) to the GPS - not used
#include <SoftwareSerial.h>
SoftwareSerial GPS(RXpin, TXpin);
void loop()
{
while (GPS.available())
{
Serial.write(GPS.read());
}
}
void setup()
{
GPS.begin(9600);
Serial.begin(115200);
Serial.println("26_GPS_Echo Starting");
}

View File

@@ -0,0 +1,272 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 24/12/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 a portable GPS checker. It reads the GPS for 5 seconds and copies
the characters from the GPS to the serial monitor, this is an example printout from a working GPS that
has just been powered on;
28_GPS_Checker Starting
Wait GPS Fix 5 seconds
Timeout - No GPS Fix 5s
Wait GPS Fix 5 seconds
$PGACK,103*40
$PGACK,105*46
$PMTK011,MTKGPS*08
$PMTK010,001*2E
$PMTK010,00æ*2D
$GPGGA,235942.800,,,,,0,0,,,M,,M,,*4B
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,235942.800,V,,,,,0.00,0.00,050180,,,N*42
$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32
$GPGSV,1,1,03,30,,,43,07,,,43,05,,,38*70
Timeout - No GPS Fix 5s
Wait GPS Fix 5 seconds
That printout is from a Meadiatek GPS, the Ublox ones are similar. The data from the GPS is also fed into
the TinyGPS++ library and if there is no fix a message is printed on the serial monitor.
When the program detects that the GPS has a fix, it prints the Latitude, Longitude, Altitude, Number
of satellites in use, the HDOP value, time and date 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; '#define GPSPOWER -1' from -1 to the pin number
being used. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic levels.
There is a set of GPS co-ordinates defined, TestLatitude and TestLongitude, when the GPS has its location
fix the distance and direction to the Test location is calculated and shown on the serial monitor.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define Program_Version "V1.2"
#define authorname "Stuart Robinson"
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define RXpin A3 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin A2 //pin number for GPS TX output from Arduino- RX into GPS
#define LED1 8 //pin number for LED, turns on when printing Fix data
#define GPSPOWER -1 //Pin that controls power to GPS, set to -1 if not used
#define GPSONSTATE HIGH //logic level to turn GPS on via pin GPSPOWER
#define GPSOFFSTATE LOW //logic level to turn GPS off via pin GPSPOWER
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);
float GPSLat; //Latitude from GPS
float GPSLon; //Longitude from GPS
float GPSAlt; //Altitude from GPS
uint8_t GPSSats; //number of GPS satellites in use
uint32_t GPSHdop; //HDOP from GPS
uint8_t hours, mins, secs, day, month;
uint16_t year;
uint32_t startGetFixmS;
uint32_t endFixmS;
//GPS co-ordinates to use for the test location transmission
const float TestLatitude = 51.48230; //Cardiff castle keep, used for location testing purposes
const float TestLongitude = -3.18136;
void loop()
{
if (gpsWaitFix(5))
{
digitalWrite(LED1, HIGH); //LED on to indicate fix
Serial.println();
Serial.println();
Serial.print(F("Fix time "));
Serial.print(endFixmS - startGetFixmS);
Serial.println(F("mS"));
GPSLat = gps.location.lat();
GPSLon = gps.location.lng();
GPSAlt = gps.altitude.meters();
GPSSats = gps.satellites.value();
GPSHdop = 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();
printGPSfix();
startGetFixmS = millis(); //have a fix, next thing that happens is checking for a fix, so restart timer
digitalWrite(LED1, LOW);
}
else
{
Serial.println();
Serial.println();
Serial.print(F("Timeout - No GPS Fix "));
Serial.print( (millis() - startGetFixmS) / 1000 );
Serial.println(F("s"));
}
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for updated fix
uint32_t startmS, waitmS;
uint8_t GPSchar;
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.println(F(" seconds"));
waitmS = waitSecs * 1000; //convert seconds wait into mS
startmS = millis();
while ( (uint32_t) (millis() - startmS) < waitmS) //allows for millis() overflow
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
Serial.write(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated())
{
endFixmS = millis(); //record the time when we got a GPS fix
return true;
}
}
return false;
}
void printGPSfix()
{
float tempfloat;
uint32_t distance;
uint16_t direction;
Serial.print(F("New GPS Fix "));
tempfloat = ( (float) GPSHdop / 100);
Serial.print(F("Lat,"));
Serial.print(GPSLat, 6);
Serial.print(F(",Lon,"));
Serial.print(GPSLon, 6);
Serial.print(F(",Alt,"));
Serial.print(GPSAlt, 1);
Serial.print(F("m,Sats,"));
Serial.print(GPSSats);
Serial.print(F(",HDOP,"));
Serial.print(tempfloat, 2);
Serial.print(F(",Time,"));
if (hours < 10)
{
Serial.print(F("0"));
}
Serial.print(hours);
Serial.print(F(":"));
if (mins < 10)
{
Serial.print(F("0"));
}
Serial.print(mins);
Serial.print(F(":"));
if (secs < 10)
{
Serial.print(F("0"));
}
Serial.print(secs);
Serial.print(F(",Date,"));
Serial.print(day);
Serial.print(F("/"));
Serial.print(month);
Serial.print(F("/"));
Serial.print(year);
distance = gps.distanceBetween(GPSLat, GPSLon, TestLatitude, TestLongitude);
direction = gps.courseTo(GPSLat, GPSLon, TestLatitude, TestLongitude);
Serial.println();
Serial.print(F("Distance to Test Location ("));
Serial.print(TestLatitude, 6);
Serial.print((","));
Serial.print(TestLongitude, 6);
Serial.print((") "));
Serial.print(distance);
Serial.print(("m"));
Serial.println();
Serial.print(F("Direction to Test Location ("));
Serial.print(TestLatitude, 6);
Serial.print((","));
Serial.print(TestLongitude, 6);
Serial.print((") "));
Serial.print(direction);
Serial.print(("d"));
Serial.println();
Serial.println();
}
void GPSON()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
}
}
void GPSOFF()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
}
}
void setup()
{
pinMode(LED1, OUTPUT);
if (GPSPOWER >= 0)
{
pinMode(GPSPOWER, OUTPUT);
GPSON();
}
GPSserial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("28_GPS_Checker Starting"));
Serial.println();
startGetFixmS = millis();
}

View File

@@ -0,0 +1,335 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 29/12/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 a portable GPS checker with display option. It uses an SSD1306 or
SH1106 128x64 I2C OLED display. The program reads the GPS for 5 seconds checking for a fix and copies
the characters from the GPS to the serial monitor so you can see if the GPS is working. This is an example
printout from a working GPS with the program having been just been powered on;
29_GPS_Checker_Display Starting
Wait GPS Fix 5 seconds
$GPGGA,235945.020,,,,,0,0,,,M,,M,,*46
$GPGLL,,,,,235945.020,V,N*74
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,1,1,01,11,,,33*78
$GPRMC,235945.020,V,,,,,0.00,0.00,050180,,,N*4F
$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32
$GPGGA,235946.020,,,,,0,0,,,M,,M,,*45
$GPGLL,,,,,235946.020,V,N*77
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,1,1,02,22,,,36,11,,,33*7E
$GPRMC,235946.020,V,,,,,0.00,0.00,050180,,,N*4C
Timeout - No GPS Fix 5s
Wait GPS Fix 5 seconds
That printout is from a Meadiatek GPS, the Ublox ones are similar. The data from the GPS is also fed into
the TinyGPS++ library and if there is no fix a message is printed on the serial monitor.
When the program detects that the GPS has a fix, it prints the Latitude, Longitude, Altitude, Speed, Number
of satellites in use, the HDOP value, time and date to the serial monitor. If the I2C OLED display is
attached that is updated as well. Display is assumed to be on I2C address 0x3C.
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; '#define GPSPOWER -1' from -1 to the pin number
being used. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic levels.
Serial monitor baud rate is set at 115200.
Changes:
290920 - Add speed to serial monitor output and display
*******************************************************************************************************/
#define Program_Version "V1.2"
#define authorname "Stuart Robinson"
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define RXpin A3 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin A2 //pin number for GPS TX output from Arduino- RX into GPS
#define GPSPOWER -1 //Pin that controls power to GPS, set to -1 if not used
#define GPSONSTATE HIGH //logic level to turn GPS on via pin GPSPOWER
#define GPSOFFSTATE LOW //logic level to turn GPS off via pin GPSPOWER
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);
#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
#define DEFAULTFONT u8x8_font_chroma48medium8_r //font used by U8X8 Library
float GPSLat; //Latitude from GPS
float GPSLon; //Longitude from GPS
float GPSAlt; //Altitude from GPS
uint8_t GPSSats; //number of GPS satellites in use
uint32_t GPSHdop; //HDOP from GPS
float GPSSpeed; //Speed of GPS, mph
uint8_t hours, mins, secs, day, month;
uint16_t year;
uint32_t startGetFixmS;
uint32_t endFixmS;
void loop()
{
if (gpsWaitFix(5))
{
Serial.println();
Serial.println();
Serial.print(F("Fix time "));
Serial.print(endFixmS - startGetFixmS);
Serial.println(F("mS"));
GPSLat = gps.location.lat();
GPSLon = gps.location.lng();
GPSAlt = gps.altitude.meters();
GPSSats = gps.satellites.value();
GPSHdop = gps.hdop.value();
GPSSpeed = gps.speed.mph();
hours = gps.time.hour();
mins = gps.time.minute();
secs = gps.time.second();
day = gps.date.day();
month = gps.date.month();
year = gps.date.year();
printGPSfix(); //print GPS data to serial monitor
displayscreen1(); //print GPS data on display
startGetFixmS = millis(); //have a fix, next thing that happens is checking for a fix, so restart timer
}
else
{
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("No GPS Fix "));
disp.print( (millis() - startGetFixmS) / 1000 );
Serial.println();
Serial.println();
Serial.print(F("Timeout - No GPS Fix "));
Serial.print( (millis() - startGetFixmS) / 1000 );
Serial.println(F("s"));
}
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for updated fix
uint32_t startmS, waitmS;
uint8_t GPSchar;
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.println(F(" seconds"));
//Serial.print(F("Current millis() "));
//Serial.println(millis());
waitmS = waitSecs * 1000; //convert seconds wait into mS
startmS = millis();
while ( (uint32_t) (millis() - startmS) < waitmS) //allows for millis() overflow
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
Serial.write(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated())
{
endFixmS = millis(); //record the time when we got a GPS fix
return true;
}
}
return false;
}
void printGPSfix()
{
float tempfloat;
Serial.print(F("New GPS Fix "));
tempfloat = ( (float) GPSHdop / 100);
Serial.print(F("Latitude,"));
Serial.print(GPSLat, 6);
Serial.print(F(",Longitude,"));
Serial.print(GPSLon, 6);
Serial.print(F(",Altitude,"));
Serial.print(GPSAlt, 1);
Serial.print(F("m,Speed,"));
Serial.print(GPSSpeed, 1);
Serial.print(F("mph,Sats,"));
Serial.print(GPSSats);
Serial.print(F(",HDOP,"));
Serial.print(tempfloat, 2);
Serial.print(F(",Time,"));
if (hours < 10)
{
Serial.print(F("0"));
}
Serial.print(hours);
Serial.print(F(":"));
if (mins < 10)
{
Serial.print(F("0"));
}
Serial.print(mins);
Serial.print(F(":"));
if (secs < 10)
{
Serial.print(F("0"));
}
Serial.print(secs);
Serial.print(F(",Date,"));
Serial.print(day);
Serial.print(F("/"));
Serial.print(month);
Serial.print(F("/"));
Serial.print(year);
Serial.println();
Serial.println();
}
void displayscreen1()
{
//show GPS data on display
float tempfloat;
tempfloat = ( (float) GPSHdop / 100);
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(GPSLat, 6);
disp.clearLine(1);
disp.setCursor(0, 1);
disp.print(GPSLon, 6);
disp.clearLine(2);
disp.setCursor(0, 2);
disp.print(GPSAlt,0);
disp.print(F("m"));
disp.clearLine(3);
disp.setCursor(0, 3);
disp.print(GPSSpeed,0);
disp.print(F("mph"));
disp.clearLine(4);
disp.setCursor(0, 4);
disp.print(F("Sats "));
disp.print(GPSSats);
disp.clearLine(5);
disp.setCursor(0, 5);
disp.print(F("HDOP "));
disp.print(tempfloat);
disp.clearLine(6);
disp.setCursor(0, 6);
if (hours < 10)
{
disp.print(F("0"));
}
disp.print(hours);
disp.print(F(":"));
if (mins < 10)
{
disp.print(F("0"));
}
disp.print(mins);
disp.print(F(":"));
if (secs < 10)
{
disp.print(F("0"));
}
disp.print(secs);
disp.print(F(" "));
disp.clearLine(7);
disp.setCursor(0, 7);
disp.print(day);
disp.print(F("/"));
disp.print(month);
disp.print(F("/"));
disp.print(year);
}
void GPSON()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
}
}
void GPSOFF()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
}
}
void setup()
{
if (GPSPOWER >= 0)
{
pinMode(GPSPOWER, OUTPUT);
GPSON();
}
GPSserial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
disp.begin();
disp.setFont(DEFAULTFONT);
disp.clear();
disp.setCursor(0, 0);
disp.print(F("Display Ready"));
Serial.println(F("29_GPS_Checker_With_Display Starting"));
Serial.println();
startGetFixmS = millis();
}

View File

@@ -0,0 +1,69 @@
// --------------------------------------
// i2c_scanner
// from: https://playground.arduino.cc/Main/I2cScanner/
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
#include <Wire.h>
uint16_t counter;
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println(F("I2C Scanner starting"));
Serial.println();
}
void loop()
{
uint8_t error, address;
int16_t nDevices;
counter++;
Serial.print(counter);
Serial.println(F(" Scanning..."));
nDevices = 0;
for (address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(F("I2C device found at address 0x"));
if (address < 16)
Serial.print(F("0"));
Serial.println(address, HEX);
nDevices++;
}
else if (error == 4)
{
Serial.print(F("Unknown error at address 0x"));
if (address < 16)
Serial.print(F("0"));
Serial.println(address, HEX);
}
}
if (nDevices == 0)
{
Serial.println(F("No I2C devices found"));
}
else
{
Serial.println();
Serial.println(F("Done"));
Serial.println();
}
delay(5000); // wait 5 seconds for next scan
}

View File

@@ -0,0 +1,122 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program is a simple test program for the SSD1306 and SH1106 OLEDs running on
a 3.3V 8Mhz bare bones ATmega328P. The program prints a short message on each line, pauses, clears the
screen, turns off the screem, puts the processor to sleep and starts again. Sleep current with display
off is circa 8uA.
OLED address defaults to 0x3C.
Screen write on 8Mhz Atmel 196mS.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <avr/sleep.h>
#include <avr/wdt.h>
#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
#define DEFAULTFONT u8x8_font_chroma48medium8_r //font for U8X8 Library
uint16_t writecount;
uint32_t startwritemS, endwritemS, timemS;
void loop()
{
writecount++;
Serial.print(writecount);
Serial.print(F(" Writing to display"));
startwritemS = millis();
disp.clear();
screen1();
endwritemS = millis();
timemS = endwritemS - startwritemS;
disp.setCursor(8, 4);
disp.print(timemS);
disp.print(F("mS"));
Serial.print(F(" - done "));
Serial.print(timemS);
Serial.println(F("mS"));
delay(2000);
Serial.println(F("PowerSave display"));
Serial.flush(); //pending serial output affects sleep mode
disp.setPowerSave(1); //power save display, turns off, sleep current circa 8uA
sleep1seconds(2); //sleep in units of 1 second
disp.setPowerSave(0); //display back to normal
}
void sleep1seconds(uint32_t sleeps)
{
uint32_t index;
for (index = 1; index <= sleeps; index++)
{
ADCSRA = 0; //disable ADC
MCUSR = 0; //clear various "reset" flags
WDTCSR = bit (WDCE) | bit (WDE); //allow changes, disable reset
WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1); //set interrupt mode and an interval, set WDIE, and 1 seconds sleep
wdt_reset(); //pat the dog
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
MCUCR = bit (BODS) | bit (BODSE); //turn off brown-out enable in software
MCUCR = bit (BODS);
interrupts (); //guarantees next instruction executed
sleep_cpu ();
//awake here
sleep_disable(); //cancel sleep as a precaution
}
}
ISR (WDT_vect)
{
//watchdog interrupt
wdt_disable(); // disable watchdog
}
void screen1()
{
disp.setCursor(0, 0);
disp.print(F("Hello World !"));
disp.setCursor(0, 1);
disp.print(F("Line 1"));
disp.setCursor(0, 2);
disp.print(F("Line 2"));
disp.setCursor(0, 3);
disp.print(F("Line 3"));
disp.setCursor(0, 4);
disp.print(F("Line 4"));
disp.setCursor(0, 5);
disp.print(F("Line 5"));
disp.setCursor(0, 6);
disp.print(F("Line 6"));
disp.setCursor(0, 7);
disp.print(F("0123456789012345")); //display is 8 lines x 16 charaters when using the
}
void setup()
{
Serial.begin(9600);
Serial.println(F("31_SSD1306_SH1106_OLED_Checker starting"));
disp.begin();
disp.setFont(DEFAULTFONT);
}

View File

@@ -0,0 +1,153 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/04/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 GPS Time checker. It reads the GPS NMEA output and displays the time
on the Arduino IDE serial monitor. If you have the serial monitor output on screen as the same time as
observing a web site displaying the current time you can check how close your GPS is reporting to real time.
At power up a GPS will not normally display the time accurate to the exact second until it receives the
navigation message that is the updated value of current leaps seconds which is sent out every 12.5 minutes.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define Program_Version "V1.0"
#define authorname "Stuart Robinson"
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define RXpin A3 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin A2 //pin number for GPS TX output from Arduino- RX into GPS
#define GPSPOWER -1 //Pin that controls power to GPS, set to -1 if not used
#define GPSONSTATE HIGH //logic level to turn GPS on via pin GPSPOWER
#define GPSOFFSTATE LOW //logic level to turn GPS off via pin GPSPOWER
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);
uint8_t hours, mins, secs;
void loop()
{
if (gpsWaitFix(5))
{
hours = gps.time.hour();
mins = gps.time.minute();
secs = gps.time.second();
printGPSfix();
}
else
{
Serial.println(F("Timeout - No GPS Fix "));
}
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for updated fix
uint32_t endwaitmS;
uint8_t GPSchar;
endwaitmS = millis() + (waitSecs * 1000);
while (millis() < endwaitmS)
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
//Serial.write(GPSchar);
}
if (gps.location.isUpdated() && gps.time.isUpdated())
{
return true;
}
}
return false;
}
void printGPSfix()
{
Serial.print(F("Time,"));
if (hours < 10)
{
Serial.print(F("0"));
}
Serial.print(hours);
Serial.print(F(":"));
if (mins < 10)
{
Serial.print(F("0"));
}
Serial.print(mins);
Serial.print(F(":"));
if (secs < 10)
{
Serial.print(F("0"));
}
Serial.print(secs);
Serial.println();
}
void GPSON()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
}
}
void GPSOFF()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
}
}
void setup()
{
if (GPSPOWER >= 0)
{
pinMode(GPSPOWER, OUTPUT);
GPSON();
}
GPSserial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("32_GPS_Checker_Time Starting"));
Serial.println();
}

View File

@@ -0,0 +1,109 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 03/09/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 of an Atmel ATMega328P processor.
At power up the flashes an LED 4 times, then turns on the LED for 5 seconds. Then the processor is put
to sleep for 16 seconds. On wakeup the LED flashes twice, then is on for 2 seconds and the board goes to
sleep again. And the sequence repeats.
Sleep current for a 'bare bones' ATmega328 with a MCP1700 regulator @ 3.3V and using an external event
such as a switch to wakeup from sleep should be around 2uA. Using the watchdog timer to wakeup raises
the deep sleep current to circa 6.2uA.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
//basic code from here - https://www.gammon.com.au/forum/?id=11497
#include <avr/sleep.h>
#include <avr/wdt.h>
#define LED1 8
void loop ()
{
Serial.println("LED Off");
digitalWrite(LED1, LOW);
digitalWrite(13, LOW);
Serial.println(F("Now Sleeping... "));
Serial.flush();
sleep8seconds(2); //sleep for about 16 seconds
Serial.println("Awake ");
led_Flash(2, 125);
Serial.println("LED On ");
digitalWrite(LED1, HIGH);
digitalWrite(13, HIGH);
delay(2000);
}
void sleep8seconds(uint32_t sleeps)
{
uint32_t index;
for (index = 1; index <= sleeps; index++)
{
ADCSRA = 0; //disable ADC
MCUSR = 0; //clear various "reset" flags
WDTCSR = bit (WDCE) | bit (WDE); //allow changes, disable reset
WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); //set interrupt mode and an interval, set WDIE, and 8 seconds delay
wdt_reset(); //pat the dog
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
MCUCR = bit (BODS) | bit (BODSE); //turn off brown-out enable in software
MCUCR = bit (BODS);
interrupts (); //guarantees next instruction executed
sleep_cpu ();
//awake here
sleep_disable(); //cancel sleep as a precaution
}
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
digitalWrite(13, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
digitalWrite(13, LOW);
delay(delaymS);
}
}
void setup ()
{
pinMode(LED1, OUTPUT);
pinMode(13, OUTPUT);
Serial.begin(9600);
led_Flash(4, 125);
Serial.println("LED On ");
digitalWrite(LED1, HIGH);
digitalWrite(13, HIGH);
delay(5000);
}
ISR (WDT_vect)
{
//watchdog interrupt
wdt_disable(); // disable watchdog
}

View File

@@ -0,0 +1,78 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program sweeps two servos from one end of their travel to the other. Useful to
check servos are connected correctly and working.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define pinservoX1 2 //pin for controlling servo X 1
#define pinservoY1 4 //pin for controlling servo Y 1
#define LED1 8
#include <Servo.h>
Servo ServoX1; //create the servo object
Servo ServoY1; //create the servo object
void loop()
{
uint16_t index;
for (index = 900; index <= 2100; index++)
{
//Serial.print(F("Microseconds1 "));
//Serial.println(index);
ServoX1.writeMicroseconds(index);
ServoY1.writeMicroseconds(index);
}
delay(1000);
for (index = 2100; index >= 900; index--)
{
//Serial.print(F("Microseconds1 "));
//Serial.println(index);
ServoX1.writeMicroseconds(index);
ServoY1.writeMicroseconds(index);
}
delay(1000);
}
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);
led_Flash(2, 125);
Serial.begin(9600);
ServoX1.attach(pinservoX1); //using pin servoX for servo object
ServoY1.attach(pinservoY1); //using pin servoX for servo object
Serial.println(F("Servo sweep test starting"));
}

View File

@@ -0,0 +1,267 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 04/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 test program has been written to check that a connected SD card adapter, Micro
or standard, is functional.
When the program runs it will attempts to create a file that is next in sequence to Log0000.txt, thus
if this is the first time the program has run on the SD card it will create file Log0001.txt. If the
file Log0001.txt exists it will create Log0002.txt etc. This ensures that everytime the program starts
it creates a new file for testing.
Next the program checks if the Logxxxx.txt file exists and if so attempts to delete it.
Then the program starts a loop. First the same file is again opened for append, it will be created if it
does not exist and then the line '1 Hello World' is writtent to the file. The file is closed and the
contents of the file are dumped to the serial monitor. The loop restarts, and this time the line
'2 Hello World' is appended to the file.
As the program progresses the file will grow in size and after 4 iterrations of the open,write,close
and dump loop the file dump on serial monitor will look like this
1 Hello World
2 Hello World
3 Hello World
4 Hello World
This file dump will grow if you let the program run. If an error with the SD card is detected at any
time the LED will rapid flash continuously and the message 'X Card failed, or not present' is printed
to serial monitor. The number X will allow you to check the program listing for where the error occured.
1 Card failed = SD card did not initialise
2 Card failed = Could nt setup logFile for new name
3 Card failed = Could not open file for append
4 Card failed = Failure to dump file to serial monitor
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SD.h>
#include <SPI.h>
#define LED1 8 //pin number for LED
#define SDCS 4 //pin number for device select on SD card module
File logFile;
char filename[] = "/LOG0000.TXT"; //filename used as base for creating logfile, 0000 replaced with numbers
uint16_t linecount;
void loop()
{
Serial.println();
Serial.println("Initializing SD card");
if (!SD.begin(SDCS))
{
cardFail(1);
}
Serial.println("Card initialized");
logFile = SD.open("/");
Serial.println("Card directory");
Serial.println();
printDirectory(logFile, 0);
Serial.println();
Serial.println();
if (!setupSDLOG(filename)) //setup logfile name for writing
{
cardFail(2);
}
Serial.print(F("logFile name is "));
Serial.println(filename);
if (SD.exists(filename))
{
Serial.print(filename);
Serial.println(" exists - delete");
SD.remove(filename);
}
if (!SD.exists(filename))
{
Serial.print(filename);
Serial.println(" does not exist");
}
while (1)
{
logFile = SD.open(filename, FILE_WRITE);
if (!logFile)
{
cardFail(3);
}
linecount++;
logFile.print(linecount);
logFile.println(" Hello World");
logFile.close();
Serial.println();
Serial.print("Dump file ");
Serial.println(filename);
Serial.println();
digitalWrite(LED1, HIGH);
if (dumpFile(filename))
{
Serial.println();
Serial.println("Finished File Dump");
}
else
{
cardFail(4);
}
digitalWrite(LED1, LOW);
delay(2000);
}
}
void printDirectory(File dir, int numTabs)
{
while (true)
{
File entry = dir.openNextFile();
if (! entry)
{
//no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory())
{
Serial.println("/");
printDirectory(entry, numTabs + 1);
}
else
{
//files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
bool dumpFile(char *buf)
{
if (SD.exists(buf))
{
Serial.print(buf);
Serial.println(" found");
}
else
{
Serial.print(filename);
Serial.println(" not found");
return false;
}
logFile = SD.open(buf);
if (logFile) //if the file is available, read from it
{
while (logFile.available())
{
Serial.write(logFile.read());
}
logFile.close();
return true;
}
return false;
}
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;
}
}
if (!logFile)
{
return 0;
}
return index; //return number of logfile created
}
void cardFail(uint8_t num)
{
while (1)
{
Serial.print(num); //so we can tell where card failed
Serial.println(" Card failed, or not present");
led_Flash(100, 25);
}
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //for PCB LED
led_Flash(4, 125);
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("43_SD_Card_Test Starting"));
}

View File

@@ -0,0 +1,115 @@
/*******************************************************************************************************
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 test program has been written to check that hardware for reading the battery
voltage has been assembled correctly such that it is funtional. The value defined as 'ADMultiplier'
in settings.h is used to adjust the value read from the 91K\11K resistor divider and convert into mV.
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
*******************************************************************************************************/
/*
******************************************************************************************************
Program operation -
******************************************************************************************************
*/
#define ADMultiplier 6.36 //adjustment to convert AD value read into mV of battery voltage
#define BATVREADON 8 //used to turn on the resistor divider to measure voltage, //this pin turns on the MOSFET that switches in the resistor divider
#define LED1 8 //pin for PCB LED
#define SupplyAD A0 //Resitor divider for battery connected here
void loop()
{
Serial.println(F("LED Flash"));
led_Flash(4, 125);
printSupplyVoltage();
Serial.println();
delay(1500);
}
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 printSupplyVoltage()
{
//get and display supply volts on terminal or monitor
Serial.print(F("Supply Volts "));
Serial.print(readSupplyVoltage());
Serial.println(F("mV"));
}
uint16_t readSupplyVoltage()
{
//relies on internal reference and 91K & 11K resistor divider
//returns supply in mV @ 10mV per AD bit read
uint16_t temp;
uint16_t volts = 0;
byte index;
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit
}
analogReference(INTERNAL);
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;
}
void setup()
{
Serial.begin(9600); //setup Serial console ouput
Serial.println();
Serial.println(__FILE__);
Serial.print(F("Compiled "));
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println("45_Battery_Voltage_Read_Test Starting");
pinMode(LED1, OUTPUT); //for PCB LED
if (BATVREADON >= 0)
{
pinMode (BATVREADON, OUTPUT); //for turning on resistor divider
}
}

View File

@@ -0,0 +1,154 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 that an MB85RC16PNF or FM24CL64 FRAM is working and retaining
memory contents when power is removed. FRAMs are non-voltatile memory devices with a typical write
endurance of from 10,000,000,000 (MB85RC16PNF) to 100,000,000,000,000 (FM24CL64B) write cycles.
When the program starts the serial monitor will first display the results of an I2C Device scan which
should list 8 devices found from 0x50 to 0x57 for a MB85RC16PNF and 0x50 for a FM24CL64 with the default
pin connections. The MB85RC16PNF has eight 256 byte pages, FM24CL64 is one page of 8kbytes. The program
then will print the contents of the memory. Next all the variable types will be written to successive
addresses will print the area of memory, then read back each variable from memory.
To check if the FRAM is reating memory you could make some changes to the variables written, run the
program and then power off. On restart the changed variables should be displayed.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
//#include <FRAM_FM24CL64.h> //SX12xx library file for FM24CL64 FRAM, 64kbit, 8kbyte, , I2C addresse 0x50
#include <FRAM_MB85RC16PNF.h> //SX12xx library file for MB85RC16PNF FRAM, 16kbit, 2kbyte, I2C addresses 0x50 to 0x57
#include <Wire.h>
#include "I2C_Scanner.h"
#define Serial_Monitor_Baud 9600 //this is baud rate used for the Arduino IDE Serial Monitor
int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM
void loop()
{
Serial.println(F("Printing memory"));
Serial.flush();
printMemory(0, 31);
Serial.println();
Serial.flush();
while (true)
{
Serial.println();
writeMemory();
Serial.println();
readMemory();
Serial.println();
delay(5000);
}
}
void writeMemory()
{
Serial.println(F("Writing variables"));
Serial.flush();
Serial.println(F("Write char A"));
writeMemoryChar(0, 'A');
Serial.println(F("Write int8_t 0x55"));
writeMemoryInt8(1, 0x55);
Serial.println(F("Write uint8_t 0xAA"));
writeMemoryUint8(2, 0xAA);
Serial.println(F("Write int16_t 0xFEDC"));
writeMemoryInt16(3, 0xFEDC);
Serial.println(F("Write uint16_t 0x1234"));
writeMemoryUint16(5, 0x1234);
Serial.println(F("Write int32_t 0xFEDCBA98"));
writeMemoryInt32(7, 0xFEDCBA98);
Serial.println(F("Write uint32_t 0x12345678"));
writeMemoryUint32(11, 0x12345678);
Serial.println(F("Write float 0.12345678"));
writeMemoryFloat(15, 0.12345678);
}
void readMemory()
{
char var1;
int8_t var2;
uint8_t var3;
int16_t var4;
uint16_t var5;
int32_t var6;
uint32_t var7;
float var8;
char buf[9];
Serial.println(F("Reading variables"));
Serial.flush();
var1 = readMemoryChar(0);
Serial.print(F("Read char "));
Serial.write(var1);
Serial.println();
var2 = readMemoryInt8(1);
Serial.print(F("Read int8_t 0x"));
Serial.println(var2,HEX);
var3 = readMemoryUint8(2);
Serial.print(F("Read uint8_t 0x"));
Serial.println(var3,HEX);
var4 = readMemoryInt16(3);
Serial.print(F("Read int16_t 0x"));
sprintf(buf, "%04X", var4);
Serial.println(buf);
var5 = readMemoryUint16(5);
Serial.print(F("Read uint16_t 0x"));
Serial.println(var5,HEX);
var6 = readMemoryInt32(7);
Serial.print(F("Read int32_t 0x"));
Serial.println(var6,HEX);
var7 = readMemoryUint32(11);
Serial.print(F("Read uint32_t 0x"));
Serial.println(var7,HEX);
var8 = readMemoryFloat(15);
Serial.print(F("Read float "));
Serial.println(var8, 7);
}
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
setup_I2CScan();
run_I2CScan();
memoryStart(Memory_Address); //optional command to start memory with I2C address, if required
}

View File

@@ -0,0 +1,84 @@
// --------------------------------------
// i2c_scanner
//
// Version 1
// This program (or code that looks like it)
// can be found in many places.
// For example on the Arduino.cc forum.
// The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
// Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26 2013
// V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
// by Arduino.cc user Krodal.
// Changes by louarnold removed.
// Scanning addresses changed from 0...127 to 1...119,
// according to the i2c scanner by Nick Gammon
// http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
// As version 4, but address scans now to 127.
// A sensor seems to use address 120.
// Version 6, November 27, 2015.
// Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
//#include <Wire.h>
void setup_I2CScan()
{
Wire.begin();
//Serial.begin(9600);
Serial.println("I2C Scanner");
}
void run_I2CScan()
{
byte error, address;
int nDevices;
Serial.println("Scanning for I2C Devices...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found");
else
Serial.println("done");
Wire.endTransmission();
}

View File

@@ -0,0 +1,84 @@
/*******************************************************************************************************
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 - The program reads a single DS18B20 temperature sensor and prints the result to the
serial monitor.
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 then these devices are
assumed to be powered on by setting the VCCPOWER pin low. If your board does not have this feature set
VCCPOWER to -1.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define programversion "V1.0"
#define ONE_WIRE_BUS 4 //pin the DS18B20 is connected to
#define LED1 8 //LED, on when reading temperature
#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-Temperature-Control-Library
DallasTemperature sensor(&oneWire); //create instance of dallas library
void loop()
{
float DS18B20temperature;
digitalWrite(LED1, HIGH);
sensor.requestTemperatures();
digitalWrite(LED1, LOW);
DS18B20temperature = sensor.getTempCByIndex(0);
Serial.print(F("DS18B20 Temperature "));
Serial.print(DS18B20temperature, 2);
Serial.println(F("c"));
delay(5000);
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, LOW);
delay(delaymS);
digitalWrite(LED1, HIGH);
delay(delaymS);
}
}
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(programversion));
Serial.println();
Serial.println("48_DS18B20_Test Starting");
pinMode(LED1, OUTPUT);
led_Flash(4, 125); //one second of flashes
sensor.begin();
sensor.requestTemperatures(); //do a null temperature read
}

View File

@@ -0,0 +1,103 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/12/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 a NRF2401 library to
check the NRF2401 can be written to and read from over the SPI bus.
The contents of the NRF2401 registers from 0x00 to 0x1F are read and printed to the serial monitor.
If the connections are OK then the printout should look like this;
57_NRF24L01_Is_It_There ?
Print registers 0x00 to 0x1F
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 3F 02 03 5F 4C 27 42 00 00 E7 52 C3 C4 C5 C6
0x10 E7 00 20 00 00 00 00 12 00 00 FF FF FF FF FF FF
Note that this is just a 'is it there type check' the CE pin is not used or needed for this simple check.
If the device is faulty, not present or wired incorrectly the register contents will likely be all 00s or
FFs. The program makes no attempt to turn on the RF transmitter or receiver.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#define CSN_PIN 10
#define NUM_REGISTERS 26
#define CMD_R_REGISTER 0x00
#define CMD_W_REGISTER 0x20
void loop()
{
Serial.println(F("Print registers 0x00 to 0x1F"));
printRegisters(0, 0x1F);
Serial.println();
delay(5000);
}
void printRegisters(uint16_t Start, uint16_t End)
{
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;) //32 lines
{
Serial.print(F("0x"));
if (Loopv1 < 0x10)
{
Serial.print(F("0"));
}
Serial.print((Loopv1), HEX); //print the register number
Serial.print(F(" "));
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
{
RegData = readRegister(Loopv1);
if (RegData < 0x10)
{
Serial.print(F("0"));
}
Serial.print(RegData, HEX); //print the register number
Serial.print(F(" "));
Loopv1++;
}
Serial.println();
}
}
uint8_t readRegister(uint8_t reg)
{
uint8_t result = 0xFF;
if (reg < NUM_REGISTERS) {
digitalWrite(CSN_PIN, LOW);
SPI.transfer(CMD_R_REGISTER | reg);
result = SPI.transfer(0xff);
digitalWrite(CSN_PIN, HIGH);
}
return result;
}
void setup()
{
Serial.begin(9600);
pinMode(CSN_PIN, OUTPUT);
Serial.println();
Serial.println(F("57_NRF24L01_Is_It_There ?"));
Serial.println();
SPI.begin();
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/04/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 program to test a Serial Bluetooth device is working. The program
uses software serial to send a Hello World message to a serial port. If the Bluetooth device is paired
with an Android device you should see Hello World in an Andriod Bluetooth terminal application.
Bluetooth baud rate is set at 9600, an HC-06 Bluetooth device is assumed.
Note that not all pins on all Arduinos will work with software serial, see here;
https://www.arduino.cc/en/Reference/softwareSerial
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define BlueToothBAUD 9600 //this is the serial baud rate that will be used for the Bluetooth, a common default
#define MONITORBAUD 9600 //this is the serial baud rate that will be used for the serial monitor
#define RXpin A3 //this is the pin that the Arduino will use to receive data from the Bluetooth
#define TXpin A2 //this is the pin that the Arduino can use to send data (commands) to the Bluetooth
#include <SoftwareSerial.h>
SoftwareSerial BlueTooth(RXpin, TXpin);
uint32_t counter;
void loop()
{
BlueTooth.print(counter++);
BlueTooth.println(F(" Hello World"));
delay(1000);
}
void setup()
{
BlueTooth.begin(BlueToothBAUD);
Serial.begin(MONITORBAUD);
Serial.println("61_Bluetooth_Test Starting");
}

View File

@@ -0,0 +1,62 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 08/09/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 sends a command to a Quectel GPS to return its firmware revision.
The output from the GPS is copied to the Serial Monitor.
If you get no data displayed on the serial monitor, the most likely cause is that you have the receive
data pin into the Arduino (RX) pin connected incorrectly.
If the data displayed on the serial terminal appears to be random text with odd symbols its very
likely you have the GPS serial baud rate set incorrectly.
Note that not all pins on all Arduinos will work with software serial, see here;
https://www.arduino.cc/en/Reference/softwareSerial
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define GPSBAUD 9600 //this is the serial baud rate that will be used for the GPS, a common default
#define MONITORBAUD 115200 //this is the serial baud rate that will be used for the serial monitor
#define RXpin A3 //this is the pin that the Arduino will use to receive data from the GPS
#define TXpin A2 //this is the pin that the Arduino can use to send data (commands) to the GPS - not used
#define GPSPOWER 4 //When high this pin turns GPS on
#define LED1 8 //when high this pin turns LED on
#include <SoftwareSerial.h>
SoftwareSerial GPS(RXpin, TXpin);
void loop()
{
while (GPS.available())
{
Serial.write(GPS.read());
}
}
void setup()
{
pinMode(GPSPOWER, OUTPUT);
digitalWrite(GPSPOWER, HIGH);
pinMode(LED1, OUTPUT);
digitalWrite(LED1, HIGH);
GPS.begin(GPSBAUD);
Serial.begin(MONITORBAUD);
Serial.println("63_QuectelGPS_Firmware_Checker");
delay(2000);
GPS.println("$PMTK605*31");
}

View File

@@ -0,0 +1,145 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 12/10/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 uses a GPS to indicate speed, should work with most GPSs. Speed update
rate approx once per second. GPS characters are output to serial monitor when checking for update from
GPS. Prints speed in large text on an SSD1306 or SH1106 OLED.
Display and serial monitor updatesto speed only occur when the a new update has been decoded from the
GPS.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define RXpin A3 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin A2 //pin number for GPS TX output from Arduino- RX into GPS
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);
#include <U8g2lib.h> //get library here > https://github.com/olikraus/u8g2
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C disp(U8G2_R0, U8X8_PIN_NONE); //use this line for 0.96" SSD1306 OLED
//U8G2_SH1106_128X64_NONAME_1_HW_I2C disp(U8G2_R0, U8X8_PIN_NONE); //use this line for 1.3" SH1106 OLED
float GPSSpeed; //Speed of GPS, mph
uint32_t startGetFixmS;
uint32_t endFixmS;
void loop()
{
if (gpsWaitFix(3))
{
Serial.println();
Serial.println();
Serial.print(F("Fix time "));
Serial.print(endFixmS - startGetFixmS);
Serial.println(F("mS"));
GPSSpeed = gps.speed.mph();
Serial.print(F("Speed,"));
Serial.print(GPSSpeed, 1);
Serial.println();
displayscreen1(); //print GPS data on display
startGetFixmS = millis(); //have a fix, next thing that happens is checking for a fix, so restart timer
}
else
{
displayscreen2();
Serial.println();
Serial.println();
Serial.print(F("Timeout - No GPS Fix "));
Serial.print( (millis() - startGetFixmS) / 1000 );
Serial.println(F("s"));
}
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for good fix
uint32_t startmS, waitmS;
uint8_t GPSchar;
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.println(F(" seconds"));
waitmS = waitSecs * 1000; //convert seconds wait into mS
startmS = millis();
while ((uint32_t) (millis() - startmS) < waitmS)
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
Serial.write(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.speed.isUpdated())
{
endFixmS = millis(); //record the time when we got a new GPS update
return true;
}
}
return false;
}
void displayscreen1()
{
disp.setFont(u8g2_font_logisoso62_tn);
disp.firstPage();
do {
disp.setCursor(0, 63);
disp.print(GPSSpeed, 0);
} while ( disp.nextPage() );
}
void displayscreen2()
{
disp.setFont(u8g2_font_lubB14_tr);
disp.firstPage();
do {
disp.setCursor(35, 15);
disp.print(F("Speedo"));
disp.setCursor(15, 45);
disp.print(F("No GPS fix"));
} while ( disp.nextPage() );
}
void setup()
{
delay(1000);
Serial.begin(115200);
GPSserial.begin(9600);
disp.begin();
disp.clear();
displayscreen2();
disp.print(F("Display Ready"));
Serial.println(F("72A_GPS_Speedo_With_Display Starting"));
Serial.println();
startGetFixmS = millis();
}

View File

@@ -0,0 +1,105 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/12/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 uses a GPS to indicate speed, should work with most GPSs. Speed update
rate approx onece per second. GPS characters are output to serial monitor when checking for update from
GPS.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define RXpin A3 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin A2 //pin number for GPS TX output from Arduino- RX into GPS
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);
float GPSSpeed; //Speed of GPS, mph
uint32_t startGetFixmS;
uint32_t endFixmS;
void loop()
{
if (gpsWaitFix(5))
{
Serial.println();
Serial.println();
Serial.print(F("Fix time "));
Serial.print(endFixmS - startGetFixmS);
Serial.println(F("mS"));
GPSSpeed = gps.speed.mph();
Serial.print(F("Speed,"));
Serial.print(GPSSpeed, 1);
Serial.println();
startGetFixmS = millis(); //have a fix, next thing that happens is checking for a fix, so restart timer
}
else
{
Serial.println();
Serial.println();
Serial.print(F("Timeout - No GPS Fix "));
Serial.print( (millis() - startGetFixmS) / 1000 );
Serial.println(F("s"));
}
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for good fix
uint32_t startmS, waitmS;
uint8_t GPSchar;
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.println(F(" seconds"));
waitmS = waitSecs * 1000; //convert seconds wait into mS
startmS = millis();
while ((uint32_t) (millis() - startmS) < waitmS)
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
Serial.write(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.speed.isUpdated())
{
endFixmS = millis(); //record the time when we got a new GPS update
return true;
}
}
return false;
}
void setup()
{
delay(1000);
Serial.begin(115200);
GPSserial.begin(9600);
Serial.println(F("72_GPS_Speedo Starting"));
Serial.println();
startGetFixmS = millis();
}

View File

@@ -0,0 +1,134 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/09/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 a simple test program for the LIL9341 TFT display that comes in a
range of sizes. The program prints a short message on each line, pauses, clears the screen, and starts
again. Program uses Adafruit ILI9341 library.
Screen write time on Arduino DUE 332mS, screen clear 268mS
Screen write time on Teensy 4.1 207mS, screen clear 180mS
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include "SPI.h"
#include "Adafruit_GFX.h" //get library here > https://github.com/adafruit/Adafruit-GFX-Library
#include "Adafruit_ILI9341.h" //get library here > https://github.com/adafruit/Adafruit_ILI9341
int8_t DISPCS = 10;
int8_t DISPDC = 8;
//int8_t DISPCS = 43; //for DUE shield
//int8_t DISPDC = 45; //for DUE shield
Adafruit_ILI9341 disp = Adafruit_ILI9341(DISPCS, DISPDC);
#define textscale 2 //default text scale
uint16_t writecount;
uint32_t startmS, endmS, timemS;
void loop()
{
setCursor(0, 0);
disp.setTextColor(ILI9341_WHITE);
disp.setTextSize(textscale);
writecount++;
Serial.print(writecount);
Serial.print(F(" Writing to display"));
startmS = millis();
disp.fillScreen(ILI9341_BLACK); //clear screen
screen1();
endmS = millis();
timemS = endmS - startmS;
setCursor(8, 4);
disp.print(timemS);
disp.print(F("mS"));
Serial.print(F(" - done "));
Serial.print(timemS);
Serial.println(F("mS"));
delay(2000);
startmS = millis();
disp.fillScreen(ILI9341_BLACK); //clear screen
endmS = millis();
timemS = endmS - startmS;
setCursor(0, 0);
disp.print(F("Screen clear "));
disp.print(timemS);
disp.print(F("mS"));
delay(2000);
}
void setCursor(uint8_t lcol, uint8_t lrow)
{
disp.setCursor((lcol * 6 * textscale), (lrow * 10 * textscale));
}
void screen1()
{
setCursor(0, 0);
disp.print(F("ILI9341_Checker"));
setCursor(0, 1);
disp.print(F("Line 1"));
setCursor(0, 2);
disp.print(F("Line 2"));
setCursor(0, 3);
disp.print(F("Line 3"));
setCursor(0, 4);
disp.print(F("Line 4"));
setCursor(0, 5);
disp.print(F("Line 5"));
setCursor(0, 6);
disp.print(F("Line 6"));
setCursor(0, 7);
disp.print(F("Line 7"));
setCursor(0, 8);
disp.print(F("Line 8"));
setCursor(0, 9);
disp.print(F("Line 9"));
setCursor(0, 10);
disp.print(F("Line 10"));
setCursor(0, 11);
disp.print(F("01234567890123456789012")); //display is 12 lines x 23 charaters
}
void setup()
{
Serial.begin(9600);
Serial.println(F("77_ILI9341_Display_Checker starting"));
SPI.begin();
disp.begin();
//disp.setFont(Arial_16);
disp.fillScreen(ILI9341_BLACK);
disp.setTextColor(ILI9341_WHITE);
disp.setRotation(1);
disp.setTextSize(textscale);
}

View File

@@ -0,0 +1,55 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 14/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a simple terminal to allow you to use a Serial terminal program, such as Teraterm
or CoolTerm to talk to a serial device such as a Bluetooth module connected to your Arduino.
Note that not all pins on all Arduinos will work with software serial, see here;
https://www.arduino.cc/en/Reference/softwareSerial
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define DEVICEBAUD 9600 //serial baud rate that will be used for the device conncted to your Arduino
#define MONITORBAUD 9600 //serial baud rate that will be used for the serial monitor
#define RXpin A3 //this is the pin that the Arduino will use to receive data from the serial device
#define TXpin A2 //this is the pin that the Arduino can use to send data (commands) to the serial device
#include <SoftwareSerial.h>
SoftwareSerial device(RXpin, TXpin);
void loop()
{
while (device.available())
{
Serial.write(device.read());
}
while (Serial.available())
{
device.write(Serial.read());
}
}
void setup()
{
device.begin(DEVICEBAUD);
Serial.begin(MONITORBAUD);
Serial.println("79_Serial_Terminal Starting");
delay(1000);
}

View File

@@ -0,0 +1,120 @@
/*******************************************************************************************************
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 is a simple test for a Bosch BME280 sensor. Readings are sent to the serial
monitor. The Seeed library assumes the BME280 is at address 0x76. It can be changed to 0x77 by an edit
in the Seeed_BME280.h librsry file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <Seeed_BME280.h> //get library here; https://github.com/Seeed-Studio/Grove_BME280
BME280 bme280; //create an instance of the BME280 senosor
#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control
#include <Wire.h>
#define LED1 8 //on board LED, high for on
float temperature; //the BME280 temperature value
float pressure; //the BME280 pressure value
uint16_t humidity; //the BME280 humididty value
void loop()
{
Serial.print(F("Reading > "));
readSensors(); //read the sensor values
printSensorValues(); //print the sensor values
Serial.println();
sleepBME280();
delay(500);
normalBME280(); //BME280 sensor to normal mode
}
void readSensors()
{
//read the sensor values into the global variables
temperature = bme280.getTemperature();
pressure = bme280.getPressure();
humidity = bme280.getHumidity();
}
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("%"));
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(uint8_t reg, uint8_t 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();
}
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);
Serial.begin(9600);
Serial.println();
Serial.println(F("81_BME280_Test starting"));
bme280.init();
Serial.println(F("Initialised BME280"));
Serial.println();
readSensors(); //do an initial sensor read
}

View File

@@ -0,0 +1,28 @@
//see the video here > https://www.youtube.com/watch?v=eeDC1m7ANJI&t=100s
//code here > https://gist.github.com/speters/f889faec42b510052a6ab4be437d38ca
//Purpose is to simply run a memory check on ATMEGA238P to test for counterfeit parts
#include <avr/boot.h>
#define SIGRD 5
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("");
Serial.println("boot sig dump");
int newLineIndex = 0;
for (uint8_t i = 0; i <= 0x1F; i += 1) {
Serial.print(boot_signature_byte_get(i), HEX);
Serial.print("\t");
newLineIndex++;
if (newLineIndex == 8) {
Serial.println("");
newLineIndex = 0;
}
}
Serial.println();
}
void loop() {
}

View File

@@ -0,0 +1,26 @@
//
// ArduinoUniqueID.ino
//
// Example shows the UniqueID on the Serial Monitor.
//
#include <ArduinoUniqueID.h> //get library here > https://github.com/ricaun/ArduinoUniqueID
void setup()
{
Serial.begin(115200);
UniqueIDdump(Serial);
Serial.print("UniqueID: ");
for (size_t i = 0; i < UniqueIDsize; i++)
{
if (UniqueID[i] < 0x10)
Serial.print("0");
Serial.print(UniqueID[i], HEX);
Serial.print(" ");
}
Serial.println();
}
void loop()
{
}

View File

@@ -0,0 +1,69 @@
// --------------------------------------
// i2c_scanner
// from: https://playground.arduino.cc/Main/I2cScanner/
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
#include <Wire.h>
uint16_t counter;
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println(F("I2C Scanner starting"));
Serial.println();
}
void loop()
{
uint8_t error, address;
int16_t nDevices;
counter++;
Serial.print(counter);
Serial.println(F(" Scanning..."));
nDevices = 0;
for (address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(F("I2C device found at address 0x"));
if (address < 16)
Serial.print(F("0"));
Serial.println(address, HEX);
nDevices++;
}
else if (error == 4)
{
Serial.print(F("Unknown error at address 0x"));
if (address < 16)
Serial.print(F("0"));
Serial.println(address, HEX);
}
}
if (nDevices == 0)
{
Serial.println(F("No I2C devices found"));
}
else
{
Serial.println();
Serial.println(F("Done"));
Serial.println();
}
delay(5000); // wait 5 seconds for next scan
}

View File

@@ -0,0 +1,86 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program is a simple test program for the SSD1306 and SH1106 OLEDs. The program
prints a short message on each line, pauses, clears the screen, and starts again.
OLED address is defined as 0x3C.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#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
#define DEFAULTFONT u8x8_font_chroma48medium8_r //font for U8X8 Library
#define OLED_Address 0x3C
uint16_t writecount;
uint32_t startwritemS, endwritemS, timemS;
void loop()
{
writecount++;
Serial.print(writecount);
Serial.print(F(" Writing to display"));
disp.setI2CAddress(OLED_Address<<1); //I2C address multiplied by 2, the lowest bit must be zero
disp.setFont(DEFAULTFONT);
startwritemS = millis();
disp.clear();
screen1();
endwritemS = millis();
timemS = endwritemS - startwritemS;
disp.setCursor(8, 4);
disp.print(timemS);
disp.print(F("mS"));
Serial.print(F(" - done"));
Serial.print(timemS);
Serial.println(F("mS"));
delay(2000);
Serial.println(F("PowerSave display"));
disp.setPowerSave(1); //power save display, turns off
delay(2000);
disp.setPowerSave(0); //display back to normal
}
void screen1()
{
disp.setCursor(0, 0);
disp.print(F("Hello World !"));
disp.setCursor(0, 1);
disp.print(F("Line 1"));
disp.setCursor(0, 2);
disp.print(F("Line 2"));
disp.setCursor(0, 3);
disp.print(F("Line 3"));
disp.setCursor(0, 4);
disp.print(F("Line 4"));
disp.setCursor(0, 5);
disp.print(F("Line 5"));
disp.setCursor(0, 6);
disp.print(F("Line 6"));
disp.setCursor(0, 7);
disp.print(F("0123456789012345")); //display is 8 lines x 16 charaters when using the
//u8x8_font_chroma48medium8_r font
}
void setup()
{
Serial.begin(9600);
Serial.println(F("31_SSD1306_SH1106_OLED_Checker_ESP32 starting"));
disp.begin();
}

View File

@@ -0,0 +1,272 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 04/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 test program has been written to check that a connected SD card adapter, Micro
or standard, is functional.
When the program runs it will attempts to create a file that is next in sequence to Log0000.txt, thus
if this is the first time the program has run on the SD card it will create file Log0001.txt. If the
file Log0001.txt exists it will create Log0002.txt etc. This ensures that everytime the program starts
it creates a new file for testing.
Next the program checks if the Logxxxx.txt file exists and if so attempts to delete it.
Then the program starts a loop. First the same file is again opened for append, it will be created if it
does not exist and then the line '1 Hello World' is writtent to the file. The file is closed and the
contents of the file are dumped to the serial monitor. The loop restarts, and this time the line
'2 Hello World' is appended to the file.
As the program progresses the file will grow in size and after 4 iterrations of the open,write,close
and dump loop the file dump on serial monitor will look like this
1 Hello World
2 Hello World
3 Hello World
4 Hello World
This file dump will grow if you let the program run. If an error with the SD card is detected at any
time the LED will rapid flash continuously and the message 'X Card failed, or not present' is printed
to serial monitor. The number X will allow you to check the program listing for where the error occured.
1 Card failed = SD card did not initialise
2 Card failed = Could nt setup logFile for new name
3 Card failed = Could not open file for append
4 Card failed = Failure to dump file to serial monitor
Note: At the time of writing, 04/06/20, the function that the dumpFile() routine uses to check if an SD
card is still present, SD.exists(filename), does not work on the SD.h file included in the current Expressif
core for Arduino. If the SD card is removed, the SD.exists(filename) function returns true so the following
dump of the file locks up the ESP32.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SD.h>
#include <SPI.h>
//pin definitions. You also need to connect the card SCK to pin 18, MISO to pin 19 and MOSI to pin 23
#define LED1 2 //pin number for LED
#define SDCS 13 //pin number for device select on SD card module
File logFile;
char filename[] = "/LOG0000.TXT"; //filename used as base for creating logfile, 0000 replaced with numbers
uint16_t linecount;
void loop()
{
Serial.println();
Serial.println("Initializing SD card");
if (!SD.begin(SDCS))
{
cardFail(1);
}
Serial.println("Card initialized");
logFile = SD.open("/");
Serial.println("Card directory");
Serial.println();
printDirectory(logFile, 0);
Serial.println();
Serial.println();
if (!setupSDLOG(filename)) //setup logfile name for writing
{
cardFail(2);
}
Serial.print(F("logFile name is "));
Serial.println(filename);
if (SD.exists(filename))
{
Serial.print(filename);
Serial.println(" exists - delete");
SD.remove(filename);
}
if (!SD.exists(filename))
{
Serial.print(filename);
Serial.println(" does not exist");
}
while (1)
{
logFile = SD.open(filename, FILE_APPEND);
if (!logFile)
{
cardFail(3);
}
linecount++;
logFile.print(linecount);
logFile.println(" Hello World");
logFile.close();
Serial.println();
Serial.print("Dump file ");
Serial.println(filename);
Serial.println();
digitalWrite(LED1, HIGH);
if (dumpFile(filename))
{
Serial.println();
Serial.println("Finished File Dump");
}
else
{
cardFail(4);
}
digitalWrite(LED1, LOW);
delay(2000);
}
}
void printDirectory(File dir, int numTabs)
{
while (true)
{
File entry = dir.openNextFile();
if (! entry)
{
//no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory())
{
Serial.println("/");
printDirectory(entry, numTabs + 1);
}
else
{
//files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
bool dumpFile(char *buf)
{
//Note, this function will return true if the SD card is remove. See note at program start.
if (SD.exists(buf))
{
Serial.print(buf);
Serial.println(" found");
}
else
{
Serial.print(filename);
Serial.println(" not found");
return false;
}
logFile = SD.open(buf);
if (logFile) //if the file is available, read from it
{
while (logFile.available())
{
Serial.write(logFile.read());
}
logFile.close();
return true;
}
return false;
}
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;
}
}
if (!logFile)
{
return 0;
}
return index; //return number of logfile created
}
void cardFail(uint8_t num)
{
while (1)
{
Serial.print(num); //so we can tell where card failed
Serial.println(" Card failed, or not present");
led_Flash(100, 25);
}
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //for PCB LED
led_Flash(4, 125);
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("43_SD_Card_Test Starting"));
}

View File

@@ -0,0 +1,110 @@
/*******************************************************************************************************
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 test program has been written to check that a connected SD card adapter, Micro
or standard, is funtional with the FS functions. To use the program first copy the file (in this programs
directory) called testfile.txt to the root directory of the SD card.
When the program runs it will attempt to open 'testfile.txt' and spool the contents to the Arduino IDE
serial monitor. The testfile is part of the source code for the Apollo 11 Lunar Lander navigation and
guidance computer. There are LED flashes at power up or reset, then at start of every loop of the test.
The LED is on whilst the testfile is being read. If the LED flashes very rapidly then there is a problem
accessing the SD card.
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.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include "ESP32_LoRa_Micro_Node.h"
#include "FS.h"
#include "SD.h"
#include "SPI.h"
void loop()
{
Serial.println(F("LED Flash"));
Serial.println();
led_Flash(2, 50);
readFile(SD, "/testfile.txt");
delay(1000);
}
void readFile(fs::FS &fs, const char * path) {
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file) {
Serial.println();
Serial.println("Failed to open file for reading");
Serial.println();
return;
}
Serial.print("Read from file: ");
digitalWrite(LED1, HIGH);
while (file.available()) {
Serial.write(file.read());
}
file.close();
digitalWrite(LED1, LOW);
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //for PCB LED
led_Flash(4, 125);
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("44_SD_Card_Test_With_FS_ESP32 Starting"));
Serial.print("Initializing SD card...");
if (!SD.begin(SDCS)) {
Serial.println("Card failed, or not present.");
led_Flash(100, 25);
return; //loop if no card found
}
Serial.println("Card initialized.");
}

View File

@@ -0,0 +1,21 @@
/*******************************************************************************************************
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 13, 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 SWITCH1 0 //pin number to attach switch
#define LED1 2 //pin number for LED
#define SDCS 13 //ESP32 pin number for device select on SD card module
#define VCCPOWER 14 //pin controls power to external devices, such as the SD card

View File

@@ -0,0 +1,111 @@
/*******************************************************************************************************
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 test program has been written to check that hardware for reading the battery
voltage has been assembled correctly such that it is funtional. The value defined as 'ADMultiplier'
in settings.h is used to adjust the value read from the 91K\11K resistor divider and convert into mV.
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 ADMultiplier 10.872 //adjustment to convert AD value read into mV of battery voltage
#define BATVREADON 25 //used to turn on the resistor divider to measure voltage //this pin turns on the MOSFET that switches in the resistor divider
#define LED1 2 //pin for PCB LED
#define SupplyAD 36 //Resitor divider for battery connected here
void loop()
{
Serial.println(F("LED Flash"));
led_Flash(4, 125);
printSupplyVoltage();
Serial.println();
delay(1500);
}
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 printSupplyVoltage()
{
//get and display supply volts on terminal or monitor
Serial.print(F("Supply Volts "));
Serial.print(readSupplyVoltage());
Serial.println(F("mV"));
}
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 setup()
{
Serial.begin(9600); //setup Serial console ouput
Serial.println();
Serial.println(__FILE__);
Serial.print(F("Compiled "));
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println("45_Battery_Voltage_Read_Test_ESP32 Starting");
pinMode(LED1, OUTPUT); //for PCB LED
if (BATVREADON >= 0)
{
pinMode(BATVREADON, OUTPUT); //controls MOSFET connecting resitor divider in circuit
}
}

View File

@@ -0,0 +1,90 @@
/*******************************************************************************************************
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 flashes a LED connected to the pin defined by LED1, and puts the ESP32
to deep_sleep for a period determined by the TIME_TO_SLEEP variable (in seconds).
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.
Current in deep_sleep for a bare bones ESP32 with regulator and no other devices was 27uA.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define LED1 2 //pin number for LED
#define VCCPOWER 14 //pin may control power to external devices, -1 if not used
#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 int32_t bootCount = 0;
RTC_DATA_ATTR uint32_t sleepcount = 0;
void loop()
{
Serial.print(F("Bootcount "));
Serial.println(bootCount);
Serial.print(F("Sleepcount "));
Serial.println(sleepcount);
Serial.println(F("LED Flash"));
led_Flash(4, 125);
Serial.println(F("LED On"));
digitalWrite(LED1, HIGH);
delay(2500);
Serial.println(F("LED Off"));
digitalWrite(LED1, LOW);
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println(F("Start Sleep"));
Serial.flush();
sleepcount++;
esp_deep_sleep_start();
Serial.println();
Serial.println();
Serial.println(F("Awake !"));
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
//flash LED to show tracker is alive
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, LOW);
delay(delaymS);
digitalWrite(LED1, HIGH);
delay(delaymS);
}
}
void setup()
{
Serial.begin(9600); //setup Serial console ouput
Serial.println(F("47_DeepSleep_Timed_Wakeup_ESP32 - Starting"));
if (bootCount == 0) //Run this only the first time
{
bootCount = bootCount + 1;
}
pinMode(LED1, OUTPUT); //for PCB LED
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT);
digitalWrite(VCCPOWER, HIGH); //VCCOUT off
}
}

View File

@@ -0,0 +1,92 @@
/*******************************************************************************************************
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 flashes a LED connected to the pin defined by LED1, and puts the ESP32 to
light_sleep for a period determined by TIME_TO_SLEEP (in seconds).
The program also has the option of using a logic pin to control the power to the lora.SD card and DS18B20
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.
Current in light_sleep mode was 1500uA
****************************************************************************************************************
*/
#define VCCPOWER 14 //when low supplies VCC power to external devices. Set to -1 if not used
#define LED1 2 //On board LED, high for on
#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(F("LED Flash"));
led_Flash(4, 125);
Serial.println(F("LED On"));
digitalWrite(LED1, HIGH);
delay(2500);
Serial.println(F("LED Off"));
digitalWrite(LED1, LOW);
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 !"));
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
//flash LED to show tracker is alive
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, LOW);
delay(delaymS);
digitalWrite(LED1, HIGH);
delay(delaymS);
}
}
void setup()
{
Serial.begin(9600); //setup Serial console ouput
Serial.println(F("50_LightSleep_Timed_Wakeup_ESP32 - Starting"));
if (bootCount == 0) //Run this only the first time
{
bootCount = bootCount + 1;
}
pinMode(LED1, OUTPUT); //for PCB LED
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
digitalWrite(VCCPOWER, HIGH); //VCCOUT off, lora device and SD card off
}
}

View File

@@ -0,0 +1,87 @@
/*******************************************************************************************************
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 flashes a LED connected to the pin defined by LED1, and puts the ESP32
to deep_sleep. Pressing BOOT switch should wake up the ESP32 from sleep.
Only the specific RTC IO pins can be used as a source for external wakeup.
These are pins: 0,2,4,12-15,25-27,32-39.
Current in deep_sleep for a bare bones ESP32 with regulator and no other devices was 27uA.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define LED1 2 //pin number for LED
#define SWITCH1 0 //pin number wakeup switch
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(F("LED Flash"));
led_Flash(4,125);
Serial.println(F("LED On"));
digitalWrite(LED1, HIGH);
delay(2500);
Serial.println(F("LED Off"));
digitalWrite(LED1, LOW);
//esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0); //wakeup on pin GPIO0 going low
Serial.println(F("Start Sleep"));
Serial.flush();
sleepcount++;
esp_deep_sleep_start();
Serial.println();
Serial.println();
Serial.println(F("Awake ?")); //should not really see this, deep sleep wakeup causes reset ....
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
//flash LED to show tracker is alive
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, LOW);
delay(delaymS);
digitalWrite(LED1, HIGH);
delay(delaymS);
}
}
void setup()
{
Serial.begin(9600); //setup Serial console ouput
Serial.println();
Serial.println();
Serial.println(F("51_DeepSleep_Timed_Wakeup_ESP32 - Starting"));
if(bootCount == 0) //Run this only the first time
{
bootCount = bootCount+1;
}
pinMode(LED1, OUTPUT); //for PCB LED
pinMode(SWITCH1, INPUT_PULLUP); //for wakeup switch
}

View File

@@ -0,0 +1,131 @@
/*******************************************************************************************************
lora 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 - When the ESP32 turns on the WiFi function, there is a short high current pulse that
can cause the ESP32 brownout detect to operate.
This test program at startup flashes an LED, leaves it on and then starts the WiFi. If the Wifi initiates
a brownout, you will see the LED flash again. The LED stays on when scanning, the program reports the
networks found to the serial console and displays them on an attached SSD1306 OLED.
Thus if you see the LED continually doing short bursts of flashing the turn on\off the WiFi is causing
the ESP32 to reset. There will also be a message on the serial monitor that the brownout detector operated.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#include "WiFi.h"
#define LED1 2 //Arduino pin number for LED, when high LED should be on.
#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
void loop()
{
Serial.println("Set WiFi to Station mode"); //Set WiFi to station mode
Serial.flush();
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(1000);
Serial.println("Setup done");
Serial.flush();
digitalWrite(LED1, HIGH);
Serial.println("WiFi scan start");
Serial.flush();
int n = WiFi.scanNetworks(); //WiFi.scanNetworks will return the number of networks found
digitalWrite(LED1, LOW);
delay(500);
disp.clear();
disp.setCursor(0, 0);
if (n == 0) {
Serial.println("No WiFi");
disp.println("No WiFi");
} else {
Serial.print(n);
disp.print(n);
Serial.println(" WiFi found");
disp.println(" WiFi found");
led_Flash(n, 500);
if (n > 16) //only want to display first 16 networks
{
n = 16;
}
for (int i = 0; i < n; ++i) {
//Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
if (i > 7)
{ disp.clearLine(i - 8);
disp.setCursor(0, i - 8);
}
else
{
disp.clearLine(i);
disp.setCursor(0, i);
}
disp.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
if (i == 7) //check if 8 lines have already been sent to display
{
delay(2000); //leave last 8 on display for a while
disp.clear();
}
}
}
Serial.println();
disp.println();
// Wait a bit before scanning again
delay(5000);
}
void led_Flash(unsigned int flashes, unsigned int delaymS)
{
//flash LED
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(5, 50);
digitalWrite(LED1, LOW);
delay(1000);
Serial.begin(9600);
disp.begin();
disp.setFont(u8x8_font_chroma48medium8_r);
disp.clear();
disp.setCursor(0, 0);
disp.print(F("Scanner Ready"));
}

View File

@@ -0,0 +1,35 @@
/*******************************************************************************************************
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 SWITCH1 0 //pin number for switch, the boot switch also
#define LED1 2 //pin number for LED
#define NSS 5 //pin number where the NSS line for the LoRa device is connected
#define SDCS 13 //ESP32 pin number for device select on SD card module
#define VCCPOWER 14 //pin controls power to external devices
#define DIO2 15 //pin number for DIO2 pin on LoRa device
#define TonePin 15 //pin number for LoRa radio tone generation, connects to LoRa device pin DIO2
#define GPSTX 16 //pin number for TX output from Arduino - RX into GPS
#define GPSRX 17 //pin number for RX input into Arduino - TX from GPS
#define BATREAD 25 //pin that switches on supply measure resistor devider
#define GPSPOWER 26 //pin controls power to external devices
#define NRESET 27 //pin where LoRa device reset line is connected
#define ONEWIREBUS 33 //pin for one wire bus devices
#define DIO1 34 //pin connected to DIO1 on LoRa device
#define DIO0 35 //pin number for DIO0 pin on LoRa device
#define SupplyAD 36 //pin for reading supply voltage
#define ADMultiplier 10 //multiplier for supply volts calculation, default

View File

@@ -0,0 +1,125 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 27/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 simple test for a Bosch BME280 sensor. Readings are sent to the serial
monitor.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <Seeed_BME280.h> //get library here; https://github.com/Seeed-Studio/Grove_BME280
BME280 bme280; //create an instance of the BME280 senosor
#define BME280_ADDRESS 0x76 //I2C bus address of BME280
#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control
#include <Wire.h>
#define LED1 2 //on board LED, high for on
float temperature; //the BME280 temperature value
float pressure; //the BME280 pressure value
uint16_t humidity; //the BME280 humididty value
void loop()
{
Serial.print(F("Reading > "));
readSensors(); //read the sensor values
printSensorValues(); //print the sensor values
Serial.println();
sleepBME280();
delay(5000);
normalBME280(); //BME280 sensor to normal mode
}
void readSensors()
{
//read the sensor values into the global variables
temperature = bme280.getTemperature();
pressure = bme280.getPressure();
humidity = bme280.getHumidity();
}
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("%"));
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(uint8_t reg, uint8_t 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();
}
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);
Serial.begin(9600);
Serial.println();
Serial.println(F("81_BME280_Test_ESP32 starting"));
bme280.init(); //intialise BME280 library
Wire.begin(); //default for ESP32 is SDA on 21, SCL on 22
//alternative pins for I2C, ESP32 allows re-direction of I2C, format is Wire.begin(SDA,SCL);
//The SeedBME280 library does do a Wire.begin(); so this will overide it
Wire.begin(16,17);
Serial.println(F("Initialised BME280"));
Serial.println();
readSensors(); //do an initial sensor read
}

View File

@@ -0,0 +1,86 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program is a simple test program for the SSD1306 and SH1106 OLEDs. The program
prints a short message on each line, pauses, clears the screen, and starts again.
OLED address is defined as 0x3C.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#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
#define DEFAULTFONT u8x8_font_chroma48medium8_r //font for U8X8 Library
#define OLED_Address 0x3C
uint16_t writecount;
uint32_t startwritemS, endwritemS, timemS;
void loop()
{
writecount++;
Serial.print(writecount);
Serial.print(F(" Writing to display"));
disp.setI2CAddress(OLED_Address<<1); //I2C address multiplied by 2, the lowest bit must be zero
disp.setFont(DEFAULTFONT);
startwritemS = millis();
disp.clear();
screen1();
endwritemS = millis();
timemS = endwritemS - startwritemS;
disp.setCursor(8, 3);
disp.print(timemS);
disp.print(F("mS"));
Serial.print(F(" - done "));
Serial.print(timemS);
Serial.println(F("mS"));
delay(2000);
Serial.println(F("PowerSave display"));
disp.setPowerSave(1); //power save display, turns off
delay(2000);
disp.setPowerSave(0); //display back to normal
}
void screen1()
{
disp.setCursor(0, 0);
disp.print(F("Hello World !"));
disp.setCursor(0, 1);
disp.print(F("Line 1"));
disp.setCursor(0, 2);
disp.print(F("Line 2"));
disp.setCursor(0, 3);
disp.print(F("Line 3"));
disp.setCursor(0, 4);
disp.print(F("Line 4"));
disp.setCursor(0, 5);
disp.print(F("Line 5"));
disp.setCursor(0, 6);
disp.print(F("Line 6"));
disp.setCursor(0, 7);
disp.print(F("0123456789012345")); //display is 8 lines x 16 charaters when using the
//u8x8_font_chroma48medium8_r font
}
void setup()
{
Serial.begin(9600);
Serial.println(F("31_SSD1306_OLED_Checker starting"));
disp.begin();
}

View File

@@ -0,0 +1,636 @@
## SX12XX Library Example Programs
For the majority of the program examples you will need to define the pins used, the frequency and the LoRa settings in the Settings.h file. The default provided settings may not be optimised for long distance. See the 'What is LoRa' document for information on how LoRa settings affect range.
Some of the examples use sleep mode on the processor and LoRa device to save power. Typical sleep currents may be mentioned in the description of the program. In most all cases a 'bare bones' Arduino has been used to measure the sleep currents and you may not get even close to the quoted figures using standard Arduinos such as Pro Minis or similar. Optimising particular Arduino boards for low power sleep is outside of the scope of this library and examples.
#### 1\_LED\_Blink &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This program blinks an LED connected the pin number defined by LED1.The pin 13 LED, fitted to some Arduinos is blinked as well. The blinks should be close to one per second. Messages are sent to the Serial Monitor also.
#### 2\_Register\_Test &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This program is stand alone, it is not necessary to install the SX12XX-LoRa library to use it.
The program checks that a 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 different to the programmed frequency, there is a rounding error due to the use of floats to calculate the frequency.
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 70 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 04 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 10 00 00 00 0F E0 00 0C 04 06 00 5C 78
0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F2 3F D9 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 70 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 04 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 10 00 00 00 0F E0 00 0C 04 06 00 5C 78
0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F2 3F D9 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
#### 3\_LoRa\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This is a minimum setup LoRa test transmitter. A packet containing the ASCII text "Hello World 1234567890" is sent using the frequency and LoRa settings specified in the LT.setupLoRa() command. The pins to access the lora device need to be defined at the top of the program also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with the transmit power used and the packet length. The matching receiver program, '4\_LoRa\_Receiver' can be used
to check the packets are being sent correctly, the frequency and LoRa settings (in the LT.setupLoRa() commands) must be the same for the transmitter and receiver programs. Sample Serial Monitor output;
10dBm Packet> Hello World 1234567890 BytesSent,23 PacketsSent,6
For an example of a more detailed configuration for a transmitter, see program 103\_LoRa\_Transmitter.
Serial monitor baud rate is set at 9600
#### 4\_LoRa\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This is a minimum setup LoRa test receiver. The program listens for incoming packets using the frequency and LoRa settings in the LT.setupLoRa() command. The pins to access the lora device need to be defined at the top of the program also.
There is a printout on the Arduino IDE serial monitor of the valid packets received, the packet is assumed to be in ASCII printable text, if it's not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor. Sample serial monitor output;
8s Hello World 1234567890,RSSI,-44dBm,SNR,9dB,Length,23,Packets,7,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error;
137s PacketError,RSSI,-89dBm,SNR,-8dB,Length,23,Packets,37,Errors,2,IRQreg,70,IRQ\_HEADER\_VALID,IRQ\_CRC\_ERROR,IRQ\_RX\_DONE
If there are no packets received in a 10 second period then you should see a message like this;
112s RXTimeout
For an example of a more detailed configuration for a receiver, see program 104\_LoRa\_Receiver.
Serial monitor baud rate is set at 9600.
<br>
#### 5\_LoRa\_TX\_Sleep\_Timed\_Wakeup\_Atmel &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Sleep folder)
This program tests the sleep mode and register retention of the lora device in sleep mode, it assumes an Atmel ATMega328P processor is in use. The LoRa settings to use are specified in the 'Settings.h' file.
A packet is sent, containing the text 'Before Device Sleep' and the LoRa device and Atmel processor are put to sleep. The processor watchdog timer should wakeup the processor in 15 seconds (approx) and 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.
Tested on a 'bare bones' ATmega328P board, the current in sleep mode was 6.5uA.
#### 6\_LoRa\_RX\_and\_Sleep\_Atmel &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Sleep folder)
The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
When the program starts the LoRa device is set-up to receive packets with pin DIO0 set to go high when a packet arrives. The receiver remains powered (it cannot receive otherwise) and the processor (Atmel ATMega328P or 1284P) is put to sleep. When pin DIO0 does go high, indicating a packet is received, the processor wakes up and prints the packet. It then goes back to sleep.
There is a printout of the valid packets received, these are assumed to be in ASCII printable text. The LED will flash for each packet received and the buzzer will sound,if fitted.
Tested on a 'bare bones' ATmega328P board, the current in sleep mode was 12.26mA.
#### 7\_LoRa\_TX\_Sleep\_Switch\_Wakeup\_Atmel &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Sleep folder)
This program tests the sleep mode and register retention of the lora device in sleep mode, it assumes an Atmel ATMega328P processor is in use. The LoRa settings to use are specified in the 'Settings.h' file.
A packet is sent, containing the text 'Before Device Sleep' and the lora device and Atmel processor are put to sleep. The processor should remain asleep until the pin defined by SWITCH1 in the Settings.h file is connected to ground and the LoRa device register values should be retained. The LoRa 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.
Tested on a bare bones ATmega328P board, the current in sleep mode was 2.4uA.
#### 8\_LoRa\_LowMemory\_TX &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (LowMemory folder)
The program transmits a packet without using a processor buffer, the LoRa device internal buffer is filled direct with variables. The program is a simulation of the type of packet that might be sent from a GPS tracker. Note that in this example a buffer of text is part of the transmitted packet, this does need a processor buffer which is used to fill the LoRa device internal buffer, if you don't need to transmit text then the uint8_t trackerID[] = "tracker1"; definition can be omitted.
The matching receiving program '9\_LoRa\_LowMemory\_RX' can be used to receive and display the packet, though the program '15\_LoRa\_RX\_Structure' should receive it as well, since the packet contents are the same.
The contents of the packet received, and printed to serial monitor, should be;
"tracker1" (buffer) - trackerID
1+ (uint32\_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16\_t) - altitude
8 (uint8\_t) - number of satellites
3999 (uint16\_t) - battery voltage
-9 (int8_t) - temperature
#### 9\_LoRa\_LowMemory\_RX &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (LowMemory folder)
The program receives a packet without using a processor buffer, the LoRa device internal buffer is read direct and copied to variables. The program is a simulation of the type of packet that might be received from a GPS tracker. Note that in this example a buffer of text is part of the received packet, this does need a processor buffer which is filled with data from the LoRa device internal buffer, if you don't need to send and receive text then the uint8_t receivebuffer[32]; definition can be omitted.
The contents of the packet received, and printed to serial monitor, should be;
"tracker1" (buffer) - trackerID
1+ (uint32\_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16\_t) - altitude
8 (uint8\_t) - number of satellites
3999 (uint16\_t) - battery voltage
-9 (int8_t) - temperature
#### 10\_LoRa\_Link\_Test\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
This is a program that can save you a great deal of time if your testing the effectiveness of a LoRa links or attached antennas. Simulations of antenna performance are no substitute for real world tests and this simple program allows both long distance link performance to be evaluated and antenna performance to be compared.
The program sends short test packets that reduce in power by 1dBm at a time. The start power is defined by start\_power and the end power is defined by end\_power (see Settings.h file). Once the end\_power point is reached, the program pauses a short while and starts the transmit sequence again at start\_power. The packet sent contains the power used to send the packet. By listening for the packets with the basic LoRa receive program (4\_LoRa\_Receiver) you can see the reception results, which should look something like this;
11s 1*T+05,CRC,80B8,RSSI,-03dBm,SNR,9dB,Length,6, Packets,9,Errors,0,IRQreg,50
12s 1*T+04,CRC,9099,RSSI,-74dBm,SNR,9dB,Length,6, Packets,10,Errors,0,IRQreg,50
14s 1*T+03,CRC,E07E,RSSI,-75dBm,SNR,9dB,Length,6, Packets,11,Errors,0,IRQreg,50
Above shows 3 packets received, the first at +05dBm (+05 in printout), the second at 4dBm (+04 in printout) and the third at 3dBm (+03) in printout.
If it is arranged so that reception of packets fails halfway through the sequence by attenuating either the transmitter (with an SMA attenuator for instance) or the receiver (by placing it in a tin perhaps) then if you swap transmitter antennas you can see the dBm difference in reception, which will be the dBm difference (gain) of the antenna.
To start the sequence a packet is sent with the number 999, when received it looks like this;
T*1999
This received packet could be used for the RX program to be able to print totals etc.
LoRa settings to use for the link test are specified in the 'Settings.h' file.
#### 11\_LoRa\_Packet\_Logger\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
This is a useful packet logger program. It listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout of the valid packets received in HEX format. Thus the program can be used to receive and record non-ASCII packets. The LED will flash for each packet received and the buzzer will sound, if fitted. The measured frequency difference between the frequency used by the transmitter and the frequency used by the receiver is shown. If this frequency difference gets to 25% of the set LoRa bandwidth, packet reception will fail. The displayed error can be reduced by using the 'offset' setting in the 'Settings.h' file.
#### 12\_ATmel\_Sleep\_with\_Switch\_Wakeup &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This program tests the deep sleep mode and wakeup with a switch of an Atmel 328P or 1284P processor. The program starts, flashes the LED and then puts the processor into permanent sleep. It can be woken up with a switch press. Used as a base test routine for checking the sleep current of a board.
Tested on an 'bare bones' ATmega328P board, the current in sleep mode was 1.7uA with a 3.3V MCP1700 regulator being used.
#### 13\_Frequency\_and\_Power\_Check\_TX &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
This is a program that transmits a long LoRa packets lasting about 5 seconds that can be used to measure the frequency and power of the transmission using external equipment. The bandwidth of the transmission is only 10khz, so a frequency counter should give reasonable average result.
The LoRa settings to use, including transmit power, are specified in the 'Settings.h' file.
#### 14\_LoRa\_Structure\_TX &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This program demonstrates the transmitting of a structure as a LoRa packet. The contents of the structure are the same as in the '8\_LoRa\_LowMemory\_TX' program. The packet sent is typical of what might be sent from a GPS tracker. The structure type is defined as trackerPacket and an instance called location1 is created. The structure which includes a character array (text) is filled with values and transmitted.
The matching receiving program '15\_LoRa\_RX\_Structure' can be used to receive and display the packet, though the program '9\_LoRa\_LowMemory\_RX' should receive it as well, since the contents are the same.
Note that the structure definition and variable order (including the buffer size) used in the transmitter need to match those used in the receiver.
The contents of the packet transmitted should be;
"tracker1" (buffer) - trackerID
1+ (uint32\_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16\_t) - altitude
8 (uint8\_t) - number of satellites
3999 (uint16\_t) - battery voltage
-9 (int8_t) - temperature
#### 15\_LoRa\_Structure\_RX &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This program demonstrates the receiving of a structure as a LoRa packet. The packet sent is typical of what might be sent from a GPS tracker.
The structure type is defined as trackerPacket and an instance called location1 is created. The structure includes a character array (text).
The matching receiving program is '15\_LoRa\_RX\_Structure' can be used to receive and display the packet, though the program '9\_LoRa\_LowMemory\_RX' should receive it as well, since the packet contents are the same.
Not that the structure definition and variable order (including the buffer size) used in the transmitter need to match those used in the receiver. Good luck.
The contents of the packet received, and printed to serial monitor, should be;
"tracker1" (buffer) - trackerID
1+ (uint32\_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16\_t) - altitude
8 (uint8\_t) - number of satellites
3999 (uint16\_t) - battery voltage
-9 (int8_t) - temperature
#### 16\_LoRa\_RX\_Frequency\_Error\_Check &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
This program can be used to check the frequency error between a pair of LoRa devices, a transmitter and receiver. This receiver measures the frequecy error between the receivers centre frequency and the centre frequency of the transmitted packet. The frequency difference is shown
for each packet and an average over 10 received packets reported. Any transmitter program can be used to give this program something to listen to, including example program '3\_LoRa\_Transmitter'.
#### 17\_Sensor\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Sensor folder)
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 micro controller 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 Atmel watchdog timer is a viable option for a very low current sensor node. A bare bones ATmega328P with regulator and LoRa device has a sleep current of 6.6uA, add the LoRa devices and BME280 sensor module and the average sleep current only rises to 6.8uA.
One of these transmitter programs is running on a long term test with a 175mAh battery, to see how long the battery actually lasts.
#### 18\_Sensor\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Sensor folder)
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\_Transmitter' 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 the program starts, the LoRa device is set-up to set the DIO0 pin high when a packet is received, the Atmel processor is then put to sleep and will wake up when a packet is received. When a packet is received, its printed and assuming the packet is validated, the sensor results are printed to the serial monitor and screen. Between readings the sensor transmitter is put to sleep in units of 8 seconds using the Atmel
processor internal watchdog.
For the sensor data to be accepted as valid the flowing 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 that's 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.
With a standard Arduino Pro Mini and SSD1306 display the current consumption was 20.25mA with the display and 16.6mA without the display.
#### 20\_LoRa\_Link\_Test\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
The program is a matching receiver program for the '10\_LoRa\_Link\_Test\_TX'. The packets received are displayed on the serial monitor and analysed to extract the packet data which indicates the power used to send the packet. A count is kept of the numbers of each power setting received. When the transmitter sends the test mode packet at the beginning of the sequence (displayed as 999) the running totals of the powers received are printed. Thus you can quickly see at what transmit power levels the reception fails.
#### 21\_On\_Off\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Remote Control folder)
This program is a remote control transmitter. When one of four switches are made (shorted to ground) a packet is transmitted with single byte indicating the state of Switch0 as bit 0, Switch1 as bit 1 and Switch2 as bit 2. To prevent false triggering at the receiver the packet contains a
32 bit number called the TXIdentity which in this example is set to 1234554321. The receiver will only act on, change the state of the outputs, if the identity set in the receiver matches that of the transmitter. The chance of a false trigger is fairly remote.
Between switch presses the LoRa device and Atmel micro controller are put to sleep. A switch press wakes up the processor from sleep, the switches are read and a packet sent. On a 'bare bones' Arduino set-up the transmitter has a sleep current of approx 2.2uA, so it's ideal for a battery powered remote control with a potential range of many kilometres.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
#### 22\_On\_Off\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Remote Control folder)
This program is a remote control receiver. When a packet is received an 8 bit byte (SwitchByte) is read and the four outputs (defined in Settings.h) are toggled according to the bits set in this byte. If the Switch1 byte has bit 0 cleared, then OUTPUT0 is toggled. If the Switch1 byte has bit 1 cleared, then OUTPUT1 is toggled. If the Switch1 byte has bit 2 cleared, then OUTPUT2 is toggled.
To prevent false triggering at the receiver the packet also contains a 32 bit number called the TXIdentity which in this example is set to 1234554321. The receiver will only act on, change the state of the outputs, if the identity set in the receiver matches that of the transmitter. The chance of a false trigger is fairly remote.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
#### 23\_GPS\_Tracker\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Tracker folder)
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 start-up 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 likely 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, if the GPS module being used has this feature. To use the option change the define in the Settings.h file; '#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic levels.
#### 24\_GPS\_Tracker\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Tracker folder)
This program is an basic receiver for the '23\_Simple\_GPS\_Tracker\_Transmitter' program.
The program reads the received packet from the tracker transmitter and displays the results on the serial monitor. The LoRa and frequency settings provided in the Settings.h file must match those used by the transmitter.
The program receives direct from the LoRa devices internal buffer.
#### 25\_GPS\_Tracker\_Receiver\_with\_Display\_and\_GPS &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Tracker folder)
This program is an example of a basic portable GPS tracker receiver. The program receives the location packets from the remote tracker and displays them on an OLED display. The program also reads a local 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 received information is printed to screen in this order top to bottom;
Latitude, Longitude, Altitude, HDOP, GPS Fixtime, Tracker battery mV, Number of received packets, Distance and direction to tracker, if local GPS fix. In addition if there is a recent tracker transmitter GPS fix a 'T' is shown on line 0 right of screen and if there is a recent local (receiver) GPS fix a 'R' is displayed line 1 right of screen.
The received information is printed to the Serial Monitor as CSV data in this order;
Packet Address information, Latitude, Longitude, Altitude, Satellites in use, HDOP, TX status byte, GPS Fixtime, Tracker battery mV, Number of received packets, Distance and direction to tracker, if local GPS fix.
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 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.
#### 26\_GPS\_Echo &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This is a simple program to test a GPS. It reads characters from the GPS using software serial and sends them (echoes) to the IDE serial monitor. If your ever having problems with a GPS (or just think you are) use this program first.
If you get no data displayed on the serial monitor, the most likely cause is that you have the receive data pin into the Arduino (RX) pin connected incorrectly.
If the data displayed on the serial terminal appears to be random text with odd symbols its very likely you have the GPS serial baud rate set incorrectly.
Note that not all pins on all Arduinos will work with software serial, see here;
https://www.arduino.cc/en/Reference/softwareSerial
Serial monitor baud rate is set at 115200.
#### 28\_GPS\_Checker &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This program is a portable GPS checker and display. At start-up the program starts checking the data coming from the GPS for a valid fix. It checks for 5 seconds and if there is no fix, prints a message on the serial monitor. During this time the data coming from the GPS is copied to the serial monitor also.
When the program detects that the GPS has a fix, it prints the Latitude, Longitude, Altitude, Number of satellites in use and the HDOP value to the serial monitor.
Serial monitor baud rate is set at 115200, GPS baud rate to 9600, both are configured in setup().
#### 29\_GPS\_Checker\_With\_Display &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This program is a GPS checker with a display output. It uses an SSD1306 or SH1106 128x64 I2C OLED display. At start-up the program starts checking the data coming from the GPS for a valid fix. It reads the GPS for 5 seconds and if there is no fix, prints a message on the serial monitor and updates the seconds without a fix on the display. During this time the data coming from the GPS is copied to the serial monitor also.
When the program detects that the GPS has a fix, it prints the Latitude, Longitude, Altitude, Number of satellites in use, the HDOP value, time and date to the serial monitor. If the I2C OLED display is attached that is updated as well. Display is assumed to be on I2C address 0x3C.
#### 30\_I2C\_Scanner &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
The program scans the I2C bus and displays the addresses of any devices found. Useful first check when using I2C devices.
#### 31\_SSD1306\_OLED\_Checker &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
This program is a simple test program for the SSD1306 and SH1106 OLEDs. The program prints a short message on each line, pauses, clears the screen, and starts again.
OLED address is defined as 0x3C.
#### 33\_LoRa\_RSSI\_Checker\_With\_Display &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
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 {packet contents} CRC,3882,RSSI,-69dBm,SNR,10dB,Length,19,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
A summary of the packet reception is sent to the OLED display as well, useful for portable applications.
#### 34\_ATmel\_Sleep\_with\_Watchdog\_Wakeup &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This program tests the sleep mode of an Atmel ATMega328P processor.
At power up the flashes an LED 4 times, then turns on the LED for 5 seconds. Then the processor is put to sleep for 8 seconds. On wakeup the LED flashes twice, then is on for 5 seconds and the board goes to sleep again. And the sequence repeats.
Sleep current for a 'bare bones' ATmega328 with a MCP1700 regulator @ 3.3V and using an external event such as a switch to wakeup from sleep should be around 2uA. Using the watchdog timer to wakeup raises the deep sleep current to circa 6.2uA.
#### 35\_Remote\_Control\_Servo\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Remote Control folder)
This is a remote control transmitter that uses a LoRa link to transmit the positions from a simple joystick to a remote receiver. The receiver uses the sent joystick positions to adjust the positions of servos. The positions of the joysticks potentiometers on the transmitter are read with the analogueRead() function.
If the joystick has a switch, often made by pressing on the joystick, then this can be used to remote control an output on the receiver. The switch is read by an interrupt, the interrupt routine sets a flag byte which is read in loop().
The program is intended as a proof of concept demonstration of how to remote control servos, the program is not designed as a practical remote control device for RC model cars for instance.
It would be straight forward to make the transmitter program send packets continuously, but in most places in the world that would break a normal limitation of 10% duty cycle for unlicensed use. Therefore the program was designed to only transmit at a 10% duty cycle. Thus the fastest (lowest air time) packets are used, spreading factor 6 at a bandwidth of 500khz. This results in an air time for the 5 byte control packet of around 4mS, so there are around 25 sent per second.
To have the transmitter program print out the values read from the joystick, comment in the line;
//#define DEBUG
Which is just above the loop() function. With the DEBUG enabled the transmission rate, the rate at which the control packets are transmitted will be slowed down.
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a 'TXidentity' number, valid values are 0 - 255. The receiver must be set-up with the matching identity number or the received packets will be ignored.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings are not necessarily optimised for long range.
#### 36\_Remote\_Control\_Servo\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Remote Control folder)
This is a remote control receiver that uses a LoRa link to control the positions of servos sent from a remote transmitter.
If the transmitter joystick has a switch, often made by pressing on the joystick, then this can be used to remote control an output on the receiver.
The program is intended as a proof of concept demonstration of how to remote control servos, the program is not designed as a practical remote control device for RC model cars for instance.
It would be straight forward to make the transmitter program send packets continuously, but in most places in the world that would break a normal limitation of 10% duty cycle for unlicensed use. Therefore the program was designed to only transmit at a 10% duty cycle. Thus the fastest (lowest air time) packets are used, spreading factor 6 at a bandwidth of 500khz. This results in an air time for the 5 byte control packet of around 4mS, so there are around 25 sent per second.
To have the receiver program print out the joystick values (0-255) read from the received packet, comment in the line;
//#define DEBUG
Which is just above the loop() function. With the DEBUG enabled then there is a possibility that some transmitted packets will be missed. With the DEBUG line enabled to servos should also sweep to and fro 3 times at program start-up.
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a 'TXidentity' number, valid values are 0 - 255. The receiver must be set-up with the matching RXIdentity number in Settings.h or the received packets will be ignored.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings are not necessarily optimised for long range.
#### 37\_Servo\_Sweep\_Tester &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This program sweeps two servos from one end of their travel to the other. Useful to check servos are connected correctly and working.
#### 38\_lora\_Relay &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Tracker folder)
This program will receive a lora packet and relay (re-transmit) it. The receiving and transmitting can use different frequencies and lora settings. The receiving and transmitting settings are in the 'Settings.h' file. For an example of it's use see this report;
How to Search 500 Square Kilometres in 10 minutes.pdf in the libraries 'Test_Reports' folder.
#### 40\_LoRa\_Transmitter\_ImplicitPacket &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Implicit folder)
This is an example of the use of implicit or fixed length LoRa packets.
Implicit packets have no header so both transmitter and receiver need to be programmed with the packet length in use. The use of spreading factor 6 requires implicit packets and together with a bandwidth of 500khz, leads to the shortest possible and lowest air time packets.
This example sends a buffer that is 23 characters long and that length must be defined in Settings.h as the constant 'PacketLength'.
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 lora device need to be defined in the 'Settings.h' file also.
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, '41\_LoRa\_Receiver\_ImplicitPackets' 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,8mS PacketsSent,1
#### 41\_LoRa\_Receiver\_ImplicitPacket &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Implicit folder)
This is an example of the use of implicit or fixed length LoRa packets. Implicit packets have no header so both transmitter and receiver need to be programmed with the packet length in use. The use of spreading factor 6 requires implicit packets and together with a bandwidth of 500khz, leads to the shortest possible and lowest air time packets. The program listens for incoming packets using the LoRa settings in the 'Settings.h'.
This example receives a buffer that is 19 characters long and that length must be defined in Settings.h as the constant 'PacketLength'.
The pins to access the lora device need to be defined in the 'Settings.h' file also.
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 {packet contents} CRC,3882,RSSI,-69dBm,SNR,10dB,Length,19,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
#### 42\_WiFi\_Scanner\_Display\_ESP32 &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware Checks\ESP32 folder)
When the ESP32 turns on the WiFi function, there is a short high current pulse that can cause the ESP32 brownout detect to operate.
This test program at startup flashes an LED, leaves it on and then starts the WiFi. If the Wifi initiates a brownout, you will see the LED flash again. The LED stays on when scanning, the program reports the networks found to the serial console and displays them on an attached SSD1306 OLED.
Thus if you see the LED continually doing short bursts of flashing the turn on off the WiFi is causing the ESP32 to reset. There will also be a message on the serial monitor that the brownout detector operated.
#### 43\_SD\_Card\_Test\_ESP32 &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware Checks\ESP32 folder)
This test program has been written to check that a connected SD card adapter, Micro or standard, is functional. To use the program first copy the file (in this programs directory) called testfile.txt to the root directory of the SD card.
When the program runs it will attempt to open 'testfile.txt' and spool the contents to the Arduino IDE serial monitor. The testfile is part of the source code for the Apollo 11 Lunar Lander navigation and guidance computer. There are LED flashes at power up or reset, then at start of every loop of the test. The LED is on whilst the testfile is being read. If the LED flashes very rapidly then there is a problem accessing the SD card.
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.
#### 44\_SD\_Card\_Test\_With\_FS\_ESP322 &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware Checks\ESP32 folder)
This test program has been written to check that a connected SD card adapter, Micro or standard, is functional with the FS functions. To use the program first copy the file (in this programs directory) called testfile.txt to the root directory of the SD card.
When the program runs it will attempt to open 'testfile.txt' and spool the contents to the Arduino IDE serial monitor. The testfile is part of the source code for the Apollo 11 Lunar Lander navigation and guidance computer. There are LED flashes at power up or reset, then at start of every loop of the test. The LED is on whilst the testfile is being read. If the LED flashes very rapidly then there is a problem accessing the SD card.
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.
#### 45\_Battery\_Voltage\_Read\_Test &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
This test program has been written to check that hardware for reading the battery voltage has been assembled correctly such that it is funtional. The value defined as 'ADMultiplier' in settings.h is used to adjust the value read from the 91K\11K resistor divider and convert into mV.
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.
#### 47\_DeepSleep\_Timed\_Wakeup\_ESP32 &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks\ESP32 folder)
This program flashes a LED connected to the pin defined by LED1, and puts the ESP32 to deep_sleep for a period determined by the TIME_TO_SLEEP variable (in seconds).
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.
Current in deep_sleep for a bare bones ESP32 with regulator and no other devices was 27uA.
#### 48\_DS18B20\_Test &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Hardware_Checks folder)
The program reads a single DS18B20 temperature sensor and prints the result to the serial monitor.
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 then these devices are assumed to be powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
#### 50\_LightSleep\_Timed\_Wakeup\_ESP32 &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (ESP32 folder)
The program flashes a LED connected to the pin defined by LED1, and puts the ESP32 to light_sleep for a period determined by TIME_TO_SLEEP (in seconds).
The program also has the option of using a logic pin to control the power to the lora device, SD card and DS18B20 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.
#### 51\_DeepSleep\_Switch\_Wakeup\_ESP32 &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (ESP32 folder)
The program flashes a LED connected to the pin defined by LED1, and puts the ESP32 to deep_sleep. Pressing BOOT switch should wake up the ESP32 from sleep.
Only the specific RTC IO pins can be used as a source for external wakeup.
These are pins: 0,2,4,12-15,25-27,32-39.
Current in deep sleep for a bare bones ESP32 with regulator and no other devices was 27uA.
#### 52\_FLRC\_Transmitter &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (SX128X\Examples\Basics folder)
This is a test transmitter for the Fast Long Range Communication (FLRC) mode introduced in the SX128X devices. A packet containing ASCII text is sent according to the frequency and FLRC settings specified in the 'Settings.h' file. The pins to access the SX128X device need to be defined
in the 'Settings.h' file also.
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, '53_FLRC_Receiver' can be used to check the packets are being sent correctly, the frequency and FLRC 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
#### 53\_FLRC\_Receiver &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (SX128X_Examples\Basics folder)
This is a test receiver for the Fast Long Range Communication (FLRC) mode introduced in the SX128X devices. The program listens for incoming packets using the FLRC settings in the 'Settings.h' file. The pins to access the SX128X device need to be defined in the 'Settings.h' file also.
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;
3s Hello World 1234567890*,CRC,DAAB,RSSI,-73dB,Length,23,Packets,1,Errors,0,IRQreg,6
If there is a packet error it might look like this, which is showing a CRC error,
6s PacketError,RSSI,-103dB,Length,119,Packets,3,Errors,1,IRQreg,46,IRQ\_RX\_DONE,IRQ\_SYNCWORD\_VALID,IRQ\_CRC\_ERROR
#### 58\_FM\_Tone &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
Transmits a FM tone using the LoRa device that can be picked up on an FM UHF handheld receiver. The tones are not true FM but the UHF receiver does not know that.
#### 59\_Play\_Star\_Wars\_Tune &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Silly folder)
A silly program really, but does demonstrate that you can shift a carrier generated by the LoRa device in FSK mode fast enough to play audio tones that can be picked up on an FM UHF handheld receiver. The tones are not true FM but the receiver does not know that.
#### 60\_LoRa\_Packet\_Logger\_Receiver\_SD &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Diagnostics and Test folder)
The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout and save to SD card of the valid packets received in HEX format. Thus the program can be used to receive and record non-ASCII packets. The LED will flash for each packet received and the buzzer will sound, if fitted. The measured frequency difference between the frequency used by the transmitter and the frequency used by the receiver is shown. If this frequency difference gets to 25% of the set LoRa bandwidth, packet reception will fail. The displayed error can be reduced by using the 'offset' setting in the 'Settings.h' file.
There will be a limit to how fast the logger can receive packets, mainly caused by the delay in writing to SD card, so at high packet rates, packets will be lost.
#### 103\_LoRa\_Transmitter\_Detailed\_Setup &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This is a program that demonstrates the detailed setup of a LoRa test transmitter. 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 lora device need to be defined in the 'Settings.h' file also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with the transmit power used, the packet length and the CRC of the packet. The matching receive program, '104\_LoRa\_Receiver' 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 transmitter and receiver programs. Sample Serial Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 CRC,DAAB TransmitTime,64mS PacketsSent,2
Serial monitor baud rate is set at 9600
#### 104\_LoRa\_Receiver\_Detailed\_Setup &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; (Basics folder)
This is a program that demonstrates the detailed setup of a LoRa test receiver. The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout on the Arduino IDE Serial Monitor of the valid packets received, the packet is assumed to be in ASCII printable text, if it's 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;
7s Hello World 1234567890*,CRC,DAAB,RSSI,-52dBm,SNR,9dB,Length,23,Packets,5,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
968s PacketError,RSSI,-87dBm,SNR,-11dB,Length,23,Packets,613,Errors,2,IRQreg,70,IRQ\_HEADER\_VALID,IRQ\_CRC\_ERROR,IRQ\_RX\_DONE
Serial monitor baud rate is set at 9600.

View File

@@ -0,0 +1,188 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 demonstrates the detailed setup of a LoRa test transmitter.
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 lora device need to be defined in the 'Settings.h' file also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used, the packet length and the CRC of the packet. The matching receive program,
'104_LoRa_Receiver' 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 transmitter and receiver programs. Sample Serial
Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 CRC,DAAB TransmitTime,64mS PacketsSent,2
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT 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 receiver
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, 10000, 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 transmitted 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
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("103_LoRa_Transmitter_Detailed_Setup 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, RFBUSY, DIO1, DIO2, DIO3, RX_EN, TX_EN, SW, 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);
LT.setRegulatorMode(USE_DCDC);
LT.setPaConfig(0x04, PAAUTO, LORA_DEVICE);
LT.setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V);
LT.calibrateDevice(ALLDevices); //is required after setting TCXO
LT.calibrateImage(Frequency);
LT.setDIO2AsRfSwitchCtrl();
LT.setPacketType(PACKET_TYPE_LORA);
LT.setRfFrequency(Frequency, Offset);
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, Optimisation);
LT.setBufferBaseAddress(0, 0);
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);
LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1
LT.setHighSensitivity(); //set for maximum gain
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);
//***************************************************************************************************
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();
}

View File

@@ -0,0 +1,46 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO2,
//DIO3, BUZZER are not used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define RX_EN -1 //pin for RX enable, used on some SX126X devices, set to -1 if not used
#define TX_EN -1 //pin for TX enable, used on some SX126X devices, set to -1 if not used
#define SW -1 //SW pin on some Dorji LoRa devices, used to power antenna switch, set to -1 if not used
#define LED1 8 //on board LED, high for on
#define LORA_DEVICE DEVICE_SX1262 //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
//for SX1262, SX1268 power range is +22dBm to -9dBm
//for SX1261, power range is +15dBm t0 -9dBm
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets

View File

@@ -0,0 +1,254 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 demonstrates the detailed setup of a LoRa test receiver.
The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins
to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout on the Arduino IDE Serial Monitor of the valid packets received, the packet is
assumed to be in ASCII printable text, if it's 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;
7s Hello World 1234567890*,CRC,DAAB,RSSI,-52dBm,SNR,9dB,Length,23,Packets,5,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
968s PacketError,RSSI,-87dBm,SNR,-11dB,Length,23,Packets,613,Errors,2,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT 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 (SNR) 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 is 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 device 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
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("104_LoRa_Receiver_Detailed_Setup Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
SPI.begin();
//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, RFBUSY, DIO1, DIO2, DIO3, RX_EN, TX_EN, SW, 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);
LT.setRegulatorMode(USE_DCDC);
LT.setPaConfig(0x04, PAAUTO, LORA_DEVICE);
LT.setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V);
LT.calibrateDevice(ALLDevices); //is required after setting TCXO
LT.calibrateImage(Frequency);
LT.setDIO2AsRfSwitchCtrl();
LT.setPacketType(PACKET_TYPE_LORA);
LT.setRfFrequency(Frequency, Offset);
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, Optimisation);
LT.setBufferBaseAddress(0, 0);
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);
LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1
LT.setHighSensitivity(); //set for maximum gain
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);
//***************************************************************************************************
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();
}

View File

@@ -0,0 +1,49 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO2,
//DIO3, BUZZER are not used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define RX_EN -1 //pin for RX enable, used on some SX126X devices, set to -1 if not used
#define TX_EN -1 //pin for TX enable, used on some SX126X devices, set to -1 if not used
#define SW -1 //SW pin on some Dorji LoRa devices, used to power antenna switch, set to -1 if not used
#define LED1 8 //on board LED, high for on
#define BUZZER 4 //pin for buzzer, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,145 @@
/*******************************************************************************************************
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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program demonstrates the transmitting of a structure as a LoRa packet. The
contents of the structure are the same as in the '8_LoRa_LowMemory_TX' program. The packet sent is
typical of what might be sent from a GPS tracker.
The structure type is defined as trackerPacket and an instance called location1 is created. The struture
which includes a character array (text) is filled with values and transmitted.
The matching receiving program '15_LoRa_RX_Structure' can be used to receive and display the packet,
though the program '9_LoRa_LowMemory_RX' should receive it as well, since the contents are the same.
Note that the structure definition and variable order (including the buffer size) used in the transmitter
need to match those used in the receiver.
The contents of the packet transmitted should be;
"tracker1" (buffer) - trackerID
1+ (uint32_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Good luck.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
SX126XLT LT;
uint32_t TXpacketCount = 1;
uint32_t startmS, endmS;
struct trackerPacket
{
uint8_t trackerID[13];
uint32_t txcount;
float latitude;
float longitude;
uint16_t altitude;
uint8_t satellites;
uint16_t voltage;
int8_t temperature;
};
struct trackerPacket location1; //define an instance called location1 of the structure trackerPacket
void loop()
{
//fill the defined structure with values
uint8_t buff[] = "tracker1"; //create the contents to be of location1.trackerID
memcpy (&location1.trackerID, &buff, sizeof(buff)); //copy the contents of buff[] into the structure
location1.txcount = TXpacketCount;
location1.latitude = 51.23456;
location1.longitude = -3.12345;
location1.altitude = 199;
location1.satellites = 8;
location1.voltage = 3999;
location1.temperature = -9;
digitalWrite(LED1, HIGH);
startmS = millis();
if (LT.transmit((uint8_t *) &location1, sizeof(location1), 0, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0
{
endmS = millis();
digitalWrite(LED1, LOW);
TXpacketCount++;
Serial.print(TXpacketCount);
Serial.print(F(" "));
Serial.print(sizeof(location1));
Serial.print(F(" Bytes Sent"));
Serial.print(F(" "));
Serial.print(endmS - startmS);
Serial.print(F("mS"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
digitalWrite(LED1, LOW);
Serial.println();
delay(packet_delay);
}
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);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
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("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/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 my own boards, the Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO2,
//DIO3, 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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,194 @@
/*******************************************************************************************************
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.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program demonstrates the receiving of a structure as a LoRa packet. The packet
sent is typical of what might be sent from a GPS tracker.
The structure type is defined as trackerPacket and an instance called location1 is created. The structure
includes a character array (text).
The matching receiving program is '15_LoRa_RX_Structure' can be used to receive and display the packet,
though the program '9_LoRa_LowMemory_RX' should receive it as well, since the packet contents are the same.
Not that the structure definition and variable order (including the buffer size) used in the transmitter
need to match those used in the receiver. Good luck.
The contents of the packet received, and printed to serial monitor, should be;
"tracker1" (buffer) - trackerID
1+ (uint32_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
SX126XLT LT;
uint8_t RXPacketL; //stores length of packet received
uint32_t RXpacketCount; //count of received packets
int8_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
uint32_t errors; //count of packet errors
struct trackerPacket
{
uint8_t trackerID[13];
uint32_t txcount;
float latitude;
float longitude;
uint16_t altitude;
uint8_t satellites;
uint16_t voltage;
int8_t temperature;
};
struct trackerPacket location1; //define an instance called location1 of the structure trackerPacket
void loop()
{
RXPacketL = LT.receive( (uint8_t *) &location1, sizeof(location1), 0, WAIT_RX); //wait for a packet to arrive with no timeout
digitalWrite(LED1, HIGH); //something has happened, what I wonder ?
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
void printlocation1()
{
uint8_t buff[13]; //define a buffer to receive a copy from the structure
memcpy (&buff, &location1.trackerID, sizeof(buff)); //copy the contents of buffer in struture to buff[]
//now print the contents of the structure
Serial.print((char*) buff); //cast to a char type for printing
Serial.print(F(","));
Serial.print(location1.txcount);
Serial.print(F(","));
Serial.print(location1.latitude, 5);
Serial.print(F(","));
Serial.print(location1.longitude, 5);
Serial.print(F(","));
Serial.print(location1.altitude);
Serial.print(F("m,"));
Serial.print(location1.satellites);
Serial.print(F("sats,"));
Serial.print(location1.voltage);
Serial.print(F("mV,"));
Serial.print(location1.temperature);
Serial.print(F("c "));
}
void packet_is_OK()
{
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(" "));
printlocation1();
printpacketDetails();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
errors++;
Serial.print(F("PacketError"));
printpacketDetails();
Serial.print(F("IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printpacketDetails()
{
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB"));
}
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(void)
{
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);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.print(F("Receiver ready"));
Serial.println();
Serial.println();
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/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 my own boards, the Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO2,
//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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,69 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/02/20
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 pin 13 LED,
fitted to some Arduinos is blinked as well. 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 8 //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);
digitalWrite(13, HIGH);
delay(100);
digitalWrite(LED1, LOW);
digitalWrite(13, 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
digitalWrite(13, HIGH); //Arduino board LED on
delay(delaymS);
digitalWrite(LED1, LOW); //LED off
digitalWrite(13, LOW); //Arduino board LED off
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
pinMode(13, OUTPUT); //setup pin as output for some Arduino boards that include an LED on pin 13
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 Starting"));
}

View File

@@ -0,0 +1,402 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/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 stand alone, it is not necessary to install the SX12XX-LoRa library
to use it. This test program is for the SX126X LoRa devices.
The program checks that a SX126X 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, SX1261, SX1262,
or SX1268 must be specified also.
Typical printout;
2_Register_Test Starting
Reset device
LoRa Device found
Reset device
Registers at reset
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x800 00 00 00 00 01 07 20 1E 00 10 19 04 0F FF 0F FF
0x810 10 00 10 00 10 00 10 00 00 00 00 00 00 00 00 00
0x820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x880 03 00 00 5F 10 08 00 00 08 05 00 39 30 00 00 0C
0x890 00 00 00 00 00 0F 0A 07 10 00 26 01 01 53 06 07
0x8A0 10 00 AA 20 5A 04 F0 00 56 56 54 43 94 20 40 00
0x8B0 00 83 11 00 01 04 0A 4C 14 0A 2F 01 6B FF FF 00
0x8C0 00 A0 20 00 00 00 AC 00 1C 00 00 AB 05 30 00 00
0x8D0 0C 14 14 40 06 00 00 10 C8 00 00 00 00 00 31 39
0x8E0 90 39 0C 04 40 20 1C 18 03 00 05 04 03 02 01 01
0x8F0 00 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00
0x900 30 00 00 00 00 00 00 00 00 00 00 00 24 04 47 04
0x910 14 12 12 04 00 03 0A 00 15 35 09 00 02 1F 5F 08
0x920 01 04 05 00 00 00 00 00 00 00 00 00 00 00 00 00
0x930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x940 00 07 00 03 02 00 10 0E 0D 0C 03 04 03 70 0C 00
0x950 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00
0x960 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x970 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x980 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x990 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Frequency at reset 915000000
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x880 03 00 00 5F 10 08 00 00 08 05 00 39 30 00 00 0C
Change Frequency 434100000
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x880 03 00 00 5F 10 08 00 00 08 05 00 1B 21 99 A0 0C
Changed Frequency 434100000
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
const uint16_t REG_RFFrequency31_24 = 0x088B;
const uint16_t REG_RFFrequency23_16 = 0x088C;
const uint16_t REG_RFFrequency15_8 = 0x088D;
const uint16_t REG_RFFrequency7_0 = 0x088E;
const uint8_t RADIO_WRITE_REGISTER = 0x0D;
const uint8_t RADIO_READ_REGISTER = 0x1D;
const uint8_t RADIO_SET_RFFREQUENCY = 0x86;
const uint8_t DEVICE_SX1261 = 0x01;
const uint8_t DEVICE_SX1262 = 0x00;
const uint8_t DEVICE_SX1268 = 0x02;
//********* Setup hardware definitions here ! *****************
//These are the pin definitions for one of the Tracker boards, 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 an Arduino Pro Mini are
//SCK pin 13, MISO pin 12, and MOSI pin 11.
#define NSS 10 //SX126X device select
#define NRESET 9 //SX126X reset pin
#define RFBUSY 7 //SX126X busy pin
#define LED1 8 //for on board LED, put high for on
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //define the device, DEVICE_SX1261, DEVICE_SX1262 or DEVICE_SX1268
//**************************************************************/
#include <SPI.h>
void setup()
{
Serial.begin(9600);
Serial.println(F("2_Register_Test 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 DIO1, DIO2 and DIO3 are not used in this example so are set to -1
if (begin(NSS, NRESET, RFBUSY, -1, -1, -1, SW, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
}
else
{
Serial.println(F("No device responding"));
}
}
void loop()
{
uint32_t frequency;
resetDevice(LORA_DEVICE); //reset the device
Serial.println(F("Registers at reset")); //show the all registers following a reset
printRegisters(0x800, 0x9FF);
Serial.println();
Serial.println();
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Frequency at reset "));
Serial.println(frequency);
printRegisters(0x0880, 0x088F); //show the registers before the frequency change
setRfFrequency(434100000, 0); //change the frequency at reset, in hertz
frequency = getFreqInt(); //read back the changed frequency
Serial.print(F("Change Frequency "));
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
printRegisters(0x0880, 0x088F); //show the registers after frequency change
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Changed Frequency "));
Serial.println(frequency);
Serial.println();
Serial.println();
delay(5000);
}
void readRegisters(uint16_t address, uint8_t *buffer, uint16_t size)
{
uint16_t index;
uint8_t addr_l, addr_h;
addr_h = address >> 8;
addr_l = address & 0x00FF;
checkBusy();
digitalWrite(NSS, LOW);
SPI.transfer(RADIO_READ_REGISTER);
SPI.transfer(addr_h); //MSB
SPI.transfer(addr_l); //LSB
SPI.transfer(0xFF);
for (index = 0; index < size; index++)
{
*(buffer + index) = SPI.transfer(0xFF);
}
digitalWrite(NSS, HIGH);
checkBusy();
}
uint8_t readRegister(uint16_t address)
{
uint8_t data;
readRegisters(address, &data, 1);
return data;
}
void writeRegisters(uint16_t address, uint8_t *buffer, uint16_t size)
{
uint8_t addr_l, addr_h;
uint8_t i;
addr_l = address & 0xff;
addr_h = address >> 8;
checkBusy();
digitalWrite(NSS, LOW);
SPI.transfer(RADIO_WRITE_REGISTER);
SPI.transfer(addr_h); //MSB
SPI.transfer(addr_l); //LSB
for (i = 0; i < size; i++)
{
SPI.transfer(buffer[i]);
}
digitalWrite(NSS, HIGH);
checkBusy();
}
void writeRegister(uint16_t address, uint8_t value)
{
writeRegisters( address, &value, 1 );
}
uint32_t getFreqInt()
{
//get the current set device frequency from registers, return as long integer
uint8_t MsbH, MsbL, Mid, Lsb;
uint32_t uinttemp;
float floattemp;
MsbH = readRegister(REG_RFFrequency31_24);
MsbL = readRegister(REG_RFFrequency23_16);
Mid = readRegister(REG_RFFrequency15_8);
Lsb = readRegister(REG_RFFrequency7_0);
floattemp = ( (MsbH * 0x1000000ul) + (MsbL * 0x10000ul) + (Mid * 0x100ul) + Lsb);
floattemp = ((floattemp * 0.95367431640625) / 1000000ul);
uinttemp = (uint32_t)(floattemp * 1000000);
return uinttemp;
}
void printRegisters(uint16_t Start, uint16_t End)
{
//prints the contents of SX126x 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;) //32 lines
{
Serial.print(F("0x"));
Serial.print((Loopv1), HEX); //print the register number
Serial.print(F(" "));
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
{
RegData = readRegister(Loopv1);
if (RegData < 0x10)
{
Serial.print(F("0"));
}
Serial.print(RegData, HEX); //print the register number
Serial.print(F(" "));
Loopv1++;
}
Serial.println();
}
}
void setRfFrequency( uint32_t frequency, int32_t offset )
{
//Note RF_Freq = freq_reg*32M/(2^25)-----> freq_reg = (RF_Freq * (2^25))/32
uint8_t Rf_Freq[4];
frequency = frequency + offset;
frequency = ( uint32_t )( ( double )frequency / ( double )0.95367431640625 );
checkBusy();
Rf_Freq[0] = (frequency >> 24) & 0xFF; //MSB
Rf_Freq[1] = (frequency >> 16) & 0xFF;
Rf_Freq[2] = (frequency >> 8) & 0xFF;
Rf_Freq[3] = frequency & 0xFF;//LSB
writeCommand(RADIO_SET_RFFREQUENCY, Rf_Freq, 4);
}
void checkBusy()
{
uint8_t busy_timeout_cnt;
busy_timeout_cnt = 0;
while (digitalRead(RFBUSY))
{
delay(1);
busy_timeout_cnt++;
if (busy_timeout_cnt > 10) //wait 10mS for busy to complete
{
busy_timeout_cnt = 0;
Serial.println(F("ERROR - Busy Timeout!"));
break;
}
}
}
void resetDevice(uint8_t device)
{
if ( (device == DEVICE_SX1261) | (device == DEVICE_SX1262) | (device == DEVICE_SX1268) )
{
Serial.println(F("Reset device"));
delay(10);
digitalWrite(NRESET, LOW);
delay(2);
digitalWrite(NRESET, HIGH);
delay(25);
checkBusy();
}
}
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinSW, uint8_t device)
{
pinMode(pinNSS, OUTPUT);
digitalWrite(pinNSS, HIGH);
pinMode(pinNRESET, OUTPUT);
digitalWrite(pinNRESET, LOW);
pinMode(pinRFBUSY, INPUT);
if (pinDIO1 >= 0)
{
pinMode( pinDIO1, INPUT);
}
if (pinDIO2 >= 0)
{
pinMode(pinDIO2, INPUT);
}
if (pinDIO3 >= 0)
{
pinMode(pinDIO3, INPUT);
}
if (pinSW >= 0)
{
pinMode(pinSW, OUTPUT); //Dorji devices have an SW pin that needs to be set high to power antenna switch
digitalWrite(pinSW, HIGH);
}
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(0x88e); //low byte of frequency setting
writeRegister(0x88e, (Regdata1 + 1));
Regdata2 = readRegister(0x88e); //read changed value back
writeRegister(0x88e, Regdata1); //restore register to original value
if (Regdata2 == (Regdata1 + 1))
{
return true;
}
else
{
return false;
}
}
void writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size)
{
uint8_t index;
checkBusy();
digitalWrite(NSS, LOW);
SPI.transfer(Opcode);
for (index = 0; index < size; index++)
{
SPI.transfer(buffer[index]);
}
digitalWrite(NSS, HIGH);
checkBusy();
}

View File

@@ -0,0 +1,123 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 minimum setup LoRa test transmitter. A packet containing the ASCII text
"Hello World 1234567890" is sent using the frequency and LoRa settings specified in the LT.setupLoRa()
command. The pins to access the lora device need to be defined at the top of the program also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used and the packet length. The matching receiver program, '4_LoRa_Receiver' can be used
to check the packets are being sent correctly, the frequency and LoRa settings (in the LT.setupLoRa()
commands) must be the same for the transmitter and receiver programs. Sample Serial Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 PacketsSent,6
For an example of a more detailed configuration for a transmitter, see program 103_LoRa_Transmitter.
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 <SX126XLT.h> //include the appropriate library
SX126XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define SW 5 //SW pin on LoRa device, used to power antenna switch
#define LORA_DEVICE DEVICE_SX1262 //we need to define the device we are using
#define TXpower 10 //LoRa transmit power in dBm
uint8_t TXPacketL;
uint32_t TXPacketCount;
uint8_t buff[] = "Hello World 1234567890"; //the message to send
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("3_LoRa_Transmitter Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Transmitter ready"));
Serial.println();
}
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 receiver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
Serial.println();
delay(1000); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
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
}

View File

@@ -0,0 +1,170 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 minimum setup LoRa test receiver. The program listens for incoming packets
using the frequency and LoRa settings in the LT.setupLoRa() command. The pins to access the lora device
need to be defined at the top of the program also.
There is a printout on the Arduino IDE serial monitor of the valid packets received, the packet is assumed
to be in ASCII printable text, if it's not ASCII text characters from 0x20 to 0x7F, expect weird things to
happen on the Serial Monitor. Sample serial monitor output;
8s Hello World 1234567890*,RSSI,-44dBm,SNR,9dB,Length,23,Packets,7,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error;
137s PacketError,RSSI,-89dBm,SNR,-8dB,Length,23,Packets,37,Errors,2,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
If there are no packets received in a 10 second period then you should see a message like this;
112s RXTimeout
For an example of a more detailed configuration for a receiver, see program 104_LoRa_Receiver.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX126XLT.h> //include the appropriate library
SX126XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define SW 5 //SW pin on LoRa device, used to power antenna switch
#define LORA_DEVICE DEVICE_SX1262 //we need to define the device we are using
#define RXBUFFER_SIZE 32 //RX buffer size
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 (SNR) of received packet
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("4_LoRa_Receiver Starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
PacketSNR = LT.readPacketSNR(); //read the received packets SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error RXpacketL is 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
RXpacketCount++;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
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
}
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}

View File

@@ -0,0 +1,95 @@
/*******************************************************************************************************
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 - Transmits a FM tone using the LoRa device that can be picked up on an FM UHF
handheld receiver. The tones are not true FM but the UHF receiver does not know that.
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 <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT LT; //create a library class instance called LT
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.println(F("PlayTone> "));
Serial.println();
digitalWrite(LED1, HIGH);
LT.toneFM(1000, 1000, deviation, adjustfreq, TXpower);
digitalWrite(LED1, LOW);
delay(1000);
}
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
pinMode(4, OUTPUT);
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("58_FM_Tone 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, RFBUSY, DIO1, SW, 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("Tone Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,36 @@
/*******************************************************************************************************
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 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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,266 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 01/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 effectiveness of a LoRa link or its
attached antennas. Simulations of antenna performance are no substitute for real world tests and this
simple program allows both long distance link performance to be evaluated and antenna performance to be
compared.
The program sends short test packets that reduce in power by 1dBm at a time. The start power is defined
by start_power and the end power is defined by end_power (see Settings.h file). Once the end_power point
is reached, the program pauses a short while and starts the transmit sequence again at start_power.
The packet sent contains the power used to send the packet. By listening for the packets with the basic
LoRa receive program (4_LoRa_Receiver) you can see the reception results, which should look something
like this;
11s 1*T+05,CRC,80B8,RSSI,-73dBm,SNR,9dB,Length,6,Packets,9,Errors,0,IRQreg,50
12s 1*T+04,CRC,9099,RSSI,-74dBm,SNR,9dB,Length,6,Packets,10,Errors,0,IRQreg,50
14s 1*T+03,CRC,E07E,RSSI,-75dBm,SNR,9dB,Length,6,Packets,11,Errors,0,IRQreg,50
Above shows 3 packets received, the first at +05dBm (+05 in printout), the second at 4dBm (+04 in
printout) and the third at 3dBm (+03) in printout.
If it is arranged so that reception of packets fails halfway through the sequence by attenuating either the
transmitter (with an SMA attenuator for instance) or the receiver (by placing it in a tin perhaps) then
if you swap transmitter antennas you can see the dBm difference in reception, which will be the dBm difference
(gain) of the antenna.
To start the sequence a packet is sent with the number 999, when received it looks like this;
T*1999
This received packet could be used for the RX program to be able to print totals etc.
LoRa settings to use for the link test are specified in the 'Settings.h' file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX126XLT.h>
#include <ProgramLT_Definitions.h>
#include "Settings.h"
SX126XLT LT;
int8_t TestPower;
uint8_t TXPacketL;
void loop()
{
Serial.println(F("Start Test Sequence"));
Serial.print(TXpower);
Serial.print(F("dBm "));
Serial.print(F("Start Packet> "));
SendTest1ModePacket();
Serial.println();
for (TestPower = start_power; TestPower >= end_power; TestPower--)
{
Serial.print(TestPower);
Serial.print(F("dBm "));
Serial.print(F("Test Packet> "));
Serial.flush();
SendTestPacket(TestPower);
Serial.println();
delay(packet_delay);
}
Serial.println(F("Finished Test Sequence"));
Serial.println();
}
void SendTestPacket(int8_t lpower)
{
//build and send the test packet in addressed form, 3 bytes will be added to begining of packet
int8_t temppower;
uint8_t buff[3]; //the packet is built in this buffer
TXPacketL = sizeof(buff);
if (lpower < 0)
{
buff[0] = '-';
}
else
{
buff[0] = '+';
}
if (TestPower == 0)
{
buff[0] = ' ';
}
temppower = TestPower;
if (temppower < 0)
{
temppower = -temppower;
}
if (temppower > 19)
{
buff[1] = '2';
buff[2] = ((temppower - 20) + 0x30);
}
else if (temppower > 9)
{
buff[1] = '1';
buff[2] = ((temppower - 10) + 0x30);
}
else
{
buff[1] = '0';
buff[2] = (temppower + 0x30);
}
LT.printASCIIPacket(buff, sizeof(buff));
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitAddressed(buff, sizeof(buff), TestPacket, Broadcast, ThisNode, 5000, lpower, WAIT_TX);
digitalWrite(LED1, LOW);
if (TXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
}
void SendTest1ModePacket()
{
//used to allow an RX to recognise the start off the sequence and possibly print totals
uint8_t buff[3]; //the packet is built in this buffer
buff[0] = '9';
buff[1] = '9';
buff[2] = '9';
TXPacketL = sizeof(buff);
LT.printASCIIPacket(buff, sizeof(buff));
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitAddressed(buff, sizeof(buff), TestMode1, Broadcast, ThisNode, 5000, start_power, WAIT_TX);
delay(mode_delaymS); //longer delay, so that the start test sequence is obvious
digitalWrite(LED1, LOW);
if (TXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
}
void packet_is_OK()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
Serial.print(F(" "));
Serial.print(TXPacketL);
Serial.print(F(" Bytes SentOK"));
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
}
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();
delay(packet_delay); //change LED flash so packet error visible
delay(packet_delay);
digitalWrite(LED1, HIGH);
delay(packet_delay);
delay(packet_delay);
digitalWrite(LED1, LOW);
}
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(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("10_LoRa_Link_Test_Transmitter Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
Serial.println(F("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 operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,52 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 01/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 Easy Pro Mini,
//be sure to change the definitiosn to match your own setup. Some pins such as DIO2,
//DIO3 may not be in used by this sketch so they do not need to be connected and should
//be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define RX_EN -1 //pin for RX enable, used on some SX126X devices, set to -1 if not used
#define TX_EN -1 //pin for TX enable, used on some SX126X devices, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //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
//for SX1262, SX1268 power range is +22dBm to -9dBm
//for SX1261, power range is +15dBm t0 -9dBm
const int8_t TXpower = 10; //Transmit power used when sending packet starting test sequence
const int8_t start_power = 10; //link test starts at this transmit power
const int8_t end_power = -8; //and ends at this power
const uint8_t ThisNode = 'T'; //this identifies the node in transmissions
#define packet_delay 1000 //mS delay between packets
#define mode_delaymS 2000 //mS delay after sending start test sequence

View File

@@ -0,0 +1,223 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 01/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 - The program listens for incoming packets using the LoRa settings in the 'Settings.h'
file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout of the valid packets received in HEX format. Thus the program can be used to receive
and record non-ASCII packets. The LED will flash for each packet received and the buzzer will sound,
if fitted. The measured frequency difference between the frequency used by the transmitter and the
frequency used by the receiver is shown. If this frequency difference gets to 25% of the set LoRa
bandwidth, packet reception will fail. The displayed error can be reduced by using the 'offset'
setting in the 'Settings.h' file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
#include <TimeLib.h> //get the library here; https://github.com/PaulStoffregen/Time
time_t recordtime; //used to record the current time, preventing displayed rollover on printing
SX126XLT LT;
uint32_t RXpacketCount;
uint32_t errors;
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.receiveSXBuffer(0, 60000, WAIT_RX); //returns 0 if packet error of some sort, timeout set at 60secs\60000mS
digitalWrite(LED1, HIGH); //something has happened
recordtime = now(); //stop the time to be displayed rolling over
printtime();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
if (BUZZER > 0)
{
delay(50); //lets have a slightly longer beep
digitalWrite(BUZZER, LOW);
}
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
RXpacketCount++;
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
Serial.print(F(" FreqErrror,"));
Serial.print(LT.getFrequencyErrorHz());
Serial.print(F("hz "));
LT.printSXBufferHEX(0, (RXPacketL - 1));
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(); //get the IRQ status
if (IRQStatus & IRQ_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);
}
}
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 printDigits(int8_t digits)
{
//utility function for digital clock display: prints preceding colon and leading 0
Serial.print(F(":"));
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printtime()
{
Serial.print(hour(recordtime));
printDigits(minute(recordtime));
printDigits(second(recordtime));
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("11_LoRa_Packet_Logger_Receiver Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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));
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
Serial.println(F("Radio Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings();
Serial.println();
LT.printOperatingSettings();
Serial.println();
Serial.println();
printtime();
Serial.print(F(" Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,42 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 01/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 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 set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define RFBUSY 7 //SX12XX busy pin
#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LED1 8 //On board LED, high for on
#define BUZZER -1 //normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,190 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 29/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 can be used to check the frequency error between a pair of LoRa
devices, a transmitter and receiver. This receiver measures the frequecy error between the receivers
centre frequency and the centre frequency of the transmitted packet. The frequency difference is shown
for each packet and an average over 10 received packets reported. Any transmitter program can be used
to give this program something to listen to, including example program '3_LoRa_Transmit'.
Checked for correct operation with lora bandwidths of 500000hz, 125000 and 7800hz. At higher bandwidths
the reported frequency errors can be within 10-20hz at minimum bandwidth, 7800hz, the reported frequency
can be circa 100hz out.
Note: Semtech appear to have stated that the frequency error function that this example uses, is not
supported for SX126X, for reasons that have not been given, so use at your own risk.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
SX126XLT LT;
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //a buffer is needed to receive packets
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
int32_t totalHzError = 0; //used to keep a running total of hZ error for averaging
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 0, WAIT_RX); //wait for a packet to arrive
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
RXpacketCount++;
Serial.print(F("PacketOK > "));
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);
Serial.println();
printFrequencyError();
}
void printFrequencyError()
{
int32_t hertzerror, regdata;
regdata = LT.getFrequencyErrorRegValue();
hertzerror = LT.getFrequencyErrorHz();
Serial.print(F("ErrorRegValue,"));
Serial.print(regdata, HEX);
Serial.print(F(" PacketHertzError,"));
Serial.print(hertzerror);
Serial.println(F("hz"));
totalHzError = totalHzError + hertzerror;
if (RXpacketCount == 10)
{
Serial.print(F("******** AverageHertzerror "));
Serial.print((totalHzError / 10));
Serial.println(F("hz"));
RXpacketCount = 0;
totalHzError = 0;
delay(5000);
}
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
errors++;
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);
}
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(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("16_LoRa_RX_Frequency_Error_Check Starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
}
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(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,47 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 29/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 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 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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define RX_EN -1 //pin for RX enable, used on some SX126X devices, set to -1 if not used
#define TX_EN -1 //pin for TX enable, used on some SX126X devices, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //we need to define 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 = 10; //LoRa TX power
#define packet_delay 1000 //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,317 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 31/05/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 lora device need to be defined in the 'Settings.h' file also.
The program is a matching receiver program for the '10_LoRa_Link_Test_Transmitter'. The packets received
are displayed on the serial monitor and analysed to extract the packet data which indicates the power
used to send the packet. A count is kept of the numbers of each power setting received. When the transmitter
sends the test mode packet at the beginning of the sequence (displayed as 999) the running totals of the
powers received are printed. Thus you can quickly see at what transmit power levels the reception fails.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
#include <ProgramLT_Definitions.h>
SX126XLT 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
uint32_t Test1Count[34]; //buffer where counts of received packets are stored, -9dbm to +22dBm
uint32_t Mode1_Cycles = 0; //count the number of cyles received
bool updateCounts = false; //update counts set to tru when first TestMode1 received, at sequence start
void loop()
{
RXPacketL = LT.receiveAddressed(RXBUFFER, RXBUFFER_SIZE, 15000, WAIT_RX); //wait for a packet to arrive with 15seconds (15000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
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)
{
delay(25); //gives a slightly longer beep
digitalWrite(BUZZER, LOW); //buzzer off
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
if (BUZZER > 0) //turn buzzer on for a valid packet
{
digitalWrite(BUZZER, HIGH);
}
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 - 3); //print the packet as ASCII characters
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);
processPacket();
}
void processPacket()
{
int8_t lTXpower;
uint8_t packettype;
uint32_t temp;
packettype = LT.readRXPacketType(); //need to know the packet type so we can decide what to do
if (packettype == TestPacket)
{
if (RXBUFFER[0] == ' ')
{
lTXpower = 0;
}
if (RXBUFFER[0] == '+')
{
lTXpower = ((RXBUFFER[1] - 48) * 10) + (RXBUFFER[2] - 48); //convert packet text to power
}
if (RXBUFFER[0] == '-')
{
lTXpower = (((RXBUFFER[1] - 48) * 10) + (RXBUFFER[2] - 48)) * -1; //convert packet text to power
}
Serial.print(F(" ("));
if (RXBUFFER[0] != '-')
{
Serial.write(RXBUFFER[0]);
}
Serial.print(lTXpower);
Serial.print(F("dBm)"));
if (updateCounts)
{
temp = (Test1Count[lTXpower+9]);
Test1Count[lTXpower+9] = temp + 1;
}
}
if (packettype == TestMode1)
{
//this is a command to switch to TestMode1 also updates totals and logs
updateCounts = true;
Serial.println();
Serial.println(F("End test sequence"));
if (Mode1_Cycles > 0)
{
print_Test1Count();
}
Serial.println();
Mode1_Cycles++;
}
}
void print_Test1Count()
{
//prints running totals of the powers of received packets
int8_t index;
uint32_t j;
Serial.print(F("Test Packets "));
Serial.println(RXpacketCount);
Serial.print(F("Test Cycles "));
Serial.println(Mode1_Cycles);
Serial.println();
for (index = 31; index >= 0; index--)
{
Serial.print(index-9);
Serial.print(F("dBm,"));
j = Test1Count[index];
Serial.print(j);
Serial.print(F(" "));
}
Serial.println();
Serial.print(F("CSV"));
for (index = 31; index >= 0; index--)
{
Serial.print(F(","));
j = Test1Count[index];
Serial.print(j);
}
Serial.println();
}
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
}
}
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
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("20_LoRa_Link_Test_Receiver Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
//setup SPI, its external to library on purpose, so settings can be mixed and matched with other SPI devices
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, RFBUSY, DIO1, 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
}
}
//this function call sets up the device for LoRa using the settings from settings.h
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 operting settings, useful check
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,42 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 31/05/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 Easy Pro Mini,
//be sure to change the definitiosn to match your own setup.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define BUZZER -1 //pin for buzzer, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //this is the device we are using
//******* Setup LoRa 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, 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

View File

@@ -0,0 +1,283 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 01/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 - The program listens for incoming packets using the LoRa settings in the 'Settings.h'
file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
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 {packet contents} CRC,3882,RSSI,-69dBm,SNR,10dB,Length,19,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
A summary of the packet reception is sent to the OLED display as well, useful for portable applications.
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 <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT LT; //create a library class instance called 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;
uint32_t RXpacketErrors;
uint16_t IRQStatus;
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, 0, WAIT_RX); //wait for a packet to arrive with no timeout
digitalWrite(LED1, HIGH); //something has happened
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH); //buzzer on
}
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
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 localCRC;
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(RXpacketErrors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("OK"));
dispscreen1();
}
void packet_is_Error()
{
printElapsedTime(); //print elapsed time to Serial Monitor
RXpacketErrors++;
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(RXpacketErrors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("Packet Error"));
dispscreen1();
delay(500); //gives longer buzzer and LED falsh for error
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
void dispscreen1()
{
disp.clearLine(1);
disp.setCursor(0, 1);
disp.print(F("RSSI "));
disp.print(PacketRSSI);
disp.print(F("dBm"));
disp.clearLine(2);
disp.setCursor(0, 2);
disp.print(F("SNR "));
if (PacketSNR > 0)
{
disp.print(F("+"));
}
disp.print(PacketSNR);
disp.print(F("dB"));
disp.clearLine(3);
disp.setCursor(0, 3);
disp.print(F("Length "));
disp.print(LT.readRXPacketL());
disp.clearLine(4);
disp.setCursor(0, 4);
disp.print(F("Packets "));
disp.print(RXpacketCount);
disp.clearLine(5);
disp.setCursor(0, 5);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
disp.clearLine(6);
disp.setCursor(0, 6);
disp.print(F("IRQreg "));
disp.print(IRQStatus, HEX);
}
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("33_LoRa_RSSI_Checker_With_Display Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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));
disp.begin();
disp.setFont(u8x8_font_chroma48medium8_r);
disp.clear();
disp.setCursor(0, 0);
disp.print(F("Check LoRa"));
disp.setCursor(0, 1);
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
disp.print(F("LoRa OK"));
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
disp.print(F("Device error"));
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//this function call sets up the device for LoRa using the settings from settings.h
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 operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 01/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 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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define RX_EN -1 //pin for RX enable, used on some SX126X devices, set to -1 if not used
#define TX_EN -1 //pin for TX enable, used on some SX126X devices, set to -1 if not used
#define BUZZER -1 //pin for buzzer, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //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 = 2; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 255 //RX buffer size

View File

@@ -0,0 +1,282 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 15/05/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 matching receiver program '43_LoRa_Data_Throughput_Acknowledge_Receiver' does then need
to be configured with same lora settings as this transmitter. When this option is set, the program will
keep running until the number of transmissions and acknowledgements has completed without any timeouts
in order to produce a valid average.
The results of the test are printed out thus;
SX1262,434000000hz,SF7,BW500000,CR4:5,LDRO_Off,SyncWord_0x12,IQNormal,Preamble_8
Total transmit time 100 packets = 1382mS
Average 16 byte packet transmit time = 13.82mS
Packets per second 72.36
Bits per packet sent = 128
Data rate = 9262bps
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 <SX126XLT.h> //include the appropriate library
#include <ProgramLT_Definitions.h>
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT 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, 10000, 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"));
Serial.print(F("Packets per second "));
Serial.println((float) (1000/averagePacketTime));
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_Test_Transmitter Starting"));
SPI.begin();
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, RFBUSY, 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();
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************************************
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 Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO1,
//DIO2, BUZZER are not used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //RFBUSY pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1262 //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_SF5; //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
//******* Setup packet parameters Here ! ***************
const uint8_t numberPackets = 50; //number of packets to send in transmit loop
const uint8_t TXPacketL = 4; //length of packet to send
const bool waitforACK = false; //set to true to have transmit wait for ack before continuing

View File

@@ -0,0 +1,252 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/04/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 lora device need to be defined in the 'Settings.h' file also.
There is a printout and save to SD card of the valid packets received in HEX format. Thus the program
can be used to receive and record non-ASCII packets. The LED will flash for each packet received and
the buzzer will sound, if fitted. The measured frequency difference between the frequency used by the
transmitter and the frequency used by the receiver is shown. If this frequency difference gets to 25%
of the set LoRa bandwidth, packet reception will fail. The displayed error can be reduced by using the
'offset' setting in the 'Settings.h' file.
There will be a limit to how fast the logger can receive packets, mainly caused by the delay in writing
to SD card, so at high packet rates, packets will be lost.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SdFat.h> //https://github.com/greiman/SdFat
SdFat SD;
File logFile;
char filename[] = "Log000.txt";
boolean SD_Found = false; //set if SD card found at program startup
uint8_t lognumber;
#include <SX126XLT.h>
SX126XLT LT;
#include "Settings.h"
#include <TimeLib.h> //get the library here; https://github.com/PaulStoffregen/Time
uint32_t RXpacketCount; //count of good packets
uint32_t errors; //count of packet errors
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
uint16_t IRQStatus; //used to read the IRQ status
int32_t FreqErrror; //frequency error of received packet, in hz
time_t recordtime; //used to record the current time, preventing displayed rollover on printing
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
#include "SD_Logger_Library.h"
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
recordtime = now(); //stop the time to be displayed rolling over
printtime();
printtimeSD();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
FreqErrror = LT.getFrequencyErrorHz();
IRQStatus = LT.readIrqStatus();
if (RXPacketL == 0)
{
packet_is_Error();
packet_is_ErrorSD();
}
else
{
packet_is_OK();
packet_is_OKSD();
}
digitalWrite(LED1, LOW);
if (BUZZER > 0)
{
delay(50); //lets have a slightly longer beep
digitalWrite(BUZZER, LOW);
}
Serial.println();
}
void packet_is_OK()
{
RXpacketCount++;
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
Serial.print(F(" FreqErrror,"));
Serial.print(FreqErrror);
Serial.print(F("hz "));
LT.printHEXPacket(RXBUFFER, RXPacketL);
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()
{
RXPacketL = LT.readRXPacketL(); //get the real packet length
if (IRQStatus & IRQ_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(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
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 printDigits(int8_t digits)
{
//utility function for digital clock display: prints preceding colon and leading 0
Serial.print(F(":"));
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printtime()
{
Serial.print(hour(recordtime));
printDigits(minute(recordtime));
printDigits(second(recordtime));
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("60_LoRa_Packet_Logger_Receiver_SD Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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));
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, 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);
}
}
lognumber = setup_SDLOG() ; //setup SD card
Serial.print(F("Lognumber "));
Serial.println(lognumber);
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings();
Serial.println();
printModemSettingsSD();
logFile.println();
LT.printOperatingSettings();
Serial.println();
printOperatingSettingsSD();
logFile.println();
printtime();
Serial.print(F(" Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,346 @@
//SD_Logger_Library.h
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/04/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.
*******************************************************************************************************/
void printModemSettingsSD();
void printOperatingSettingsSD();
void printOperatingModeSD(uint8_t opmode);
uint8_t setup_SDLOG();
void printDeviceSD();
void printSXBufferHEXSD(uint8_t start, uint8_t end);
void printHEXByteSD(uint8_t temp);
void packet_is_OKSD();
void packet_is_ErrorSD();
void printDigitsSD(int8_t digits);
void printtimeSD();
void printModemSettingsSD()
{
uint8_t regdata;
uint8_t sf;
uint32_t bandwidth;
uint8_t cr;
uint8_t opt;
uint16_t syncword;
uint8_t invertIQ;
uint16_t preamble;
uint32_t freqint;
//get al the data frome the lora device in one go to avoid swapping
//devices on the SPI bus all the time
regdata = LT.readsavedModParam2();
bandwidth = LT.returnBandwidth(regdata);
freqint = LT.getFreqInt();sf = LT.getLoRaSF();
cr = (LT.getLoRaCodingRate() + 4);
opt = LT.getOptimisation();
syncword = LT.getSyncWord();
invertIQ = LT.getInvertIQ();
preamble = LT.getPreamble();
printDeviceSD();
logFile.print(F(","));
logFile.print(freqint);
logFile.print(F("hz,SF"));
logFile.print(sf);
logFile.print(F(",BW"));
logFile.print(bandwidth);
logFile.print(F(",CR4:"));
logFile.print(cr);
logFile.print(F(",LDRO_"));
if (opt)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.print(F(",SyncWord_0x"));
logFile.print(syncword, HEX);
if (invertIQ == LORA_IQ_INVERTED)
{
logFile.print(F(",IQInverted"));
}
else
{
logFile.print(F(",IQNormal"));
}
logFile.print(F(",Preamble_"));
logFile.print(preamble);
logFile.flush();
}
void printOperatingSettingsSD()
{
//get al the data frome the lora device in one go to avoid swapping
//devices on the SPI bus all the time
uint8_t pm = LT.getPacketMode();
uint8_t hm = LT.getHeaderMode();
uint8_t crcm = LT.getCRCMode();
uint8_t lnag = LT.getLNAgain();
uint8_t opmode = LT.getOpmode();
printDeviceSD();
printOperatingModeSD(opmode);
logFile.print(F(",PacketMode_"));
if (pm)
{
logFile.print(F("LoRa"));
}
else
{
logFile.print(F("FSK"));
}
if (hm)
{
logFile.print(F(",Implicit"));
}
else
{
logFile.print(F(",Explicit"));
}
logFile.print(F(",CRC_"));
if (crcm)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.print(F(",LNAgain_"));
logFile.print(lnag);
logFile.flush();
}
void printOperatingModeSD(uint8_t opmode)
{
switch (opmode)
{
case 0:
logFile.print(F("SLEEP"));
break;
case 1:
logFile.print(F("STDBY"));
break;
case 2:
logFile.print(F("FSTX"));
break;
case 3:
logFile.print(F("TX"));
break;
case 4:
logFile.print(F("FSRX"));
break;
case 5:
logFile.print(F("RXCONTINUOUS"));
break;
case 6:
logFile.print(F("RXSINGLE"));
break;
case 7:
logFile.print(F("CAD"));
break;
default:
logFile.print(F("NOIDEA"));
break;
}
}
uint8_t setup_SDLOG()
{
//checks if the SD card is present and can be initialised
//returns log number, 1-99, if OK, 0 if not
uint8_t i;
Serial.print(F("SD card..."));
if (!SD.begin(SDCS))
{
Serial.println(F("ERROR SD card fail"));
Serial.println();
SD_Found = false;
return 0;
}
Serial.print(F("Initialized OK - "));
SD_Found = true;
for (i = 1; i < 100; i++) {
filename[4] = i / 10 + '0';
filename[5] = i % 10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logFile = SD.open(filename, FILE_WRITE);
break;
}
}
Serial.print(F("Writing to "));
Serial.println(filename);
return i;
}
void printDeviceSD()
{
switch (LORA_DEVICE)
{
case DEVICE_SX1261:
logFile.print(F("SX1261"));
break;
case DEVICE_SX1262:
logFile.print(F("SX1262"));
break;
case DEVICE_SX1268:
logFile.print(F("SX1268"));
break;
default:
logFile.print(F("Unknown Device"));
}
}
void printHEXPacketSD(uint8_t *buffer, uint8_t size)
{
uint8_t index;
for (index = 0; index < size; index++)
{
printHEXByteSD(buffer[index]);
logFile.print(F(" "));
}
}
void printHEXByteSD(uint8_t temp)
{
if (temp < 0x10)
{
logFile.print(F("0"));
}
logFile.print(temp, HEX);
}
void packet_is_OKSD()
{
//uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
logFile.print(F(" FreqErrror,"));
logFile.print(LT.getFrequencyErrorHz());
logFile.print(F("hz "));
printHEXPacketSD(RXBUFFER, RXPacketL);
logFile.print(F(" RSSI,"));
logFile.print(PacketRSSI);
logFile.print(F("dBm,SNR,"));
logFile.print(PacketSNR);
logFile.print(F("dB,Length,"));
logFile.print(RXPacketL);
logFile.print(F(",Packets,"));
logFile.print(RXpacketCount);
logFile.print(F(",Errors,"));
logFile.print(errors);
logFile.print(F(",IRQreg,"));
logFile.println(IRQStatus, HEX);
logFile.flush();
}
void packet_is_ErrorSD()
{
//uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
RXPacketL = LT.readRXPacketL(); //get the real packet length
if (IRQStatus & IRQ_RX_TIMEOUT)
{
logFile.print(F(" RXTimeout"));
}
else
{
logFile.print(F(" PacketError"));
logFile.print(F(",RSSI,"));
logFile.print(PacketRSSI);
logFile.print(F("dBm,SNR,"));
logFile.print(PacketSNR);
logFile.print(F("dB,Length,"));
logFile.print(RXPacketL);
logFile.print(F(",Packets,"));
logFile.print(RXpacketCount);
logFile.print(F(",Errors,"));
logFile.print(errors);
logFile.print(F(",IRQreg,"));
logFile.println(IRQStatus, HEX);
}
logFile.flush();
}
void printDigitsSD(int8_t digits)
{
//utility function for digital clock display: prints preceding colon and leading 0
logFile.print(F(":"));
if (digits < 10)
logFile.print('0');
logFile.print(digits);
}
void printtimeSD()
{
logFile.print(hour(recordtime));
printDigitsSD(minute(recordtime));
printDigitsSD(second(recordtime));
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/04/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, An ATmeag1284P shield base for my BBF modules.
//Be sure to change the definitions to match your own setup. Some pins such as DIO2, DIO3, 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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define BUZZER 4 //pin for buzzer, on when logic high
#define SDCS 30 //CS pin for SD card
#define LORA_DEVICE DEVICE_SX1262 //we need to define 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 RXBUFFER_SIZE 255 //RX buffer size

View File

@@ -0,0 +1,189 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 04/04/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 demonstrates the detailed setup of a LoRa test transmitter.
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 lora device need to be defined in the 'Settings.h' file also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used, the packet length and the CRC of the packet. The matching receive program,
'104_LoRa_Receiver' 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 transmitter and receiver programs. Sample Serial
Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 CRC,DAAB TransmitTime,64mS PacketsSent,2
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT 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, 10000, 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 transmitted 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
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("103_LoRa_Transmitter_Detailed_Setup 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, RFBUSY, DIO1, SW, 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);
LT.setRegulatorMode(USE_DCDC);
LT.setPaConfig(0x04, PAAUTO, LORA_DEVICE);
LT.setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V);
LT.calibrateDevice(ALLDevices); //is required after setting TCXO
LT.calibrateImage(Frequency);
LT.setDIO2AsRfSwitchCtrl();
LT.setPacketType(PACKET_TYPE_LORA);
LT.setRfFrequency(Frequency, Offset);
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, Optimisation);
LT.setBufferBaseAddress(0, 0);
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);
LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1
LT.setHighSensitivity(); //set for maximum gain
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);
//***************************************************************************************************
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(0x900, 0x9FF); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,46 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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, a ESP32 shield base with my BBF board shield on
//top. Be sure to change the definitions to match your own setup. Some pins such as DIO2, DIO3, 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 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 DIO1 35 //DIO1 pin on LoRa device, used for RX and TX done
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#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_SX1262 //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

View File

@@ -0,0 +1,254 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 04/04/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 demonstrates the detailed setup of a LoRa test receiver.
The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins
to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout on the Arduino IDE Serial Monitor of the valid packets received, the packet is
assumed to be in ASCII printable text, if it's 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;
7s Hello World 1234567890*,CRC,DAAB,RSSI,-52dBm,SNR,9dB,Length,23,Packets,5,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
968s PacketError,RSSI,-87dBm,SNR,-11dB,Length,23,Packets,613,Errors,2,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX126XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX126XLT 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 (SNR) 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 is 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 device 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
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("104_LoRa_Receiver_Detailed_Setup_ESP32 Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
SPI.begin();
//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, RFBUSY, DIO1, SW, 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);
LT.setRegulatorMode(USE_DCDC);
LT.setPaConfig(0x04, PAAUTO, LORA_DEVICE);
LT.setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V);
LT.calibrateDevice(ALLDevices); //is required after setting TCXO
LT.calibrateImage(Frequency);
LT.setDIO2AsRfSwitchCtrl();
LT.setPacketType(PACKET_TYPE_LORA);
LT.setRfFrequency(Frequency, Offset);
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, Optimisation);
LT.setBufferBaseAddress(0, 0);
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);
LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1
LT.setHighSensitivity(); //set for maximum gain
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);
//***************************************************************************************************
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(0x900, 0x9FF); //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();
}

View File

@@ -0,0 +1,52 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 04/04/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, a ESP32 shield base with my BBF board shield on
//top. Be sure to change the definitions to match your own setup. Some pins such as DIO2, DIO3, 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 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 LED1 2 //on board LED, high for on
#define DIO1 35 //DIO1 pin on LoRa device, used for RX and TX done
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#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_SX1262 //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

View File

@@ -0,0 +1,127 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 28/05/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 minimum setup LoRa test transmitter. A packet containing the ASCII text
"Hello World 1234567890" is sent using the frequency and LoRa settings specified in the LT.setupLoRa()
command. The pins to access the lora device need to be defined at the top of the program also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used and the packet length. The matching receiver program, '4_LoRa_Receiver' can be used
to check the packets are being sent correctly, the frequency and LoRa settings (in the LT.setupLoRa()
commands) must be the same for the transmitter and receiver programs. Sample Serial Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 PacketsSent,6
For an example of a more detailed configuration for a transmitter, see program 103_LoRa_Transmitter.
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 <SX126XLT.h> //include the appropriate library
SX126XLT LT; //create a library class instance called LT
//These are the pin definitions for used for the program. Be sure to change to match the pins for your
//own setup. 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 RFBUSY 25 //busy line
#define DIO1 35 //DIO1 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1262 //we need to define the device we are using
const int8_t TXpower = 10; //LoRa transmit power in dBm
uint8_t TXPacketL;
uint32_t TXPacketCount;
uint8_t buff[] = "Hello World 1234567890"; //the message to send
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("3_LoRa_Transmitter Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Transmitter ready"));
Serial.println();
}
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 receiver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
Serial.println();
delay(1000); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
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
}

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: 153 KiB

View 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.
![Picture 1](/pictures/ESP32_Bare_Bones_Schematic.jpg)
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;
![Picture 1](/pictures/ESP32_Micro_Node.jpg)
### 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

View File

@@ -0,0 +1,154 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 08/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 packet without using a processor buffer, the LoRa device
internal buffer is filled direct with variables. The program is a simulation of the type of packet
that might be sent from a GPS tracker. Note that in this example a buffer of text is part of the
transmitted packet, this does need a processor buffer which is used to fill the LoRa device internal
buffer, if you don't need to transmit text then the uint8_t trackerID[] = "Tracker1"; definition
can be ommited.
The matching receiving program '9_LoRa_LowMemory_RX' can be used to receive and display the packet,
though the program '15_LoRa_RX_Structure' should receive it as well, since the packet contents are
the same.
The contents of the packet received, and printed to serial monitor, should be;
"tracker1" (buffer) - trackerID
1+ (uint32_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
SX126XLT LT;
uint32_t TXpacketCount = 0;
uint8_t TXPacketL;
uint32_t startmS, endmS;
void loop()
{
TXpacketCount++;
if (Send_Test_Packet())
{
Serial.print(TXpacketCount);
Serial.print(F(" "));
Serial.print(TXPacketL);
Serial.print(F(" Bytes Sent"));
Serial.print(F(" "));
Serial.print(endmS - startmS);
Serial.print(F("mS"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
Serial.println();
delay(packet_delay);
}
uint8_t Send_Test_Packet()
{
//The SX12XX buffer is filled with variables of a known type and order. Make sure the receiver
//uses the same variable type and order to read variables out of the receive buffer.
float latitude, longitude;
uint16_t altitude, voltage;
uint8_t satellites;
int16_t temperature;
uint8_t len;
//test data
uint8_t trackerID[] = "tracker1";
latitude = 51.23456;
longitude = -3.12345;
altitude = 199;
satellites = 9;
voltage = 3999;
temperature = -9;
LT.startWriteSXBuffer(0); //start the write at location 0
LT.writeBuffer(trackerID, sizeof(trackerID)); //= 13 bytes (12 characters plus null (0) at end)
LT.writeUint32(TXpacketCount); //+4 = 17 bytes
LT.writeFloat(latitude); //+4 = 21 bytes
LT.writeFloat(longitude); //+4 = 25 bytes
LT.writeUint16(altitude); //+2 = 27 bytes
LT.writeUint8(satellites); //+1 = 28 bytes
LT.writeUint16(voltage); //+2 = 30 bytes
LT.writeInt8(temperature); //+1 = 31 bytes total to send
len = LT.endWriteSXBuffer();
digitalWrite(LED1, HIGH);
startmS = millis();
TXPacketL = LT.transmitSXBuffer(0, len, 5000, TXpower, WAIT_TX); //set a TX timeout of 5000mS
endmS = millis();
digitalWrite(LED1, LOW);
return TXPacketL;
}
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);
led_Flash(2, 125);
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
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("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/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 my own boards, the Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO2,
//DIO3, 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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,195 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 08/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 receives a packet without using a processor buffer, the LoRa device
internal buffer is read direct and copied to variables. The program is a simulation of the type of packet
that might be received from a GPS tracker. Note that in this example a buffer of text is part of the
received packet, this does need a processor buffer which is filled with data from the LoRa device internal
buffer, if you don't need to send and receive text then the uint8_t receivebuffer[32]; definition can be
ommited.
The contents of the packet received, and printed to serial monitor, should be;
"Tracker1" (buffer) - trackerID
1+ (uint32_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
SX126XLT LT;
uint32_t RXpacketCount;
uint16_t errors;
uint8_t RXPacketL; //length of received packet
int8_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
uint8_t packet_is_OK()
{
float latitude, longitude;
uint16_t altitude, voltage;
uint8_t satellites;
int8_t temperature;
uint32_t txcount;
uint8_t receivebuffer[16]; //create receive buffer, make sure this is big enough for buffer sent !!!
//packet has been received, now read from the SX12xx Buffer using the same variable type and
//order as the transmit side used.
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(" "));
LT.startReadSXBuffer(0); //start buffer read at location 0
LT.readBuffer(receivebuffer); //read in the character buffer
txcount = LT.readUint32(); //read in the TXCount
latitude = LT.readFloat(); //read in the latitude
longitude = LT.readFloat(); //read in the longitude
altitude = LT.readUint16(); //read in the altitude
satellites = LT.readUint8(); //read in the number of satellites
voltage = LT.readUint16(); //read in the voltage
temperature = LT.readInt8(); //read in the temperature
RXPacketL = LT.endReadSXBuffer();
Serial.print((char*)receivebuffer); //print the received buffer, cast to char needed
Serial.print(F(","));
Serial.print(txcount);
Serial.print(F(","));
Serial.print(latitude, 5);
Serial.print(F(","));
Serial.print(longitude, 5);
Serial.print(F(","));
Serial.print(altitude);
Serial.print(F("m,"));
Serial.print(satellites);
Serial.print(F("sats,"));
Serial.print(voltage);
Serial.print(F("mV,"));
Serial.print(temperature);
Serial.print(F("c "));
Serial.print(F(" RSSI"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB"));
return RXPacketL;
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
errors++;
Serial.print(F("PacketError"));
printpacketDetails();
Serial.print(F("IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printpacketDetails()
{
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB"));
}
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);
led_Flash(2, 125);
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
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,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/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 my own boards, the Easy Pro Mini,
//be sure to change the definitions to match your own setup. Some pins such as DIO2,
//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 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define RFBUSY 7 //SX126X busy pin
#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define DIO3 -1 //DIO3 pin on LoRa device, normally not used so set to -1
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1262 //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

View File

@@ -0,0 +1,44 @@
# SX126X Library
<cr>
This part of the SX12XX library supports the SX1261, SX1262 and SX1268 (all UHF) LoRa devices..
The objective of the library is to allow the same program sketches to be used across the range of UHF lora modules SX126x and SX127x (UHF) as well as the 2.4Ghz SX128x modules.
The library was tested on both NiceRF and Dorji modules.
The Library has not been tested on the Semtech SX1261MB2BAS or similar development boards, so consider them unsupported. These development modules are not low cost and are not in a form (and too big) to be of practical use to the author of the library.
###Considerations for pin usage
There is a range of SX126X modules available and they have slightly different pins usage.
The library only supports the SPI based LoRa modules and these all require that the SPI bus pins, SCK, MOSI and MISO are connected. All modules also need a NSS (chip select pin) and NRESET (reset) pin. All devices need the RFBUSY pin to be used also.
Of the LoRa devices DIO pins the SX126X library in standard form only uses DIO1. The Dorji DRF1262 and DRF1268 modules have an additional SW pin which must be configured and used since it provides power to the antenna switch on these modules. Some SX126x modules have RX and TX enable pins that need to be appropiatly activated when receiving or transmitting.
Thus a begin function that initialised all possible permutations of pins would look like this;
begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX\_EN, TX\_EN, SW, LORA\_DEVICE);
Clearly the above begin statement is somewhat cumbersome and could potentially be shortened for the NiceRF S1262 devices to;
begin(NSS, NRESET, RFBUSY, DIO1, LORA\_DEVICE);
And shortened for the Dorji devices to;
begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA\_DEVICE);
Which is a lot more manageable.
The first edition of the SX126X part of the library did use use a begin function in the examples of;
begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, SW, LORA\_DEVICE)
This format is still valid so if you have written your own programs using the earlier library these programs do not need changing. You could not have used the newer constructs of the begin command (to support the newer devices) in your programs since the newer constructs did not exist in the older version library.
Accepted its all a bit confusing, but regrettably module manufacturers have different ideas about design.

View File

@@ -0,0 +1,307 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 program is a remote control transmitter. When one of four switches are made
(shorted to ground) a packet is transmitted with single byte indicating the state of Switch0 as bit 0,
Switch1 as bit 1 and Switch2 as bit 2. To prevent false triggering at the receiver the packet contains a
32 bit number called the TXIdentity which in this example is set to 1234554321. The receiver will only
act on, change the state of the outputs, if the identity set in the receiver matches that of the
transmitter. The chance of a false trigger is fairly remote.
Between switch presses the LoRa device and Atmel microcontroller are put to sleep. A switch press wakes
up the processor from sleep, the switches are read and a packet sent. On a 'bare bones' Arduino setup
the transmitter has a sleep current of approx 2.2uA, so it's ideal for a battery powered remote control
with a potential range of many kilometres.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
are not necessarily optimised for long range.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
#include <avr/wdt.h> //watchdog timer library, integral to Arduino IDE
#include <avr/sleep.h> //watchdog timer library, integral to Arduino IDE
#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt
SX126XLT LT;
uint32_t TXpacketCount;
uint8_t TXPacketL;
volatile bool switch0flag = false;
volatile bool switch1flag = false;
volatile bool switch2flag = false;
volatile bool switch3flag = false;
void loop()
{
uint8_t switches;
digitalWrite(LED1, LOW); //turn off indicator LED
Serial.print(F("Sleeping zzzz"));
Serial.flush(); //make sure all serial output has gone
LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep.
sleep_permanent(); //sleep Atmel processor permanently for switch wakeup only
LT.wake(); //wake up the lora device - nicely
digitalWrite(LED1, HIGH);
Serial.println(F(" - Awake !!")); //the processor has woken up
switches = readSwitches(); //read the state of the switches
TXpacketCount++;
Serial.print(TXpacketCount); //print the numbers of sends
Serial.print(F(" Sending > "));
Serial.print(switches, BIN);
if (sendSwitchPacket(switches))
{
Serial.println(F(" SentOK"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
Serial.println();
delay(500);
}
uint8_t sendSwitchPacket(uint8_t switches)
{
//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(RControl1); //this byte identifies the type of packet
LT.writeUint32(TXIdentity); //this 32bit integer defines the Identity of the transmiter
LT.writeUint8(switches); //this byte contains the 8 switch values to be sent
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
//now transmit the packet, 10 second timeout, and wait for it to complete sending
TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX);
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
void sleep_permanent()
{
attachInterrupts();
ADCSRA = 0; //disable ADC
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE); //turn on brown-out enable select
MCUCR = bit (BODS); //this must be done within 4 clock cycles of above
interrupts (); //guarantees next instruction executed
sleep_cpu (); //sleep within 3 clock cycles of above
/* wake up here */
sleep_disable();
detachInterrupts();
}
void attachInterrupts()
{
if (SWITCH0 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH0), wake0, FALLING);
switch0flag = false;
}
if (SWITCH1 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH1), wake1, FALLING);
switch1flag = false;
}
if (SWITCH2 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH2), wake2, FALLING);
switch2flag = false;
}
if (SWITCH3 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH3), wake3, FALLING);
switch3flag = false;
}
}
void detachInterrupts()
{
if (SWITCH0 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH0));
}
if (SWITCH1 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH1));
}
if (SWITCH2 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH2));
}
if (SWITCH3 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH3));
}
}
void wake0()
{
switch0flag = true;
}
void wake1()
{
switch1flag = true;
}
void wake2()
{
switch2flag = true;
}
void wake3()
{
switch3flag = true;
}
uint8_t readSwitches()
{
uint8_t switchByte = 0xFF; //start assuming all switches off
if (switch0flag)
{
bitClear(switchByte, 0); //if the flag is set clear the bit
Serial.println(F("SWITCH0 pressed"));
}
if (switch1flag)
{
bitClear(switchByte, 1); //if the flag is set clear the bit
Serial.println(F("SWITCH1 pressed"));
}
if (switch2flag)
{
bitClear(switchByte, 2); //if the flag is set clear the bit
Serial.println(F("SWITCH2 pressed"));
}
if (switch3flag)
{
bitClear(switchByte, 3); //if the flag is set clear the bit
Serial.println(F("SWITCH3 pressed"));
}
return switchByte;
}
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 setupSwitches()
{
if (SWITCH0 >= 0)
{
pinMode(SWITCH0, INPUT_PULLUP);
}
if (SWITCH1 >= 0)
{
pinMode(SWITCH1, INPUT_PULLUP);
}
if (SWITCH2 >= 0)
{
pinMode(SWITCH2, INPUT_PULLUP);
}
if (SWITCH3 >= 0)
{
pinMode(SWITCH3, INPUT_PULLUP);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
setupSwitches();
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
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("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,52 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 Easy Pro Mini,
//be sure to change the definitiosn to match your own setup. Some pins such as DIO2,
//DIO3, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t RFBUSY = 7; //RF busy on LoRa device
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t DIO3 = -1; //DIO3 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
const int8_t RX_EN = -1; //pin for RX enable, used on some SX126X devices, set to -1 if not used
const int8_t TX_EN = -1; //pin for TX enable, used on some SX126X devices, set to -1 if not used
const int8_t SW = -1; //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //this is the device we are using
const int8_t SWITCH0 = 2;
const int8_t SWITCH1 = 4;
const int8_t SWITCH2 = A3;
const int8_t SWITCH3 = A2;
const uint32_t TXIdentity = 1234554321; //define an identity number, the receiver must use the same number
//range is 0 to 4294967296
//******* Setup LoRa Test 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
#define TXpower 10 //power for transmissions in dBm

View File

@@ -0,0 +1,297 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 program is a remote control receiver. When a packet is received an 8 bit byte
(SwitchByte) is read and the four outputs (defined in Settings.h) are toggled according to the bits
set in this byte. If the Switch1 byte has bit 0 cleared, then OUTPUT0 is toggled. If the Switch1 byte
has bit 1 cleared, then OUTPUT1 is toggled. If the Switch1 byte has bit 2 cleared, then OUTPUT2 is toggled.
To prevent false triggering at the receiver the packet contains also contains a 32 bit number called the
TXIdentity which in this example is set to 1234554321. The receiver will only act on, change the state
of the outputs, if the identity set in the receiver matches that of the transmitter. The chance of a
false trigger is fairly remote.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define programversion "V1.0"
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX126XLT LT;
uint32_t RXpacketCount;
uint16_t errors;
uint8_t RXPacketL; //length of received packet
uint8_t RXPacketType; //type of received packet
int8_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
uint8_t SwitchByte = 0xFF; //this is the transmitted switch values, bit 0 = Switch0 etc
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI(); //read the signal strength of the received packet
PacketSNR = LT.readPacketSNR(); //read the signal to noise ratio of the received packet
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
uint8_t packet_is_OK()
{
//packet has been received, now read from the SX12xx Buffer using the same variable type and
//order as the transmit side used.
uint32_t TXIdentity;
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(" Packet Received"));
LT.startReadSXBuffer(0); //start buffer read at location 0
RXPacketType = LT.readUint8(); //read in the packet type
TXIdentity = LT.readUint32(); //read in the identity of transmitter
SwitchByte = LT.readUint8(); //read in the Switch values
RXPacketL = LT.endReadSXBuffer(); //finish buffer read
printpacketDetails();
if (RXPacketType != RControl1)
{
Serial.print(F(" Wrong packet type"));
led_Flash(5, 25); //short fast speed flash indicates wrong packet type
return 0;
}
if (TXIdentity != RXIdentity)
{
Serial.print(F(" Transmitter "));
Serial.print(TXIdentity);
Serial.print(F(" not recognised"));
led_Flash(5, 25); //short fast speed flash indicates transmitter not recognised
return 0;
}
if (LT.readRXPacketL() != 6)
{
Serial.print(F(" Wrong Packet Length"));
led_Flash(5, 25); //short fast speed flash indicates transmitter not recognised
return 0;
}
//if we get to here, then the packet is valid so switch outputs accordingly
if (BUZZER >= 0)
{
digitalWrite(BUZZER, HIGH);
}
Serial.print(F(",SwitchByte Received "));
Serial.print(SwitchByte, BIN); //print switch values in binary, if a bit is 0, that switch is active
actionOutputs(SwitchByte);
if (BUZZER >= 0)
{
digitalWrite(BUZZER, LOW);
}
return RXPacketL;
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
errors++;
Serial.print(F("PacketError"));
printpacketDetails();
Serial.print(F("IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printpacketDetails()
{
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 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 actionOutputs(uint8_t switches)
{
//read the recreived switch byte and toggle outputs as required
if (!bitRead(switches, 0))
{
//toggle Output state
digitalWrite(OUTPUT0, !digitalRead(OUTPUT0)); //toggle Output state
}
if (!bitRead(switches, 1))
{
digitalWrite(OUTPUT1, !digitalRead(OUTPUT1)); //toggle Output state
}
if (!bitRead(switches, 2))
{
digitalWrite(OUTPUT2, !digitalRead(OUTPUT2)); //toggle Output state
}
if (!bitRead(switches, 3))
{
digitalWrite(OUTPUT3, !digitalRead(OUTPUT3)); //toggle Output state
}
}
void setupOutputs()
{
//configure the output pins, if a pin is defiend in 'Settings.h' as -1, its not configured, so stays as input
if (OUTPUT0 >= 0)
{
pinMode(OUTPUT0, OUTPUT);
}
if (OUTPUT1 >= 0)
{
pinMode(OUTPUT1, OUTPUT);
}
if (OUTPUT2 >= 0)
{
pinMode(OUTPUT2, OUTPUT);
}
if (OUTPUT3 >= 0)
{
pinMode(OUTPUT3, OUTPUT);
}
if (BUZZER >= 0)
{
pinMode(BUZZER, OUTPUT);
}
}
void outputCheck(uint8_t number, uint32_t ondelaymS, uint32_t offdelaymS)
{
uint8_t index;
Serial.println(F("Toggling outputs"));
for (index = 1; index <= number; index++)
{
digitalWrite(OUTPUT0, HIGH);
delay(ondelaymS);
digitalWrite(OUTPUT0, LOW);
delay(offdelaymS);
digitalWrite(OUTPUT1, HIGH);
delay(ondelaymS);
digitalWrite(OUTPUT1, LOW);
delay(offdelaymS);
digitalWrite(OUTPUT2, HIGH);
delay(ondelaymS);
digitalWrite(OUTPUT2, LOW);
delay(offdelaymS);
digitalWrite(OUTPUT3, HIGH);
delay(offdelaymS);
digitalWrite(OUTPUT3, LOW);
delay(offdelaymS);
digitalWrite(BUZZER, HIGH);
delay(offdelaymS);
digitalWrite(BUZZER, LOW);
delay(offdelaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
setupOutputs();
outputCheck(3, 500, 100);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
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"));
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 Easy Pro Mini,
//be sure to change the definitiosn to match your own setup. Some pins such as DIO2,
//DIO3, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t RFBUSY = 7; //RF busy on LoRa device
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t DIO3 = -1; //DIO3 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
const int8_t RX_EN = -1; //pin for RX enable, used on some SX126X devices, set to -1 if not used
const int8_t TX_EN = -1; //pin for TX enable, used on some SX126X devices, set to -1 if not used
const int8_t SW = -1; //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
const int8_t BUZZER = -1; //pin for buzzer, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //this is the device we are using
const int8_t OUTPUT0 = 2;
const int8_t OUTPUT1 = 4;
const int8_t OUTPUT2 = A3;
const int8_t OUTPUT3 = A2;
const uint32_t RXIdentity = 1234554321; //define an identity number, the receiver must use the same number
//range is 0 to 4294967296
//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
#define TXpower 10 //power for transmissions in dBm

View File

@@ -0,0 +1,205 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 remote control transmitter that uses a LoRa link to transmit the positions
from a simple joystick to a remote receiver. The receiver uses the sent joystick positions to adjust the
positions of servos. The postions of the joysticks potentiometers on the transmitter are read with the
analogueRead() function.
If the joystick has a switch, often made by pressing on the joystick, then this can be used to remote
control an output on the receiver. The switch is read by an interrupt, the interrupt routine sets a flag
byte which is read in loop().
The program is intended as a proof of concept demonstration of how to remote control servos, the program
is not designed as a practical remote control device for RC model cars for instance.
It would be straight forward to make the transmitter program send packets continuously, but in most places
in the world that would break a normal limitation of 10% duty cycle for unlicensed use. Therefore the
program was designed to only transmit at a 10% duty cycle. Thus the fastest (lowest air time) packets are
used, spreading factor 6 at a bandwidth of 500khz. This results in an air time for the 5 byte control
packet of around 4mS, so there are around 25 sent per second.
To have the transmitter program print out the values read from the joystick, comment in the line;
//#define DEBUG
Which is just above the loop() function. With the DEBUG enabled the transmission rate, the rate at which
the control packets are transmitted will be slowed down.
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a
'TXidentity' number, valid values are 0 - 65535. The receiver must be setup with the matching identity
number or the received packets will be ignored.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
are not necessarily optimised for long range.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX126XLT LT;
#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt
uint32_t TXpacketCount;
uint8_t TXPacketL;
uint8_t joystickX1value; //variable to read the value from the analog pin
uint8_t joystickY1value; //variable to read the value from the analog pin
volatile bool switch1flag = false;
//#define DEBUG //comment in thie line (remove the two // at the beggining) for debug output
void loop()
{
uint8_t switchByte = 0xFF;
joystickX1value = (uint8_t) (analogRead(joystickX1) / 4) ; //read the joystick X1 pot, turn 0-1023 into 0 to 255
joystickY1value = (uint8_t) (analogRead(joystickY1) / 4); //read the joystick Y1 pot
if (switch1flag)
{
bitClear(switchByte, 1); //if the switch is down clear the bit
digitalWrite(LED1, HIGH); //turn on LED as switch indicator
switch1flag = false;
}
if (!sendJoystickPacket(joystickX1value, joystickY1value, switchByte))
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
}
uint8_t sendJoystickPacket(uint16_t X1value, uint16_t Y1value, uint8_t switches)
{
//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;
uint32_t packetStartmS, packettimemS;
LT.startWriteSXBuffer(0); //start the write packet to buffer process
LT.writeUint8(RControl1); //this is the packet type
LT.writeUint8(TXIdentity); //this value represents the transmitter number
LT.writeUint8(X1value); //this byte contains joystick pot AD X1 value to be sent
LT.writeUint8(Y1value); //this byte contains joystick pot AD Y1 value to be sent
LT.writeUint8(switches); //switches value
LT.endWriteSXBuffer(); //close the packet, thee are 5 bytes to send
//now transmit the packet, 10 second timeout, and wait for it to complete sending
packetStartmS = millis();
TXPacketL = LT.transmitSXBuffer(0, PacketLength, 10000, TXpower, WAIT_TX);
packettimemS = millis() - packetStartmS;
#ifdef DEBUG
Serial.print(TXIdentity);
Serial.print(F(",X1,"));
Serial.print(joystickX1value);
Serial.print(F(",Y1,"));
Serial.print(joystickY1value);
Serial.print(F(","));
Serial.print(switches, BIN);
Serial.print(F(","));
Serial.print(packettimemS);
Serial.print(F("mS"));
Serial.println();
#endif
digitalWrite(LED1, LOW); //LED off, may have been on due to switch press
delay(packettimemS * 9); //delay for 9 times packet transmit time to ensure 10% duty cycle
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
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 attachInterrupts()
{
if (SWITCH1 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH1), wake1, FALLING);
switch1flag = false;
}
}
void detachInterrupts()
{
if (SWITCH1 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH1));
}
}
void wake1()
{
switch1flag = true;
}
void setupSwitches()
{
if (SWITCH1 >= 0)
{
pinMode(SWITCH1, INPUT_PULLUP);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
setupSwitches();
Serial.begin(115200);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
attachInterrupts();
Serial.println(F("35_Remote_Control_Servo_Transmitter ready"));
}

View File

@@ -0,0 +1,53 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 ! ***************
//******* 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 DIO2,
//DIO3, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t RFBUSY = 7; //RF busy on LoRa device
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t DIO3 = -1; //DIO3 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
const int8_t RX_EN = -1; //pin for RX enable, used on some SX126X devices, set to -1 if not used
const int8_t TX_EN = -1; //pin for TX enable, used on some SX126X devices, set to -1 if not used
const int8_t SW = -1; //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //this is the device we are using
const int8_t joystickX1 = A2; //analog pin for the joystick 1 X pot
const int8_t joystickY1 = A3; //analog pin for the joystick 1 Y pot
const int8_t SWITCH1 = 2; //switch on joystick, set to -1 if not used
const uint32_t TXIdentity = 123 ; //define a transmitter number, the receiver must use the same number
//range is 0 to 255
//******* Setup LoRa Test 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 uint8_t PacketLength = 5; //packet length is fixed
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,259 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 remote control receiver that uses a LoRa link to control the positions of
servos sent from a remote transmitter.
If the ttransmitter joystick has a switch, often made by pressing on the joystick, then this can be used
to remote control an output on the receiver.
The program is intended as a proof of concept demonstration of how to remote control servos, the program
is not designed as a practical remote control device for RC model cars for instance.
It would be straight forward to make the transmitter program send packets continuously, but in most places
in the world that would break a normal limitation of 10% duty cycle for unlicensed use. Therefore the
program was designed to only transmit at a 10% duty cycle. Thus the fastest (lowest air time) packets are
used, spreading factor 6 at a bandwidth of 500khz. This results in an air time for the 5 byte control
packet of around 4mS, so there are around 25 sent per second.
To have the receiver program print out the joystick values (0-255) read from the received packet, comment
in the line;
//#define DEBUG
Which is just above the loop() function. With the DEBUG enabled then there is a possibility that some
transmitted packets will be missed. With the DEBUG line enabled to servos should also sweep to and fro 3
times at program start-up.
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a
'TXidentity' number, valid values are 0 - 255. The receiver must be setup with the matching RXIdentity
number in Settings.h or the received packets will be ignored.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
are not necessarily optimised for long range.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define programversion "V1.0"
#include <SPI.h>
#include <SX126XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX126XLT LT;
#include <Servo.h>
Servo ServoX1; //create the servo object
Servo ServoY1; //create the servo object
uint8_t joystickX1value; //variable to read the value from the analog pin
uint8_t joystickY1value; //variable to read the value from the analog pin
uint8_t RXPacketL; //length of received packet
uint8_t RXPacketType; //type of received packet
//#define DEBUG
void loop()
{
uint16_t IRQStatus;
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort
while (!digitalRead(DIO1)); //wait for DIO1 to go high
IRQStatus = LT.readIrqStatus();
if (LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID + IRQ_PREAMBLE_DETECTED))
{
packet_is_OK();
}
else
{
Serial.print(F("IRQ,"));
Serial.print(LT.readIrqStatus(),HEX);
Serial.print(F(","));
packet_is_Error();
}
}
uint8_t packet_is_OK()
{
//packet has been received, now read from the SX12xx Buffer using the same variable type and
//order as the transmit side used.
uint8_t TXIdentity;
uint16_t pulseX1, pulseY1;
uint8_t switchByte = 0xFF; //this is the transmitted switch values, bit 0 = Switch0 etc
LT.startReadSXBuffer(0); //start buffer read at location 0
RXPacketType = LT.readUint8(); //read in the packet type
TXIdentity = LT.readUint8(); //read in the transmitter number
joystickX1value = LT.readUint8(); //this byte contains joystick pot AD X1 value sent
joystickY1value = LT.readUint8(); //this byte contains joystick pot AD Y1 value sent
switchByte = LT.readUint8(); //read in the Switch values
RXPacketL = LT.endReadSXBuffer(); //end buffer read
#ifdef DEBUG
Serial.print(TXIdentity);
Serial.print(F(",X1,"));
Serial.print(joystickX1value);
Serial.print(F(",Y1,"));
Serial.print(joystickY1value);
Serial.print(F(","));
Serial.print(switchByte, BIN);
Serial.println();
#endif
if (RXPacketType != RControl1)
{
Serial.print(F("Packet type "));
Serial.println(RXPacketType);
led_Flash(5, 25); //short fast speed flash indicates wrong packet type
return 0;
}
if (TXIdentity != RXIdentity)
{
Serial.print(F("TX"));
Serial.print(TXIdentity);
Serial.println(F("?"));
return 0;
}
//actionServos
pulseX1 = map(joystickX1value, 0, 255, 1000, 2000); //scale the numbers from the joystick
ServoX1.writeMicroseconds(pulseX1);
pulseY1 = map(joystickY1value, 0, 255, 1000, 2000); //scale the numbers from the joystick
ServoY1.writeMicroseconds(pulseY1); //move the servo to position
//actionOutputs
if (!bitRead(switchByte, 1))
{
digitalWrite(OUTPUT1, !digitalRead(OUTPUT1)); //Toggle Output state
}
return RXPacketL;
}
void packet_is_Error()
{
uint16_t IRQStatus;
int8_t PacketRSSI;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
PacketRSSI = LT.readPacketRSSI(); //read the signal strength of the received packet
Serial.print(F("Err,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm"));
}
Serial.println();
}
void setupOutputs()
{
//configure the output pins, if a pin is defiend in 'Settings.h' as -1, its not configured, so stays as input
if (OUTPUT1 >= 0)
{
pinMode(OUTPUT1, OUTPUT);
}
}
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 sweepTest(uint8_t num)
{
uint16_t index1, index2;
for (index1 = 1; index1 <= num; index1++)
{
for (index2 = 900; index2 <= 2100; index2++)
{
ServoX1.writeMicroseconds(index2);
ServoY1.writeMicroseconds(index2);
}
delay(1000);
for (index2 = 2100; index2 >= 900; index2--)
{
ServoX1.writeMicroseconds(index2);
ServoY1.writeMicroseconds(index2);
}
delay(1000);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
setupOutputs();
Serial.begin(115200);
ServoX1.attach(pinservoX1); //connect pin pinservoX1 to ServoX1 object
ServoY1.attach(pinservoY1); //connect pin pinservoY1 to ServoY1 object
#ifdef DEBUG
Serial.println(F("Servo sweep test"));
sweepTest(3);
#endif
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
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("36_Remote_Control_Servo_Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 Easy Pro Mini,
//be sure to change the definitiosn to match your own setup. Some pins such as DIO2,
//DIO3, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t RFBUSY = 7; //RF busy on LoRa device
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t DIO3 = -1; //DIO3 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
const int8_t RX_EN = -1; //pin for RX enable, used on some SX126X devices, set to -1 if not used
const int8_t TX_EN = -1; //pin for TX enable, used on some SX126X devices, set to -1 if not used
const int8_t SW = -1; //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1262 //this is the device we are using
const int8_t pinservoX1 = 2; //pin for controlling servo X1
const int8_t pinservoY1 = 4; //pin for controlling servo Y1
const int8_t OUTPUT1 = 8; //this output toggles when joystick switch is pressed on receiver
const uint16_t RXIdentity = 123; //define a receiver number, the transmitter must use the same number
//range is 0 to 255
//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 uint8_t PacketLength = 5; //packet length is fixed

View File

@@ -0,0 +1,69 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/02/20
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 pin 13 LED,
fitted to some Arduinos is blinked as well. 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 8 //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);
digitalWrite(13, HIGH);
delay(100);
digitalWrite(LED1, LOW);
digitalWrite(13, 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
digitalWrite(13, HIGH); //Arduino board LED on
delay(delaymS);
digitalWrite(LED1, LOW); //LED off
digitalWrite(13, LOW); //Arduino board LED off
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
pinMode(13, OUTPUT); //setup pin as output for some Arduino boards that include an LED on pin 13
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 Starting"));
}

View File

@@ -0,0 +1,401 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/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 stand alone, it is not necessary to install the SX12XX-LoRa library
to use it. This test program is for the SX126X LoRa devices.
The program checks that a SX126X 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, SX1261, SX1262,
or SX1268 must be specified also.
Typical printout;
2_Register_Test Starting
Reset device
LoRa Device found
Reset device
Registers at reset
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x800 00 00 00 00 01 07 20 1E 00 10 19 04 0F FF 0F FF
0x810 10 00 10 00 10 00 10 00 00 00 00 00 00 00 00 00
0x820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x880 03 00 00 5F 10 08 00 00 08 05 00 39 30 00 00 0C
0x890 00 00 00 00 00 0F 0A 07 10 00 26 01 01 53 06 07
0x8A0 10 00 AA 20 5A 04 F0 00 56 56 54 43 94 20 40 00
0x8B0 00 83 11 00 01 04 0A 4C 14 0A 2F 01 6B FF FF 00
0x8C0 00 A0 20 00 00 00 AC 00 1C 00 00 AB 05 30 00 00
0x8D0 0C 14 14 40 06 00 00 10 C8 00 00 00 00 00 31 39
0x8E0 90 39 0C 04 40 20 1C 18 03 00 05 04 03 02 01 01
0x8F0 00 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00
0x900 30 00 00 00 00 00 00 00 00 00 00 00 24 04 47 04
0x910 14 12 12 04 00 03 0A 00 15 35 09 00 02 1F 5F 08
0x920 01 04 05 00 00 00 00 00 00 00 00 00 00 00 00 00
0x930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x940 00 07 00 03 02 00 10 0E 0D 0C 03 04 03 70 0C 00
0x950 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00
0x960 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x970 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x980 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x990 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x9F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Frequency at reset 915000000
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x880 03 00 00 5F 10 08 00 00 08 05 00 39 30 00 00 0C
Change Frequency 434100000
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x880 03 00 00 5F 10 08 00 00 08 05 00 1B 21 99 A0 0C
Changed Frequency 434100000
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
const uint16_t REG_RFFrequency31_24 = 0x088B;
const uint16_t REG_RFFrequency23_16 = 0x088C;
const uint16_t REG_RFFrequency15_8 = 0x088D;
const uint16_t REG_RFFrequency7_0 = 0x088E;
const uint8_t RADIO_WRITE_REGISTER = 0x0D;
const uint8_t RADIO_READ_REGISTER = 0x1D;
const uint8_t RADIO_SET_RFFREQUENCY = 0x86;
const uint8_t DEVICE_SX1261 = 0x01;
const uint8_t DEVICE_SX1262 = 0x00;
const uint8_t DEVICE_SX1268 = 0x02;
//********* Setup hardware definitions here ! *****************
//These are the pin definitions for one of the Tracker boards, be sure to change them to match your
//own setup. You will also need to connect up the pins for the SPI bus
#define NSS 10 //SX126X device select
#define NRESET 9 //SX126X reset pin
#define RFBUSY -1 //SX126X busy pin
#define SW -1 //SW pin on Dorji devices is used to turn RF switch on\off, set to -1 if not used
#define LORA_DEVICE DEVICE_SX1261 //define the device, DEVICE_SX1261, DEVICE_SX1262 or DEVICE_SX1268
//**************************************************************/
#include <SPI.h>
void setup()
{
Serial.begin(9600);
Serial.println(F("2_Register_Test 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 DIO1, DIO2 and DIO3 are not used in this example so are set to -1
if (begin(NSS, NRESET, RFBUSY, -1, -1, -1, SW, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
}
else
{
Serial.println(F("No device responding"));
}
}
void loop()
{
uint32_t frequency;
resetDevice(LORA_DEVICE); //reset the device
Serial.println(F("Registers at reset")); //show the all registers following a reset
printRegisters(0x800, 0x9FF);
Serial.println();
Serial.println();
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Frequency at reset "));
Serial.println(frequency);
printRegisters(0x0880, 0x088F); //show the registers before the frequency change
setRfFrequency(434100000, 0); //change the frequency at reset, in hertz
frequency = getFreqInt(); //read back the changed frequency
Serial.print(F("Change Frequency "));
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
printRegisters(0x0880, 0x088F); //show the registers after frequency change
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Changed Frequency "));
Serial.println(frequency);
Serial.println();
Serial.println();
delay(5000);
}
void readRegisters(uint16_t address, uint8_t *buffer, uint16_t size)
{
uint16_t index;
uint8_t addr_l, addr_h;
addr_h = address >> 8;
addr_l = address & 0x00FF;
checkBusy();
digitalWrite(NSS, LOW);
SPI.transfer(RADIO_READ_REGISTER);
SPI.transfer(addr_h); //MSB
SPI.transfer(addr_l); //LSB
SPI.transfer(0xFF);
for (index = 0; index < size; index++)
{
*(buffer + index) = SPI.transfer(0xFF);
}
digitalWrite(NSS, HIGH);
checkBusy();
}
uint8_t readRegister(uint16_t address)
{
uint8_t data;
readRegisters(address, &data, 1);
return data;
}
void writeRegisters(uint16_t address, uint8_t *buffer, uint16_t size)
{
uint8_t addr_l, addr_h;
uint8_t i;
addr_l = address & 0xff;
addr_h = address >> 8;
checkBusy();
digitalWrite(NSS, LOW);
SPI.transfer(RADIO_WRITE_REGISTER);
SPI.transfer(addr_h); //MSB
SPI.transfer(addr_l); //LSB
for (i = 0; i < size; i++)
{
SPI.transfer(buffer[i]);
}
digitalWrite(NSS, HIGH);
checkBusy();
}
void writeRegister(uint16_t address, uint8_t value)
{
writeRegisters( address, &value, 1 );
}
uint32_t getFreqInt()
{
//get the current set device frequency from registers, return as long integer
uint8_t MsbH, MsbL, Mid, Lsb;
uint32_t uinttemp;
float floattemp;
MsbH = readRegister(REG_RFFrequency31_24);
MsbL = readRegister(REG_RFFrequency23_16);
Mid = readRegister(REG_RFFrequency15_8);
Lsb = readRegister(REG_RFFrequency7_0);
floattemp = ( (MsbH * 0x1000000ul) + (MsbL * 0x10000ul) + (Mid * 0x100ul) + Lsb);
floattemp = ((floattemp * 0.95367431640625) / 1000000ul);
uinttemp = (uint32_t)(floattemp * 1000000);
return uinttemp;
}
void printRegisters(uint16_t Start, uint16_t End)
{
//prints the contents of SX126x 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;) //32 lines
{
Serial.print(F("0x"));
Serial.print((Loopv1), HEX); //print the register number
Serial.print(F(" "));
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
{
RegData = readRegister(Loopv1);
if (RegData < 0x10)
{
Serial.print(F("0"));
}
Serial.print(RegData, HEX); //print the register number
Serial.print(F(" "));
Loopv1++;
}
Serial.println();
}
}
void setRfFrequency( uint32_t frequency, int32_t offset )
{
//Note RF_Freq = freq_reg*32M/(2^25)-----> freq_reg = (RF_Freq * (2^25))/32
uint8_t Rf_Freq[4];
frequency = frequency + offset;
frequency = ( uint32_t )( ( double )frequency / ( double )0.95367431640625 );
checkBusy();
Rf_Freq[0] = (frequency >> 24) & 0xFF; //MSB
Rf_Freq[1] = (frequency >> 16) & 0xFF;
Rf_Freq[2] = (frequency >> 8) & 0xFF;
Rf_Freq[3] = frequency & 0xFF;//LSB
writeCommand(RADIO_SET_RFFREQUENCY, Rf_Freq, 4);
}
void checkBusy()
{
uint8_t busy_timeout_cnt;
busy_timeout_cnt = 0;
while (digitalRead(RFBUSY))
{
delay(1);
busy_timeout_cnt++;
if (busy_timeout_cnt > 10) //wait 10mS for busy to complete
{
busy_timeout_cnt = 0;
Serial.println(F("ERROR - Busy Timeout!"));
break;
}
}
}
void resetDevice(uint8_t device)
{
if ( (device == DEVICE_SX1261) | (device == DEVICE_SX1262) | (device == DEVICE_SX1268) )
{
Serial.println(F("Reset device"));
delay(10);
digitalWrite(NRESET, LOW);
delay(2);
digitalWrite(NRESET, HIGH);
delay(25);
checkBusy();
}
}
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinSW, uint8_t device)
{
pinMode(pinNSS, OUTPUT);
digitalWrite(pinNSS, HIGH);
pinMode(pinNRESET, OUTPUT);
digitalWrite(pinNRESET, LOW);
pinMode(pinRFBUSY, INPUT);
if (pinDIO1 >= 0)
{
pinMode( pinDIO1, INPUT);
}
if (pinDIO2 >= 0)
{
pinMode(pinDIO2, INPUT);
}
if (pinDIO3 >= 0)
{
pinMode(pinDIO3, INPUT);
}
if (pinSW >= 0)
{
pinMode(pinSW, OUTPUT); //Dorji devices have an SW pin that needs to be set high to power antenna switch
digitalWrite(pinSW, HIGH);
}
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(0x88e); //low byte of frequency setting
writeRegister(0x88e, (Regdata1 + 1));
Regdata2 = readRegister(0x88e); //read changed value back
writeRegister(0x88e, Regdata1); //restore register to original value
if (Regdata2 == (Regdata1 + 1))
{
return true;
}
else
{
return false;
}
}
void writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size)
{
uint8_t index;
checkBusy();
digitalWrite(NSS, LOW);
SPI.transfer(Opcode);
for (index = 0; index < size; index++)
{
SPI.transfer(buffer[index]);
}
digitalWrite(NSS, HIGH);
checkBusy();
}

View File

@@ -0,0 +1,123 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 minimum setup LoRa test transmitter. A packet containing the ASCII text
"Hello World 1234567890" is sent using the frequency and LoRa settings specified in the LT.setupLoRa()
command. The pins to access the lora device need to be defined at the top of the program also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used and the packet length. The matching receiver program, '4_LoRa_Receiver' can be used
to check the packets are being sent correctly, the frequency and LoRa settings (in the LT.setupLoRa()
commands) must be the same for the transmitter and receiver programs. Sample Serial Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 PacketsSent,6
For an example of a more detailed configuration for a transmitter, see program 103_LoRa_Transmitter.
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 <SX126XLT.h> //include the appropriate library
SX126XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //SX126X busy pin
#define DIO1 4 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define SW 5 //SW pin on LoRa device, used to power antenna switch
#define LORA_DEVICE DEVICE_SX1261 //we need to define the device we are using
#define TXpower 10 //LoRa transmit power in dBm
uint8_t TXPacketL;
uint32_t TXPacketCount;
uint8_t buff[] = "Hello World 1234567890"; //the message to send
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("3_LoRa_Transmitter Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Transmitter ready"));
Serial.println();
}
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 receiver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
Serial.println();
delay(1000); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
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
}

Some files were not shown because too many files have changed in this diff Show More