commit 9f3ffaba3079be89019e3da068c5d73d5ea45beb Author: Vlad Utkin Date: Tue May 11 20:43:42 2021 +0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..e80666b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e3c18a0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "files.associations": { + "*.old": "cpp", + "array": "cpp", + "deque": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "initializer_list": "cpp" + } +} \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -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 +#include + +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 diff --git a/lib/SX12XX-LoRa/ReadMe.md b/lib/SX12XX-LoRa/ReadMe.md new file mode 100644 index 0000000..7f2dff0 --- /dev/null +++ b/lib/SX12XX-LoRa/ReadMe.md @@ -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. + +Buy Me A Coffee + +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. +
+ +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. + + +
+ + +## 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. + +
+ + + +### Stuart Robinson + +### December 2020 + diff --git a/lib/SX12XX-LoRa/Updates.md b/lib/SX12XX-LoRa/Updates.md new file mode 100644 index 0000000..5bcf984 --- /dev/null +++ b/lib/SX12XX-LoRa/Updates.md @@ -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 diff --git a/lib/SX12XX-LoRa/What is LoRa.md b/lib/SX12XX-LoRa/What is LoRa.md new file mode 100644 index 0000000..d9da98e --- /dev/null +++ b/lib/SX12XX-LoRa/What is LoRa.md @@ -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. + +
+ +### Stuart Robinson +### December 2019 \ No newline at end of file diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/12_ATmel_Sleep_with_Switch_Wakeup/12_ATmel_Sleep_with_Switch_Wakeup.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/12_ATmel_Sleep_with_Switch_Wakeup/12_ATmel_Sleep_with_Switch_Wakeup.ino new file mode 100644 index 0000000..f406504 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/12_ATmel_Sleep_with_Switch_Wakeup/12_ATmel_Sleep_with_Switch_Wakeup.ino @@ -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 + +#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")); + + +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/26A_GPS_Echo_Simple/26A_GPS_Echo_Simple.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/26A_GPS_Echo_Simple/26A_GPS_Echo_Simple.ino new file mode 100644 index 0000000..2e23315 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/26A_GPS_Echo_Simple/26A_GPS_Echo_Simple.ino @@ -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 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"); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/26B_GPS_Echo_Hardware_Serial/26B_GPS_Echo_Hardware_Serial.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/26B_GPS_Echo_Hardware_Serial/26B_GPS_Echo_Hardware_Serial.ino new file mode 100644 index 0000000..137f41b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/26B_GPS_Echo_Hardware_Serial/26B_GPS_Echo_Hardware_Serial.ino @@ -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"); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/26C_GPS_Echo_UBLOXI2C/26C_GPS_Echo_UBLOXI2C.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/26C_GPS_Echo_UBLOXI2C/26C_GPS_Echo_UBLOXI2C.ino new file mode 100644 index 0000000..5453d70 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/26C_GPS_Echo_UBLOXI2C/26C_GPS_Echo_UBLOXI2C.ino @@ -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 +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"); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/26_GPS_Echo/26_GPS_Echo.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/26_GPS_Echo/26_GPS_Echo.ino new file mode 100644 index 0000000..74760cf --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/26_GPS_Echo/26_GPS_Echo.ino @@ -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 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"); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/28_GPS_Checker/28_GPS_Checker.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/28_GPS_Checker/28_GPS_Checker.ino new file mode 100644 index 0000000..a8bff7b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/28_GPS_Checker/28_GPS_Checker.ino @@ -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 //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 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(); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/29_GPS_Checker_With_Display/29_GPS_Checker_With_Display.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/29_GPS_Checker_With_Display/29_GPS_Checker_With_Display.ino new file mode 100644 index 0000000..30b58a1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/29_GPS_Checker_With_Display/29_GPS_Checker_With_Display.ino @@ -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 //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 GPSserial(RXpin, TXpin); + + +#include //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(); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/30_I2C_Scanner/30_I2C_Scanner.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/30_I2C_Scanner/30_I2C_Scanner.ino new file mode 100644 index 0000000..79656a0 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/30_I2C_Scanner/30_I2C_Scanner.ino @@ -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 +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 +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/31_SSD1306_SH1106_OLED_Checker/31_SSD1306_SH1106_OLED_Checker.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/31_SSD1306_SH1106_OLED_Checker/31_SSD1306_SH1106_OLED_Checker.ino new file mode 100644 index 0000000..9a05d5d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/31_SSD1306_SH1106_OLED_Checker/31_SSD1306_SH1106_OLED_Checker.ino @@ -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 +#include + + +#include //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); +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/32_GPS_Checker_Time/32_GPS_Checker_Time.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/32_GPS_Checker_Time/32_GPS_Checker_Time.ino new file mode 100644 index 0000000..83b182e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/32_GPS_Checker_Time/32_GPS_Checker_Time.ino @@ -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 //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 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(); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/34_ATmel_Sleep_with_Watchdog_Wakeup/34_ATmel_Sleep_with_Watchdog_Wakeup.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/34_ATmel_Sleep_with_Watchdog_Wakeup/34_ATmel_Sleep_with_Watchdog_Wakeup.ino new file mode 100644 index 0000000..be156e7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/34_ATmel_Sleep_with_Watchdog_Wakeup/34_ATmel_Sleep_with_Watchdog_Wakeup.ino @@ -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 +#include + +#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 +} + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/37_Servo_Sweep_Tester/37_Servo_Sweep_Tester.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/37_Servo_Sweep_Tester/37_Servo_Sweep_Tester.ino new file mode 100644 index 0000000..83f1525 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/37_Servo_Sweep_Tester/37_Servo_Sweep_Tester.ino @@ -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 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")); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/43_SD_Card_Test/43_SD_Card_Test.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/43_SD_Card_Test/43_SD_Card_Test.ino new file mode 100644 index 0000000..9c78ee2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/43_SD_Card_Test/43_SD_Card_Test.ino @@ -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 +#include + + +#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")); +} + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/45_Battery_Voltage_Read_Test/45_Battery_Voltage_Read_Test.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/45_Battery_Voltage_Read_Test/45_Battery_Voltage_Read_Test.ino new file mode 100644 index 0000000..ed7fb13 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/45_Battery_Voltage_Read_Test/45_Battery_Voltage_Read_Test.ino @@ -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 + } +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/46_I2C_FRAM_Memory_Test/46_I2C_FRAM_Memory_Test.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/46_I2C_FRAM_Memory_Test/46_I2C_FRAM_Memory_Test.ino new file mode 100644 index 0000000..9c0502f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/46_I2C_FRAM_Memory_Test/46_I2C_FRAM_Memory_Test.ino @@ -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 //SX12xx library file for FM24CL64 FRAM, 64kbit, 8kbyte, , I2C addresse 0x50 +#include //SX12xx library file for MB85RC16PNF FRAM, 16kbit, 2kbyte, I2C addresses 0x50 to 0x57 + +#include +#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 + +} + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/46_I2C_FRAM_Memory_Test/I2C_Scanner.h b/lib/SX12XX-LoRa/examples/Hardware_Checks/46_I2C_FRAM_Memory_Test/I2C_Scanner.h new file mode 100644 index 0000000..3ec460a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/46_I2C_FRAM_Memory_Test/I2C_Scanner.h @@ -0,0 +1,84 @@ + // -------------------------------------- + // i2c_scanner + // + // Version 1 + // This program (or code that looks like it) + // can be found in many places. + // For example on the Arduino.cc forum. + // The original author is not know. + // Version 2, Juni 2012, Using Arduino 1.0.1 + // Adapted to be as simple as possible by Arduino.cc user Krodal + // Version 3, Feb 26 2013 + // V3 by louarnold + // Version 4, March 3, 2013, Using Arduino 1.0.3 + // by Arduino.cc user Krodal. + // Changes by louarnold removed. + // Scanning addresses changed from 0...127 to 1...119, + // according to the i2c scanner by Nick Gammon + // http://www.gammon.com.au/forum/?id=10896 + // Version 5, March 28, 2013 + // As version 4, but address scans now to 127. + // A sensor seems to use address 120. + // Version 6, November 27, 2015. + // Added waiting for the Leonardo serial communication. + // + // + // This sketch tests the standard 7-bit addresses + // Devices with higher bit address might not be seen properly. + // + + + //#include + + + void setup_I2CScan() + { + Wire.begin(); + + //Serial.begin(9600); + Serial.println("I2C Scanner"); + } + + + void run_I2CScan() + { + byte error, address; + int nDevices; + + Serial.println("Scanning 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(); + } + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/48_DS18B20_Test/48_DS18B20_Test.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/48_DS18B20_Test/48_DS18B20_Test.ino new file mode 100644 index 0000000..d32de64 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/48_DS18B20_Test/48_DS18B20_Test.ino @@ -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 //get library here > https://github.com/PaulStoffregen/OneWire +OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library + +#include //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 +} + + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/57_NRF24L01_Is_It_There/57_NRF24L01_Is_It_There.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/57_NRF24L01_Is_It_There/57_NRF24L01_Is_It_There.ino new file mode 100644 index 0000000..a5d8890 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/57_NRF24L01_Is_It_There/57_NRF24L01_Is_It_There.ino @@ -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 + +#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(); +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/61_Bluetooth_Test/61_Bluetooth_Test.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/61_Bluetooth_Test/61_Bluetooth_Test.ino new file mode 100644 index 0000000..35cc291 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/61_Bluetooth_Test/61_Bluetooth_Test.ino @@ -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 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"); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/63_QuectelGPS_Firmware_Checker/63_QuectelGPS_Firmware_Checker.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/63_QuectelGPS_Firmware_Checker/63_QuectelGPS_Firmware_Checker.ino new file mode 100644 index 0000000..1dd673b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/63_QuectelGPS_Firmware_Checker/63_QuectelGPS_Firmware_Checker.ino @@ -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 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"); + +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/72A_GPS_Speedo_With_Display/72A_GPS_Speedo_With_Display.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/72A_GPS_Speedo_With_Display/72A_GPS_Speedo_With_Display.ino new file mode 100644 index 0000000..820aaa2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/72A_GPS_Speedo_With_Display/72A_GPS_Speedo_With_Display.ino @@ -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 //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 GPSserial(RXpin, TXpin); + +#include //get library here > https://github.com/olikraus/u8g2 +#include + +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(); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/72_GPS_Speedo/72_GPS_Speedo.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/72_GPS_Speedo/72_GPS_Speedo.ino new file mode 100644 index 0000000..9b93ebf --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/72_GPS_Speedo/72_GPS_Speedo.ino @@ -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 //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 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(); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/77_ILI9341_Display_Checker/77_ILI9341_Display_Checker.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/77_ILI9341_Display_Checker/77_ILI9341_Display_Checker.ino new file mode 100644 index 0000000..47a9d62 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/77_ILI9341_Display_Checker/77_ILI9341_Display_Checker.ino @@ -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); +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/79_Serial_Terminal/79_Serial_Terminal.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/79_Serial_Terminal/79_Serial_Terminal.ino new file mode 100644 index 0000000..2d24860 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/79_Serial_Terminal/79_Serial_Terminal.ino @@ -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 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); + +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/81_BME280_Test/81_BME280_Test.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/81_BME280_Test/81_BME280_Test.ino new file mode 100644 index 0000000..ad1cbaf --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/81_BME280_Test/81_BME280_Test.ino @@ -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 //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 + +#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 +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/88_ATMEGA328P_TEST/88_ATMEGA328P_TEST.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/88_ATMEGA328P_TEST/88_ATMEGA328P_TEST.ino new file mode 100644 index 0000000..8ebf110 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/88_ATMEGA328P_TEST/88_ATMEGA328P_TEST.ino @@ -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 +#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() { + +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/89_ArduinoUniqueID/89_ArduinoUniqueID.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/89_ArduinoUniqueID/89_ArduinoUniqueID.ino new file mode 100644 index 0000000..a7a2401 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/89_ArduinoUniqueID/89_ArduinoUniqueID.ino @@ -0,0 +1,26 @@ +// +// ArduinoUniqueID.ino +// +// Example shows the UniqueID on the Serial Monitor. +// + +#include //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() +{ +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/30_I2C_Scanner/30_I2C_Scanner.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/30_I2C_Scanner/30_I2C_Scanner.ino new file mode 100644 index 0000000..79656a0 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/30_I2C_Scanner/30_I2C_Scanner.ino @@ -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 +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 +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/31_SSD1306_SH1106_OLED_Checker_ESP32/31_SSD1306_SH1106_OLED_Checker_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/31_SSD1306_SH1106_OLED_Checker_ESP32/31_SSD1306_SH1106_OLED_Checker_ESP32.ino new file mode 100644 index 0000000..92795c1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/31_SSD1306_SH1106_OLED_Checker_ESP32/31_SSD1306_SH1106_OLED_Checker_ESP32.ino @@ -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 //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/43_SD_Card_Test_ESP32/43_SD_Card_Test_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/43_SD_Card_Test_ESP32/43_SD_Card_Test_ESP32.ino new file mode 100644 index 0000000..2b49bb1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/43_SD_Card_Test_ESP32/43_SD_Card_Test_ESP32.ino @@ -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 +#include + +//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")); +} + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/44_SD_Card_Test_With_FS_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/44_SD_Card_Test_With_FS_ESP32.ino new file mode 100644 index 0000000..e569dd6 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/44_SD_Card_Test_With_FS_ESP32.ino @@ -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."); +} + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/ESP32_LoRa_Micro_Node.h b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/ESP32_LoRa_Micro_Node.h new file mode 100644 index 0000000..06e4e0f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/ESP32_LoRa_Micro_Node.h @@ -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 + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/testfile.txt b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/testfile.txt new file mode 100644 index 0000000..3f10610 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/44_SD_Card_Test_With_FS_ESP32/testfile.txt @@ -0,0 +1,1062 @@ +# Copyright: Public domain. +# Filename: BURN_BABY_BURN--MASTER_IGNITION_ROUTINE.agc +# Purpose: Part of the source code for Luminary 1A build 099. +# It is part of the source code for the Lunar Module's (LM) +# Apollo Guidance Computer (AGC), for Apollo 11. +# Assembler: yaYUL +# Contact: Ron Burkey . +# Website: www.ibiblio.org/apollo. +# Pages: 731-751 +# Mod history: 2009-05-19 RSB Adapted from the corresponding +# Luminary131 file, using page +# images from Luminary 1A. +# 2009-06-07 RSB Corrected 3 typos. +# 2009-07-23 RSB Added Onno's notes on the naming +# of this function, which he got from +# Don Eyles. +# +# This source code has been transcribed or otherwise adapted from +# digitized images of a hardcopy from the MIT Museum. The digitization +# was performed by Paul Fjeld, and arranged for by Deborah Douglas of +# the Museum. Many thanks to both. The images (with suitable reduction +# in storage size and consequent reduction in image quality as well) are +# available online at www.ibiblio.org/apollo. If for some reason you +# find that the images are illegible, contact me at info@sandroid.org +# about getting access to the (much) higher-quality images which Paul +# actually created. +# +# Notations on the hardcopy document read, in part: +# +# Assemble revision 001 of AGC program LMY99 by NASA 2021112-61 +# 16:27 JULY 14, 1969 + +# Page 731 +## At the get-together of the AGC developers celebrating the 40th anniversary +## of the first moonwalk, Don Eyles (one of the authors of this routine along +## with Peter Adler) has related to us a little interesting history behind the +## naming of the routine. +## +## It traces back to 1965 and the Los Angeles riots, and was inspired +## by disc jockey extraordinaire and radio station owner Magnificent Montague. +## Magnificent Montague used the phrase "Burn, baby! BURN!" when spinning the +## hottest new records. Magnificent Montague was the charismatic voice of +## soul music in Chicago, New York, and Los Angeles from the mid-1950s to +## the mid-1960s. +# BURN, BABY, BURN -- MASTER IGNITION ROUTINE + + BANK 36 + SETLOC P40S + BANK + EBANK= WHICH + COUNT* $$/P40 + +# THE MASTER IGNITION ROUTINE IS DESIGNED FOR USE BY THE FOLLOWING LEM PROGRAMS: P12, P40, P42, P61, P63. +# IT PERFORMS ALL FUNCTIONS IMMEDIATELY ASSOCIATED WITH APS OR DPS IGNITION: IN PARTICULAR, EVERYTHING LYING +# BETWEEN THE PRE-IGNITION TIME CHECK -- ARE WE WITHIN 45 SECONDS OF TIG? -- AND TIG + 26 SECONDS, WHEN DPS +# PROGRAMS THROTTLE UP. +# +# VARIATIONS AMONG PROGRAMS ARE ACCOMODATED BY MEANS OF TABLES CONTAINING CONSTANTS (FOR AVEGEXIT, FOR +# WAITLIST, FOR PINBALL) AND TCF INSTRUCTIONS. USERS PLACE THE ADRES OF THE HEAD OF THE APPROPRIATE TABLE +# (OF P61TABLE FOR P61LM, FOR EXAMPLE) IN ERASABLE REGISTER `WHICH' (E4). THE IGNITION ROUTINE THEN INDEXES BY +# WHICH TO OBTAIN OR EXECUTE THE PROPER TABLE ENTRY. THE IGNITION ROUTINE IS INITIATED BY A TCF BURNBABY, +# THROUGH BANKJUMP IF NECESSARY. THERE IS NO RETURN. +# +# THE MASTER IGNITION ROUTINE WAS CONCEIVED AND EXECUTED, AND (NOTA BENE) IS MAINTAINED BY ADLER AND EYLES. +# +# HONI SOIT QUI MAL Y PENSE +# +# *********************************************** +# TABLES FOR THE IGNITION ROUTINE +# *********************************************** +# +# NOLI SE TANGERE + +P12TABLE VN 0674 # (0) + TCF ULLGNOT # (1) + TCF COMFAIL3 # (2) + TCF GOCUTOFF # (3) + TCF TASKOVER # (4) + TCF P12SPOT # (5) + DEC 0 # (6) NO ULLAGE + EBANK= WHICH + 2CADR SERVEXIT # (7) + + TCF DISPCHNG # (11) + TCF WAITABIT # (12) + TCF P12IGN # (13) + +P40TABLE VN 0640 # (0) + TCF ULLGNOT # (1) + TCF COMFAIL4 # (2) + TCF GOPOST # (3) + TCF TASKOVER # (4) + TCF P40SPOT # (5) +# Page 732 + DEC 2240 # (6) + EBANK= OMEGAQ + 2CADR STEERING # (7) + + TCF P40SJUNK # (11) + TCF WAITABIT # (12) + TCF P40IGN # (13) + TCF REP40ALM # (14) + +P41TABLE TCF P41SPOT # (5) + DEC -1 # (6) + EBANK= OMEGAQ + 2CADR CALCN85 # (7) + + TCF COMMON # (11) + TCF TIGTASK # (12) + +P42TABLE VN 0640 # (0) + TCF WANTAPS # (1) + TCF COMFAIL4 # (2) + TCF GOPOST # (3) + TCF TASKOVER # (4) + TCF P42SPOT # (5) + DEC 2640 # (6) + EBANK= OMEGAQ + 2CADR STEERING # (7) + + TCF P40SJUNK # (11) + TCF WAITABIT # (12) + TCF P42IGN # (13) + TCF P42STAGE # (14) + +P63TABLE VN 0662 # (0) + TCF ULLGNOT # (1) + TCF COMFAIL3 # (2) + TCF V99RECYC # (3) + TCF TASKOVER # (4) + TCF P63SPOT # (5) + DEC 2240 # (6) + EBANK= WHICH + 2CADR SERVEXIT # (7) + + TCF DISPCHNG # (11) + TCF WAITABIT # (12) +# Page 733 + TCF P63IGN # (13) + +ABRTABLE VN 0663 # (0) + TCF ULLGNOT # (1) + TCF COMFAIL3 # (2) + TCF GOCUTOFF # (3) + TCF TASKOVER # (4) + NOOP # (5) + NOOP # (6) + NOOP # (7) + NOOP + TCF DISPCHNG # (11) + TCF WAITABIT # (12) + TCF ABRTIGN # (13) + +# ********************************* +# GENERAL PURPOSE IGNITION ROUTINES +# ********************************* + +BURNBABY TC PHASCHNG # GROUP 4 RESTARTS HERE + OCT 04024 + + CAF ZERO # EXTIRPATE JUNK LEFT IN DVTOTAL + TS DVTOTAL + TS DVTOTAL +1 + + TC BANKCALL # P40AUTO MUST BE BANKCALLED EVEN FROM ITS + CADR P40AUTO # OWN BANK TO SET UP RETURN PROPERLY + +B*RNB*B* EXTEND + DCA TIG # STORE NOMINAL TIG FOR OBLATENESS COMP. + DXCH GOBLTIME # AND FOR P70 OR P71. + + INHINT + TC IBNKCALL + CADR ENGINOF3 + RELINT + + INDEX WHICH + TCF 5 + +P42SPOT = P40SPOT # (5) +P12SPOT = P40SPOT # (5) +P63SPOT = P41SPOT # (5) IN P63 CLOKTASK ALREADY GOING +P40SPOT CS CNTDNDEX # (5) +# Page 734 + TC BANKCALL # MUST BE BANKCALLED FOR GENERALIZED + CADR STCLOK2 # RETURN +P41SPOT TC INTPRET # (5) + DLOAD DSU + TIG + D29.9SEC + STCALL TDEC1 + INITCDUW + BOFF CALL + MUNFLAG + GOMIDAV + CSMPREC + VLOAD MXV + VATT1 + REFSMMAT + VSR1 + STOVL V(CSM) # CSM VELOCITY -- M/CS*2(7) + RATT1 + VSL4 MXV + REFSMMAT + STCALL R(CSM) # CSM POSITION -- M*2(24) + MUNGRAV + STODL G(CSM) # CSM GRAVITY VEC. -- M/CS*2(7) + TAT + STORE TDEC1 # RELOAD TDEC1 FOR MIDTOAV. +GOMIDAV CALRB + MIDTOAV1 + TCF CALLT-35 # MADE IT IN TIME. + + EXTEND # TIG WAS SLIPPED, SO RESET TIG TO 29.9 + DCA PIPTIME1 # SECONDS AFTER THE TIME TO WHICH WE DID + DXCH TIG # INTEGRATE. + EXTEND + DCA D29.9SEC + DAS TIG + +CALLT-35 DXCH MPAC + DXCH SAVET-30 # DELTA-T UNTIL TIG-30 + EXTEND + DCS 5SECDP + DAS SAVET-30 # DELTA-T UNTIL TIG-35 + EXTEND + DCA SAVET-30 + TC LONGCALL + EBANK= TTOGO + 2CADR TIG-35 + + TC PHASCHNG + OCT 20254 # 4.25SPOT FOR TIG-35 RESTART. +# Page 735 + TC CHECKMM + DEC 63 + TCF ENDOFJOB # NOT P63 + CS CNTDNDEX # P63 CAN START DISPLAYING NOW. + TS DISPDEX + TC INTPRET + VLOAD ABVAL + VN1 + STORE ABVEL # INITIALIZE ABVEL FOR P63 DISPLAY + EXIT + TCF ENDOFJOB + +# ******************************** + +TIG-35 CAF 5SEC + TC TWIDDLE + ADRES TIG-30 + + TC PHASCHNG + OCT 40154 # 4.15SPOT FOR TIG-30 RESTART + + CS BLANKDEX # BLANK DSKY FOR 5 SECONDS + TS DISPDEX + + INDEX WHICH + CS 6 # CHECK ULLAGE TIME. + EXTEND + BZMF TASKOVER + CAF 4.9SEC # SET UP TASK TO RESTORE DISPLAY AT TIG-30 + TC TWIDDLE + ADRES TIG-30.1 + + CAF PRIO17 # A NEGATIVE ULLAGE TIME INDICATES P41, IN + TC NOVAC # WHICH CASE WE HAVE TO SET UP A JOB TO + EBANK= TTOGO # BLANK THE DSKY FOR FIVE SECONDS, SINCE + 2CADR P41BLANK # CLOKJOB IS NOT RUNNING DURING P41. + + TCF TASKOVER + +P41BLANK TC BANKCALL # BLANK DSKY. + CADR CLEANDSP + TCF ENDOFJOB + +TIG-30.1 CAF PRIO17 # SET UP JOB TO RESTORE DISPLAY AT TIG-30 + TC NOVAC + EBANK= TTOGO + 2CADR TIG-30A + + TCF TASKOVER +# Page 736 +TIG-30A CAF V16N85B + TC BANKCALL # RESTORE DISPLAY. + CADR REGODSP # REGODSP DOES A TCF ENDOFJOB + +# ******************************** + +TIG-30 CAF S24.9SEC + TC TWIDDLE + ADRES TIG-5 + + CS CNTDNDEX # START UP CLOKTASK AGAIN + TS DISPDEX + + INDEX WHICH # PICK UP APPROPRIATE ULLAGE -- ON TIME + CA 6 # Was CAF --- RSB 2009. + EXTEND + BZMF ULLGNOT # DON'T SET UP ULLAGE IF DT IS NEG OR ZERO + TS SAVET-30 # SAVE DELTA-T FOR RESTART + TC TWIDDLE + ADRES ULLGTASK + + CA THREE # RESTART PROTECT ULLGTASK (1.3SPOT) + TS L + CS THREE + DXCH -PHASE1 + CS TIME1 + TS TBASE1 + + INDEX WHICH + TCF 1 + +WANTAPS CS FLGWRD10 # (1) FOR P42 ENSURE APSFLAG IS SET. IF IT + MASK APSFLBIT # WASN'T SET, DAP WILL BE INITIALIZED TO + ADS FLGWRD10 # ASCENT VALUES BY 1/ACCS IN 2 SECONDS. + +ULLGNOT EXTEND # (1) + INDEX WHICH + DCA 7 # LOAD AVEGEXIT WITH APPROPRIATE 2CADR + DXCH AVEGEXIT + + CAF TWO # 4.2SPOT RESTARTS IMMEDIATELY AT REDO4.2 + TS L + CS TWO # AND ALSO AT TIG-5 AT THE CORRECT TIME. + DXCH -PHASE4 + + CS TIME1 + TS TBASE4 # SET TBASE4 FOR TIG-5 RESTART + +REDO2.17 EXTEND +# Page 737 + DCA NEG0 # CLEAR OUT GROUP 2 SO LAMBERT CAN START + DXCH -PHASE2 # IF NEEDED. + +REDO4.2 CCS PHASE5 # IF SERVICER GOING? + TCF TASKOVER # YES, DON'T START IT UP AGAIN. + + TC POSTJUMP + CADR PREREAD # PREREAD END THIS TASK + +# ********************************* + +ULLGTASK TC ONULLAGE # THIS COMES AT TIG-7.5 OR TIG-3.5 + TC PHASCHNG + OCT 1 + TCF TASKOVER + +# ********************************* + +TIG-5 EXTEND + DCA NEG0 # INSURE THAT GROUP 3 IS INACTIVE. + DXCH -PHASE3 + + CAF 5SEC + TC TWIDDLE + ADRES TIG-0 + + TC DOWNFLAG # RESET IGNFLAG AND ASINFLAG + ADRES IGNFLAG # FOR LIGHT-UP LOGIC. + TC DOWNFLAG + ADRES ASTNFLAG + + INDEX WHICH + TCF 11 + +P40SJUNK CCS PHASE3 # (11) P40 AND P42. S40.13 IN PROGRESS? + TCF DISPCHNG # YES + + CAF PRIO20 + TC FINDVAC + EBANK= TTOGO + 2CADR S40.13 + + TC PHASCHNG # 3.5SPOT FOR S40.13 + OCT 00053 +DISPCHNG CS VB99DEX # (11) + TS DISPDEX + +# Page 738 +COMMON TC PHASCHNG # RESTART TIG-0 (4.7SPOT) + OCT 40074 + TCF TASKOVER + +# ********************************* + +TIG-0 CS FLAGWRD7 # SET IGNFLAG SINCE TIG HAS ARRIVED + MASK IGNFLBIT + ADS FLAGWRD7 + + TC CHECKMM # IN P63 CASE, THROTTLE-UP IS ZOOMTIME + DEC 63 # AFTER NOMINAL IGNITION, NOT ACTUAL + TCF IGNYET? + CA ZOOMTIME + TC WAITLIST + EBANK= DVCNTR + 2CADR P63ZOOM + + TC 2PHSCHNG + OCT 40033 + + OCT 05014 + OCT 77777 + +IGNYET? CAF ASTNBIT # CHECK ASTNFLAG: HAS ASTRONAUT RESPONDED + MASK FLAGWRD7 # TO OUR ENGINE ENABLE REQUEST? + EXTEND + INDEX WHICH + BZF 12 # BRANCH IF HE HAS NOT RESPONDED YET + +IGNITION CS FLAGWRD5 # INSURE ENGONFLG IS SET. + MASK ENGONBIT + ADS FLAGWRD5 + CS PRIO30 # TURN ON THE ENGINE. + EXTEND + RAND DSALMOUT + AD BIT13 + EXTEND + WRITE DSALMOUT + EXTEND # SET TEVENT FOR DOWNLINK + DCA TIME2 + DXCH TEVENT + + EXTEND # UPDATE TIG USING TGO FROM S40.13 + DCA TGO + DXCH TIG + EXTEND + DCA TIME2 + DAS TIG + +# Page 739 + CS FLUNDBIT # PERMIT GUIDANCE LOOP DISPLAYS + MASK FLAGWRD8 + TS FLAGWRD8 + + INDEX WHICH + TCF 13 + +P63IGN EXTEND # (13) INITIATE BURN DISPLAYS + DCA DSP2CADR + DXCH AVGEXIT + + CA Z # ASSASSINATE CLOKTASK + TS DISPDEX + + CS FLAGWRD9 # SET FLAG FOR P70-P71 + MASK LETABBIT + ADS FLAGWRD9 + + CS FLAGWRD7 # SET SWANDISP TO ENABLE R10. + MASK SWANDBIT + ADS FLAGWRD7 + + CS PULSES # MAKE SURE DAP IS NOT IN MINIMUM-IMPULSE + MASK DAPBOOLS # MODE, IN CASE OF SWITCH TO P66 + TS DAPBOOLS + + EXTEND # INITIALIZE TIG FOR P70 AND P71. + DCA TIME2 + DXCH TIG + + CAF ZERO # INITIALIZE WCHPHASE, AND FLPASS0 + TS WCHPHASE + TS WCHPHOLD # ALSO WHCPHOLD + CA TWO + TS FLPASS0 + + TCF P42IGN +P40IGN CS FLAGWRD5 # (13) + MASK NOTHRBIT + EXTEND + BZF P42IGN + CA ZOOMTIME + TC WAITLIST + EBANK= DVCNTR + 2CADR P40ZOOM + +P63IGN1 TC 2PHSCHNG + OCT 40033 # 3.3SPOT FOR ZOOM RESTART. + OCT 05014 # TYPE C RESTARTS HERE IMMEDIATELY + OCT 77777 + +# Page 740 + TCF P42IGN +P12IGN CAF EBANK6 + TS EBANK + EBANK= AOSQ + + CA IGNAOSQ # INITIALIZE DAP BIAS ACCELERATION + TS AOSQ # ESTIMATES AT P12 IGNITION. + CA IGNAOSR + TS AOSR + + CAF EBANK7 + TS EBANK + EBANK= DVCNTR + +ABRTIGN CA Z # (13) KILL CLOKTASK + TS DISPDEX + + EXTEND # CONNECT ASCENT GYIDANCE TO SERVICER. + DCA ATMAGADR + DXCH AVGEXIT + + CS FLAGWRD7 # ENABLE R10. + MASK SWANDBIT + ADS FLAGWRD7 + +P42IGN CS DRIFTBIT # ENSURE THAT POWERED-FLIGHT SWITCHING + MASK DAPBOOLS # CURVES ARE USED. + TS DAPBOOLS + CAF IMPULBIT # EXAMINE IMPULSE SWITCH + MASK FLAGWRD2 + CCS A + TCF IMPLBURN + +DVMONCON TC DOWNFLAG + ADRES IGNFLAG # CONNECT DVMON + TC DOWNFLAG + ADRES ASTNFLAG + TC DOWNFLAG + ADRES IDLEFLAG + + TC PHASCHNG + OCT 40054 + + TC FIXDELAY # TURN ULLAGE OFF HALF A SECOND AFTER + DEC 50 # LIGHT UP. + +ULLAGOFF TC NOULLAGE + +WAITABIT EXTEND # KILL GROUP 4 + DCA NEG0 +# Page 741 + DXCH -PHASE4 + + TCF TASKOVER + +TIGTASK TC POSTJUMP # (12) + CADR TIGTASK1 + +# ******************************** + + BANK 31 + SETLOC P40S3 + BANK + COUNT* $$/P40 + +TIGTASK1 CAF PRIO16 + TC NOVAC + EBANK= TRKMKCNT + 2CADR TIGNOW + + TC PHASCHNG + OCT 6 # KILL GROUP 6 + + TCF TASKOVER + +# ******************************** + +P63ZOOM EXTEND + DCA LUNLANAD + DXCH AVEGEXIT + + TC IBNKCALL + CADR FLATOUT + TCF P40ZOOMA + +P40ZOOM CAF BIT13 + TS THRUST + CAF BIT4 + + EXTEND + WOR CHAN14 + +P40ZOOMA TC PHASCHNG + OCT 3 + TCF TASKOVER + + EBANK= DVCNTR +LUNLANAD 2CADR LUNLAND + +# Page 742 +ZOOM = P40ZOOMA + BANK 36 + SETLOC P40S + BANK + COUNT* $$/P40 + +# ******************************** + +COMFAIL TC UPFLAG # (15) + ADRES IDLEFLAG + TC UPFLAG # SET FLAG TO SUPPRESS CONFLICTING DISPLAY + ADRES FLUNDISP + CAF FOUR # RESET DVMON + TS DVCNTR + CCS PHASE6 # CLOCKTASK ACTIVE? + TCF +3 # YES + TC BANKCALL # OTHERWISE, START IT UP + CADR STCLOK1 + +3 CS VB97DEX + TS DISPDEX + TC PHASCHNG # TURN OFF GROUP 4. + OCT 00004 + TCF ENDOFJOB + +COMFAIL1 INDEX WHICH + TCF 2 + +COMFAIL3 CA Z # (15) KILL CLOKTASK USING Z + TCF +2 + +COMFAIL4 CS CNTDNDEX + TS DISPDEX + + TC DOWNFLAG # RECONNECT DV MONITOR + ADRES IDLEFLAG + TC DOWNFLAG # PERMIT GUIDANCE LOOP DISPLAYS + ADRES FLUNDISP + TCF ENDOFJOB + +COMFAIL2 TC PHASCHNG # KILL ZOOM RESTART PROTECTION + OCT 00003 + + INHINT + TC KILLTASK # KILL ZOOM IN CASE IT'S STILL TO COME + CADR ZOOM + TC IBNKCALL # COMMAND ENGINE OFF + CADR ENGINOF4 + TC UPFLAG # SET THE DRIFT BIT FOR THE DAP. + ADRES DRIFTDFL +# Page 743 + TC INVFLAG # USE OTHER RCS SYSTEM + ADRES AORBTFLG + TC UPFLAG # TURN ON ULLAGE + ADRES ULLAGFLG + CAF BIT1 + INHINT + TC TWIDDLE + ADRES TIG-5 + TCF ENDOFJOB + +# *********************************** +# SUBROUTINES OF THE IGNITION ROUTINE +# *********************************** + +INVFLAG CA Q + TC DEBIT + COM + EXTEND + RXOR LCHAN + TCF COMFLAG + +# *********************************** + +NOULLAGE CS ULLAGER # MUST BE CALLED IN A TASK OR UNDER INHINT + MASK DAPBOOLS + TS DAPBOOLS + TC Q + +# *********************************** + +ONULLAGE CS DAPBOOLS # TURN ON ULLAGE. MUST BE CALLED IN + MASK ULLAGER # A TASK OR WHILE INHINTED. + ADS DAPBOOLS + TC Q + +# *********************************** + +STCLOK1 CA ZERO # THIS ROUTINE STARTS THE COUNT-DOWN +STCLOK2 TS DISPDEX # (CLOKTASK AND CLOKJOB). SETTING +STCLOK3 TC MAKECADR # SETTING DISPDEX POSITIVE KILLS IT. + TS TBASE4 # RETURN SAVE (NOT FOR RESTARTS). + EXTEND + DCA TIG + DXCH MPAC + EXTEND + DCS TIME2 +# Page 744 + DAS MPAC # HAVE TIG -- TIME2, UNDOUBTEDLY A + NUMBER + TC TPAGREE # POSITIVE, SINCE WE PASSED THE + CAF 1SEC # 45 SECOND CHECK. + TS Q + DXCH MPAC + MASK LOW5 # RESTRICT MAGNITUDE OF NUMBER IN A + EXTEND + DV Q + CA L # GET REMAINDER + AD TWO + INHINT + TC TWIDDLE + ADRES CLOKTASK + TC 2PHSCHNG + OCT 40036 # 6.3SPOT FOR CLOKTASK + OCT 05024 + OCT 13000 + + CA TBASE4 + TC BANKJUMP + +CLOKTASK CS TIME1 # SET TBASE6 FOR GROUP 6 RESTART + TS TBASE6 + + CCS DISPDEX + TCF KILLCLOK + NOOP + CAF PRIO27 + TC NOVAC + EBANK= TTOGO + 2CADR CLOKJOB + + TC FIXDELAY # WAIT A SECOND BEFORE STARTING OVER + DEC 100 + TCF CLOKTASK + +KILLCLOK EXTEND # KILL RESTART + DCA NEG0 + DXCH -PHASE6 + TCF TASKOVER + +CLOKJOB EXTEND + DCS TIG + DXCH TTOGO + EXTEND +# Page 745 + DCA TIME2 + DAS TTOGO + INHINT + CCS DISPDEX # IF DISPDEX HAS BEEN SET POSITIVE BY A + TCF ENDOFJOB # TASK OR A HIGHER PRIORITY JOB SINCE THE + TCF ENDOFJOB # LAST CLOKTASK, AVOID USING IT AS AN + COM # INDEX. + RELINT # ***** DISPDEX MUST NEVER B -0 ***** + INDEX A + TCF DISPNOT -1 # (-1 DUE TO EFFECT OF CCS) + +VB97DEX = OCT35 # NEGATIVE OF THIS IS PROPER FOR DISPDEX + + -35 CS ZERO # INDICATE VERB 97 PASTE + TS NVWORD1 + CA NVWORD +2 # NVWORD+2 CONTAINS V06 & APPROPRIATE NOUN + TC BANKCALL + CADR CLOCPLAY + TCF STOPCLOK # TERMINATE CLOKTASK ON THE WAY TO P00H + TCF COMFAIL1 + TCF COMFAIL2 + + # THIS DISPLAY IS CALLED VIA ASTNCLOK + -25 CAF V06N61 # IT IS PRIMARILY USED BY THE CREW IN P63 + TC BANKCALL # TO RESET HIS EVENT TIMER TO AGREE WITH + CADR REFLASH # TIG. + TCF STOPCLOK + TCF ASTNRETN + TCF -6 + +CNTDNDEX = LOW4 # OCT17: NEGATIVE PROPER FOR DISPDEX + + -17 INDEX WHICH # THIS DISPLAY COMES UP AT ONE SECOND + # Was CAF --- RSB 2009 + CA 0 # INTERVALS. IT IS NORMALLY OPERATED + TC BANKCALL # BETWEEN TIG-30 SECONDS AND TIG-5 SECONDS + CADR REGODSP # REGODSP DOES ITS OWN TCF ENDOFJOB + +VB99DEX = ELEVEN # OCT13: NEGATIVE PROPER FOR DISPDEX + +V99RECYC EQUALS + + -13 CS BIT9 # INDICATE VERB 99 PASTE + TS NVWORD1 + INDEX WHICH # THIS IS THE "PLEASE ENABLE ENGINE" + # Was CAF --- RSB 2004 + CA 0 # DISPLAY; IT IS INITIATED AT TIG-5 SEC. + TC BANKCALL # THE DISPLAY IS A V99NXX, WHERE XX IS + CADR CLOCPLAY # NOUN THAT HAD PREVIOUSLY BEEN DISPLAYED + TCF STOPCLOK # TERMINATE GOTOP00H TURNS OFF ULLAGE. + TCF *PROCEED + TCF *ENTER + +# Page 746 +BLANKDEX = TWO # NEGATIVE OF THIS IS PROPER FOR DISPDEX + + -2 TC BANKCALL # BLANK DSKY. THE DSKY IS BLANKED FOR + CADR CLEANDSP # 5 SECONDS AT TIG-35 TO INDICATE THAT +DISPNOT TCF ENDOFJOB # AVERAGE G IS STARTING. + +STOPCLOK TC NULLCLOK # STOP CLOKTASK & TURN OFF ULLAGE ON THE + TCF GOTOP00H # WAY TO P00 (GOTOP00H RELINTS) + +NULLCLOK INHINT + EXTEND + QXCH P40/RET + TC NOULLAGE # TURN OFF ULLAGE ... + TC KILLTASK # DON'T LET IT COME ON, EITHER ... + CADR ULLGTASK + TC PHASCHNG # NOT EVEN IF THERE'S A RESTART. + OCT 1 + CA Z # KILL CLOKTASK + TS DISPDEX + TC P40/RET + +ASTNRETN TC PHASCHNG + OCT 04024 + CAF ZERO # STOP DISPLAYING BUT KEEP RUNNING + TS DISPDEX + CAF PRIO13 + TC FINDVAC + EBANK= STARIND + 2CADR ASTNRET + + TCF ENDOFJOB + +*PROCEED TC UPFLAG + ADRES ASTNFLAG + + TCF IGNITE + +*ENTER INHINT + INDEX WHICH + TCF 3 + +GOPOST CAF PRIO12 # (3) MUST BE LOWER PRIORITY THAN CLOKJOB + TC FINDVAC + EBANK= TTOGO + 2CADR POSTBURN + +# Page 747 + INHINT # SET UP THE DAP FOR COASTING FLIGHT. + TC IBNKCALL + CADR ALLCOAST + TC NULLCLOK + TC PHASCHNG # 4.13 RESTART FOR POSTBURN + OCT 00134 + + TCF ENDOFJOB + +GOCUTOFF CAF PRIO17 # (3) + TC FINDVAC + EBANK= TGO + 2CADR CUTOFF + + TC DOWNFLAG + ADRES FLUNDISP + + INHINT # SET UP THE DAP FOR COASTING FLIGHT. + TC IBNKCALL + CADR ALLCOAST + TC NULLCLOK + TC PHASCHNG + OCT 07024 + OCT 17000 + EBANK= TGO + 2CADR CUTOFF + + TCF ENDOFJOB + +IGNITE CS FLAGWRD7 # (2) + MASK IGNFLBIT + CCS A + TCF IGNITE1 + CAF BIT1 + INHINT + TC TWIDDLE + ADRES IGNITION + + CAF OCT23 # IMMEDIATE RESTART AT IGNITION + TS L + COM + DXCH -PHASE4 + +IGNITE1 CS CNTDNDEX # RESTORE OLD DISPLAY. + TS DISPDEX + + TCF ENDOFJOB + +# Page 748 +# ******************************** + +P40ALM TC ALARM # PROGRAM SELECTION NOT CONSISTENT WITH + OCT 1706 # VEHICLE CONFIGURATION + +REP40ALM CAF V05N09 # (14) + TC BANKCALL + CADR GOFLASH + + TCF GOTOP00H # V34E TERMINATE + TCF +2 # PROCEED CHECK FOR P42 + TCF REP40ALM # V32E REDISPLAY ALARM + + INDEX WHICH # FOR P42, ALLOW CREW TO PROCEED EVEN + TCF 14 # THOUGH VEHICLE IS UNSTAGED. + +# ******************************** + + BANK 31 + SETLOC P40S2 + BANK + + COUNT* $$/P40 + +P40AUTO TC MAKECADR # HELLO THERE. + TS TEMPR60 # FOR GENERALIZED RETURN TO OTHER BANKS. +P40A/P TC BANKCALL # SUBROUTINE TO CHECK PGNCS CONTROL + CADR G+N,AUTO # AND AUTO STABILIZATION MODES + CCS A # +0 INDICATES IN PGNCS, IN AUTO + TCF TURNITON # + INDICATES NOT IN PGNCS AND/OR AUTO + CAF APSFLBIT # ARE WE ON THE DESCENT STAGE? + MASK FLGWRD10 + CCS A + TCF GOBACK # RETURN + CAF BIT5 # YES, CHECK FOR AUTO-THROTTLE MODE + EXTEND + RAND CHAN30 + EXTEND + BZF GOBACK # IN AUTO-THROTTLE MODE -- RETURN +TURNITON CAF P40A/PMD # DISPLAYS V50N25 R1=203 PLEASE PERFORM + TC BANKCALL # CHECKLIST 203 TURN ON PGNCS ETC. + CADR GOPERF1 + TCF GOTOP00H # V34E TERMINATE + TCF P40A/P # RECYCLE +GOBACK CA TEMPR60 + TC BANKJUMP # GOODBYE. COME AGAIN SOON. + +P40A/PMD OCT 00203 + +# Page 749 + BANK 36 + SETLOC P40S + BANK + + COUNT* $$/P40 + +# ********************************** +# CONSTANTS FOR THE IGNITION ROUTINE +# ********************************** + +SERVCADR = P63TABLE +7 + +P40ADRES ADRES P40TABLE + +P41ADRES ADRES P41TABLE -5 + +P42ADRES ADRES P42TABLE + + EBANK= DVCNTR +DSP2CADR 2CADR P63DISPS -2 + + EBANK= DVCNTR +ATMAGADR 2CADR ATMAG + +? = GOTOP00H + +D29.9SEC 2DEC 2990 + +S24.9SEC DEC 2490 + +4.9SEC DEC 490 + +OCT20 = BIT5 + +V06N61 VN 0661 + +# Page 750 +# KILLTASK +# MOD NO: NEW PROGRAM +# MOD BY: COVELLI +# +# FUNCTIONAL DESCRIPTION: +# +# KILLTASK IS USED TO REMOVE A TASK FROM THE WAITLIST BY SUBSTITUTING A NULL TASK CALLED `NULLTASK' (OF COURSE), +# WHICH MERELY DOES A TC TASKOVER. IF THE SAME TASK IS SCHEDULED MORE THAN ONCE, ONLY THE ONE WHICH WILL OCCUR +# FIRST IS REMOVED. IF THE TASK IS NOT SCHEDULED, KILLTASK TAKES NO ACTION AND RETURNS WITH NO ALARM. KILLTASK +# LEAVES INTERRUPTS INHIBITED SO CALLER MUST RELINT +# +# CALLING SEQUENCE +# L TC KILLTASK # IN FIXED-FIXED +# L+1 CADR ???????? # CADR (NOT 2CADR) OF TASK TO BE REMOVED. +# L+2 (RELINT) # RETURN +# +# EXIT MODE: AT L+2 OF CALLING SEQUENCE. +# +# ERASABLE INITIALIZATION: NONE. +# +# OUTPUT: 2CADR OF NULLTASK IN LST2 +# +# DEBRIS: ITEMP1 - ITEMP4, A, L, Q. + + EBANK= LST2 + BLOCK 3 # KILLTASK MUST BE IN FIXED-FIXED. + SETLOC FFTAG6 + BANK + COUNT* $$/KILL +KILLTASK CA KILLBB + INHINT + LXCH A + INDEX Q + CA 0 # GET CADR. + LXCH BBANK + TCF KILLTSK2 # CONTINUE IN SWITCHED FIXED. + + EBANK= LST2 +KILLBB BBCON KILLTSK2 + + BANK 27 + + SETLOC P40S1 + BANK + COUNT* $$/KILL + +KILLTSK2 LXCH ITEMP2 # SAVE CALLER'S BBANK +# Page 751 + INCR Q + EXTEND + QXCH ITEMP1 # RETURN 2ADR IN ITEMP1,ITEMP2 + + TS ITEMP3 # CADR IS IN A + MASK LOW10 + AD BIT11 + TS ITEMP4 # GENADR OF TASK + + CS LOW10 + MASK ITEMP3 + TS ITEMP3 # FBANK OF TASK + + ZL +ADRSCAN INDEX L + CS LST2 + AD ITEMP4 # COMPARE GENADRS + EXTEND + BZF TSTFBANK # IF THEY MATCH, COMPARE FBANKS +LETITLIV CS LSTLIM + AD L + EXTEND # ARE WE DONE? + BZF DEAD # YES -- DONE, SO RETURN + INCR L + INCR L + TCF ADRSCAN # CONTINUE LOOP. + +DEAD DXCH ITEMP1 + DTCB + +TSTFBANK CS LOW10 + INDEX L + MASK LST2 +1 # COMPARE FBANKS ONLY. + EXTEND + SU ITEMP3 + EXTEND + BZF KILLDEAD # MATCH -- KILL IT. + TCF LETITLIV # NO MATCH -- CONTINUE. + +KILLDEAD CA TCTSKOVR + INDEX L + TS LST2 # REMOVE TASK BY INSERTING TASKOVER + TCF DEAD + +LSTLIM EQUALS BIT5 # DEC 16 + + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/45_Battery_Voltage_Read_Test_ESP32/45_Battery_Voltage_Read_Test_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/45_Battery_Voltage_Read_Test_ESP32/45_Battery_Voltage_Read_Test_ESP32.ino new file mode 100644 index 0000000..edeb8e0 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/45_Battery_Voltage_Read_Test_ESP32/45_Battery_Voltage_Read_Test_ESP32.ino @@ -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 + } + +} + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/47_DeepSleep_Timed_Wakeup_ESP32/47_DeepSleep_Timed_Wakeup_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/47_DeepSleep_Timed_Wakeup_ESP32/47_DeepSleep_Timed_Wakeup_ESP32.ino new file mode 100644 index 0000000..368769d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/47_DeepSleep_Timed_Wakeup_ESP32/47_DeepSleep_Timed_Wakeup_ESP32.ino @@ -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 + } + +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/50_LightSleep_Timed_Wakeup_ESP32/50_LightSleep_Timed_Wakeup_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/50_LightSleep_Timed_Wakeup_ESP32/50_LightSleep_Timed_Wakeup_ESP32.ino new file mode 100644 index 0000000..7e6c4bc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/50_LightSleep_Timed_Wakeup_ESP32/50_LightSleep_Timed_Wakeup_ESP32.ino @@ -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 + } + +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/51_DeepSleep_Switch_Wakeup_ESP32/51_DeepSleep_Switch_Wakeup_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/51_DeepSleep_Switch_Wakeup_ESP32/51_DeepSleep_Switch_Wakeup_ESP32.ino new file mode 100644 index 0000000..a557fb3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/51_DeepSleep_Switch_Wakeup_ESP32/51_DeepSleep_Switch_Wakeup_ESP32.ino @@ -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 + +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/64_WiFi_Scanner_Display_ESP32/64_WiFi_Scanner_Display_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/64_WiFi_Scanner_Display_ESP32/64_WiFi_Scanner_Display_ESP32.ino new file mode 100644 index 0000000..ca83477 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/64_WiFi_Scanner_Display_ESP32/64_WiFi_Scanner_Display_ESP32.ino @@ -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 //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")); +} diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/64_WiFi_Scanner_Display_ESP32/ESP32_LoRa_Micro_Node.h b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/64_WiFi_Scanner_Display_ESP32/ESP32_LoRa_Micro_Node.h new file mode 100644 index 0000000..73abaf9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/64_WiFi_Scanner_Display_ESP32/ESP32_LoRa_Micro_Node.h @@ -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 + + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/81_BME280_Test_ESP32/81_BME280_Test_ESP32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/81_BME280_Test_ESP32/81_BME280_Test_ESP32.ino new file mode 100644 index 0000000..f1aeeda --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/ESP32/81_BME280_Test_ESP32/81_BME280_Test_ESP32.ino @@ -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 //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 + +#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 +} + diff --git a/lib/SX12XX-LoRa/examples/Hardware_Checks/STM32/31_SSD1306_OLED_Checker_STM32/31_SSD1306_OLED_Checker_STM32.ino b/lib/SX12XX-LoRa/examples/Hardware_Checks/STM32/31_SSD1306_OLED_Checker_STM32/31_SSD1306_OLED_Checker_STM32.ino new file mode 100644 index 0000000..5fa0ce1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/Hardware_Checks/STM32/31_SSD1306_OLED_Checker_STM32/31_SSD1306_OLED_Checker_STM32.ino @@ -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 //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/ReadMe.md b/lib/SX12XX-LoRa/examples/ReadMe.md new file mode 100644 index 0000000..3d03dba --- /dev/null +++ b/lib/SX12XX-LoRa/examples/ReadMe.md @@ -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             (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             (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             (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             (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. +
+ +#### 5\_LoRa\_TX\_Sleep\_Timed\_Wakeup\_Atmel             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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             (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. + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/103_LoRa_Transmitter_Detailed_Setup.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/103_LoRa_Transmitter_Detailed_Setup.ino new file mode 100644 index 0000000..edd1db9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/103_LoRa_Transmitter_Detailed_Setup.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/Settings.h new file mode 100644 index 0000000..8bed135 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/104_LoRa_Receiver_Detailed_Setup.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/104_LoRa_Receiver_Detailed_Setup.ino new file mode 100644 index 0000000..a4146ac --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/104_LoRa_Receiver_Detailed_Setup.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/Settings.h new file mode 100644 index 0000000..dd7295e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/Settings.h @@ -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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino new file mode 100644 index 0000000..572a7b5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino @@ -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 +#include +#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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/14_LoRa_Structure_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/14_LoRa_Structure_TX/Settings.h new file mode 100644 index 0000000..7bc656f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/14_LoRa_Structure_TX/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino new file mode 100644 index 0000000..7cdc034 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino @@ -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 +#include +#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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/15_LoRa_Structure_RX/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/15_LoRa_Structure_RX/Settings.h new file mode 100644 index 0000000..e5ad937 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/15_LoRa_Structure_RX/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/1_LED_Blink/1_LED_Blink.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/1_LED_Blink/1_LED_Blink.ino new file mode 100644 index 0000000..2865c0a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/1_LED_Blink/1_LED_Blink.ino @@ -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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/2_Register_Test/2_Register_Test.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/2_Register_Test/2_Register_Test.ino new file mode 100644 index 0000000..0754ea4 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/2_Register_Test/2_Register_Test.ino @@ -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 + + +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(); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino new file mode 100644 index 0000000..ae46757 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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 +} + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino new file mode 100644 index 0000000..3d2d920 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/58_FM_Tone/58_FM_Tone.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/58_FM_Tone/58_FM_Tone.ino new file mode 100644 index 0000000..5c224ed --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/58_FM_Tone/58_FM_Tone.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/58_FM_Tone/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/58_FM_Tone/Settings.h new file mode 100644 index 0000000..f32a364 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Basics/58_FM_Tone/Settings.h @@ -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 + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino new file mode 100644 index 0000000..45a5bb6 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino @@ -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 +#include +#include +#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(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h new file mode 100644 index 0000000..df4699d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h @@ -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 + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino new file mode 100644 index 0000000..59f62e3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino @@ -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 +#include +#include "Settings.h" +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h new file mode 100644 index 0000000..9ab7049 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino new file mode 100644 index 0000000..7802beb --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino @@ -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 +#include +#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(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h new file mode 100644 index 0000000..42b8fa5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h @@ -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 + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino new file mode 100644 index 0000000..61054a2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc +#include + +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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h new file mode 100644 index 0000000..f878524 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h @@ -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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino new file mode 100644 index 0000000..37e873d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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 //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h new file mode 100644 index 0000000..ec2dd6b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h @@ -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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino new file mode 100644 index 0000000..0256384 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include +#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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h new file mode 100644 index 0000000..32fbd9a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h @@ -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 + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/60_LoRa_Packet_Logger_Receiver_SD.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/60_LoRa_Packet_Logger_Receiver_SD.ino new file mode 100644 index 0000000..432e141 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/60_LoRa_Packet_Logger_Receiver_SD.ino @@ -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 + +#include //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 LT; + +#include "Settings.h" +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/SD_Logger_Library.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/SD_Logger_Library.h new file mode 100644 index 0000000..a8c868a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/SD_Logger_Library.h @@ -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)); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/Settings.h new file mode 100644 index 0000000..bdd505a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/Settings.h @@ -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 diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/103_LoRa_Transmitter_Detailed_Setup_ESP32.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/103_LoRa_Transmitter_Detailed_Setup_ESP32.ino new file mode 100644 index 0000000..7518c4c --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/103_LoRa_Transmitter_Detailed_Setup_ESP32.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/Settings.h new file mode 100644 index 0000000..49206f1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/104_LoRa_Receiver_Detailed_Setup_ESP32.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/104_LoRa_Receiver_Detailed_Setup_ESP32.ino new file mode 100644 index 0000000..719a09f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/104_LoRa_Receiver_Detailed_Setup_ESP32.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/Settings.h new file mode 100644 index 0000000..2d257c7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/Settings.h @@ -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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino new file mode 100644 index 0000000..4062747 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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 +} + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg new file mode 100644 index 0000000..19b2873 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg new file mode 100644 index 0000000..ff18459 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Shield.jpg b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Shield.jpg new file mode 100644 index 0000000..7f1c2bf Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/Pictures/ESP32_Shield.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/ReadMe.md b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/ReadMe.md new file mode 100644 index 0000000..f33e6f5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ESP32/ReadMe.md @@ -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. + +
+ +**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 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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino new file mode 100644 index 0000000..273ae30 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino @@ -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 +#include +#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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h new file mode 100644 index 0000000..7bc656f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino new file mode 100644 index 0000000..5f8c767 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino @@ -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 +#include +#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(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h new file mode 100644 index 0000000..e5ad937 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/ReadMe.md b/lib/SX12XX-LoRa/examples/SX126x_examples/ReadMe.md new file mode 100644 index 0000000..e031719 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/ReadMe.md @@ -0,0 +1,44 @@ +# SX126X Library + + + +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. + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino new file mode 100644 index 0000000..9b6efc2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino @@ -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 +#include +#include "Settings.h" +#include + +#include //watchdog timer library, integral to Arduino IDE +#include //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(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h new file mode 100644 index 0000000..407659c --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino new file mode 100644 index 0000000..27d83dc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino @@ -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 +#include +#include "Settings.h" +#include + + +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")); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/22_On_Off_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/22_On_Off_Receiver/Settings.h new file mode 100644 index 0000000..2ccfda1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/22_On_Off_Receiver/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino new file mode 100644 index 0000000..848ab16 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino @@ -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 +#include +#include "Settings.h" +#include + +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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h new file mode 100644 index 0000000..84fe7de --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino new file mode 100644 index 0000000..18c43ff --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino @@ -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 +#include +#include "Settings.h" +#include + +SX126XLT LT; + +#include +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(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h new file mode 100644 index 0000000..3998d15 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h @@ -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 + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/1_LED_Blink/1_LED_Blink.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/1_LED_Blink/1_LED_Blink.ino new file mode 100644 index 0000000..2865c0a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/1_LED_Blink/1_LED_Blink.ino @@ -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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/2_Register_Test/2_Register_Test.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/2_Register_Test/2_Register_Test.ino new file mode 100644 index 0000000..cc09bd5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/2_Register_Test/2_Register_Test.ino @@ -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 + + +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(); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino new file mode 100644 index 0000000..72ead20 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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 +} + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino new file mode 100644 index 0000000..3d2d920 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/STM32/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino new file mode 100644 index 0000000..2e0cd4f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino @@ -0,0 +1,315 @@ +/******************************************************************************************************* + 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 transmits a LoRa packet without using a processor buffer, the LoRa + devices internal buffer is filled directly with variables. + + The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There + is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end. + + Although the LoRa packet transmitted and received has its own internal CRC error checking, you could + still receive packets of the same length from another source. If this valid packet were to be used + to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet + is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet. + This CRC value is read by the receiver and used to check that the received CRC matches the supposed + sensor data in the packet. As an additional check there is some addressing information at the beginning + of the packet which is also checked for validity. Thus we can be relatively confident when reading the + received packet that its genuine and from this transmitter. The packet is built and sent in the + sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to + the packet. + + Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of + 8 seconds using the Atmel processor internal watchdog. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + 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. + + 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 150mAh battery, to see how long + the battery actually lasts. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +#include //watchdog timer library, integral to Arduino IDE +#include //get the library here; https://github.com/rocketscream/Low-Power + +SX126XLT LT; + +#include //get library here; https://github.com/Seeed-Studio/Grove_BME280 +BME280 bme280; //create an instance of the BME280 senosor +#include + +uint32_t TXpacketCount; +uint8_t TXPacketL; + +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t CRCvalue; //the CRC value of the packet data up to this point +uint8_t packetlength; //the packet length that was sent, checked against length received + + +void loop() +{ + TXpacketCount++; + Serial.print(TXpacketCount); //print the numbers of sends + Serial.print(F(" Sending > ")); + + readSensors(); //read the sensor values + printSensorValues(); //print the sensor values + + if (sendSensorPacket()) + { + Serial.println(F("SentOK")); + } + else + { + Serial.print(F("Send Error - IRQreg,")); + Serial.println(LT.readIrqStatus(), HEX); + } + + Serial.print(F("Sleeping zzzz")); + Serial.flush(); //make sure all serial output has gone + + //now put the sensor, LoRa device and processor to sleep + sleepBME280(); //sleep the BME280 + LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep. + sleep8seconds(sleeps); //sleep Atmel processor in units of approx 8 seconds + + //wait a bit ................ + Serial.println(F(" - Awake !!")); //the processor has woken up + Serial.println(); + + LT.wake(); + normalBME280(); //BME280 sensor to normal mode +} + + +uint8_t sendSensorPacket() +{ + //The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the + //receiver uses the same variable types and sequence to read variables out of the receive buffer. + uint8_t len; + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + + LT.writeUint8(Sensor1); //this byte defines the packet type + LT.writeUint8('B'); //this byte identifies the destination node of the packet + LT.writeUint8(1); //this byte identifies the source node of the packet + + /************************************************************************ + Highlighted section - this is where the actual sensor data is added to the packet + ************************************************************************/ + LT.writeFloat(temperature); //add the BME280 temperature + LT.writeFloat(pressure); //add the BME280 pressure + LT.writeUint16(humidity); //add the BME280 humididty + LT.writeUint16(voltage); //add the battery voltage + LT.writeUint8(statusbyte); //add the status byte + /************************************************************************/ + + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + addPacketErrorCheck(len); //add the additional CRC error checking to the packet end + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, (len + 2), 5000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void addPacketErrorCheck(uint8_t len) +{ + //calculate the CRC of packet sensor data + CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF); + + Serial.print(F("Calculated CRC value ")); + Serial.println(CRCvalue, HEX); + + LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data + LT.writeUint16(CRCvalue); //add the actual CRC value + LT.endWriteSXBuffer(); //close the packet +} + + +void readSensors() +{ + //read the sensor values into the global variables + temperature = bme280.getTemperature(); + pressure = bme280.getPressure(); + humidity = bme280.getHumidity(); + + if (BATVREADON >= 0) + { + voltage = readBatteryVoltage(); //read resistor divider across battery + } + else + { + voltage = 9999; //set a default value + } + statusbyte = 0x55; //manually set this for now, its a test +} + + +void printSensorValues() +{ + Serial.print(F("Temperature,")); + Serial.print(temperature, 1); + Serial.print(F("c,Pressure,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(" ")); + Serial.flush(); +} + + +void sleep8seconds(uint32_t sleeps) +{ + //uses the lowpower library + uint32_t index; + + for (index = 1; index <= sleeps; index++) + { + //sleep 8 seconds + LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); + } +} + + +void sleepBME280() +{ + //write this register value to BME280 to put it to sleep + writeBME280reg(BME280_REGISTER_CONTROL, B01111100); +} + + +void normalBME280() +{ + //write this register value to BME280 to put it to read mode + writeBME280reg(BME280_REGISTER_CONTROL, B01111111); +} + + +void writeBME280reg(byte reg, byte regvalue) +{ + //write a register value to the BME280 + Wire.beginTransmission((uint8_t) BME280_ADDRESS); + Wire.write((uint8_t)reg); + Wire.write((uint8_t)regvalue); + Wire.endTransmission(); +} + + +uint16_t readBatteryVoltage() +{ + //relies on 1V1 internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + byte index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + analogReference(INTERNAL1V1); + temp = analogRead(BATTERYAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(BATTERYAD); + volts = volts + temp; + } + volts = ((volts / 5) * ADMultiplier) + DIODEMV; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + return volts; +} + + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + 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); + + if (!bme280.init()) + { + Serial.println("BME280 Device error!"); + led_Flash(100, 15); //long very fast speed flash indicates BME280 device error + } + + Serial.println(F("Transmitter ready")); + Serial.println(); + + readSensors(); //do an initial sensor read +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/17_Sensor_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/17_Sensor_Transmitter/Settings.h new file mode 100644 index 0000000..39853af --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/17_Sensor_Transmitter/Settings.h @@ -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. +*******************************************************************************************************/ + +//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 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 BATVREADON 8 //when high turns on the resistor divider to measure voltage, -1 if not used +#define BATTERYAD A7 //Resitor divider for battery connected here, -1 if not used +#define ADMultiplier 10.00 //adjustment to convert AD value read into mV of battery voltage +#define DIODEMV 98 //mV voltage drop accross diode @ low idle current + +#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 = 14; //LoRa transmit power in dBm + +#define BME280_ADDRESS 0x76 //I2C bus address of BME280 +#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control + +const uint8_t sleeps = 2; //number of 8 second sleeps, gap between transmissions diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino new file mode 100644 index 0000000..1a386d9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino @@ -0,0 +1,358 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 18/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 LoRa packet without using a processor buffer, the LoRa devices + internal buffer is read direct for the received sensor data. + + The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity, + and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status + value at the end of the packet. + + When the program starts, the LoRa device is setup to set the DIO1 pin high 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. + + For the sensor data to be accepted as valid the folowing need to match; + + The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet. + The packet must start with a byte that matches the packet type sent, 'Sensor1' + The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node' + + In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid + packet is acted on and erroneous values displayed. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + With a standard Arduino Pro Mini and SSD1306 display the current consumption was 20.25mA with the + display and 16.6mA without the display. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +SX126XLT LT; + +#include //get library here > https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306 + +uint32_t RXpacketCount; //count of all packets received +uint32_t ValidPackets; //count of packets received with valid data +uint32_t RXpacketErrors; //count of all packets with errors received +bool packetisgood; + +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet + +uint8_t RXPacketType; +uint8_t RXDestination; +uint8_t RXSource; +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want + } + + digitalWrite(LED1, LOW); + Serial.println(); +} + + +void packet_Received_OK() +{ + //a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from + //an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data + + uint8_t len; + uint8_t contenterrors; //keep a count of errors found in packet + + RXpacketCount++; + Serial.print(RXpacketCount); + Serial.print(F(",PacketsReceived,")); + + LT.startReadSXBuffer(0); + RXPacketType = LT.readUint8(); + RXDestination = LT.readUint8(); + RXSource = LT.readUint8(); + + /************************************************************************ + Highlighted section - this is where the actual sensor data is read from + the packet + ************************************************************************/ + temperature = LT.readFloat(); //the BME280 temperature value + pressure = LT.readFloat(); //the BME280 pressure value + humidity = LT.readUint16(); //the BME280 humididty value + voltage = LT.readUint16(); //the battery voltage value + statusbyte = LT.readUint8(); //a status byte, not currently used + /************************************************************************/ + + len = LT.endReadSXBuffer(); + + printreceptionDetails(); //print details of reception, RSSI etc + Serial.println(); + + contenterrors = checkPacketValid(len); //pass length of packet to check routine + + if (contenterrors == 0) + { + Serial.println(F(" Packet is good")); + ValidPackets++; + printSensorValues(); //print the sensor values + Serial.println(); + printPacketCounts(); //print count of valid packets and errors + displayscreen1(); + Serial.println(); + } + else + { + Serial.println(F(" Packet is not valid")); + RXpacketErrors++; + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +uint8_t checkPacketValid(uint8_t len) +{ + //this function checks if the packet is valid and will be displayed + + uint8_t errors = 0; + + if (RXPacketType != Sensor1) //is it a Sensor1 type packet + { + errors++; + } + + if (RXDestination != This_Node) //was the packet sent to this receiver node ? + { + errors++; + } + + if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ? + { + errors++; + } + + Serial.println(); + Serial.print(F("Error Check Count = ")); + Serial.print(errors); + return errors; +} + + +bool checkCRCvalue(uint8_t len) +{ + uint16_t CRCSensorData; + + Serial.print(F("len = ")); + Serial.println(len); + + CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data + + Serial.print(F("(CRC of Received sensor data ")); + Serial.print(CRCSensorData, HEX); + Serial.print(F(")" )); + + TXCRCvalue = ((LT.getByteSXBuffer(len + 1) << 8) + (LT.getByteSXBuffer(len))); + + Serial.print(F("(CRC transmitted ")); + Serial.print(TXCRCvalue, HEX); + Serial.print(F(")" )); + + if (TXCRCvalue != CRCSensorData) + { + Serial.print(F(" Sensor Data Not Valid")); + return false; + } + else + { + Serial.print(F(" Sensor Data is Valid")); + return true; + } + +} + + +void printSensorValues() +{ + Serial.print(F("Temp,")); + Serial.print(temperature, 1); + Serial.print(F("c,Press,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(",CRC,")); + Serial.print(TXCRCvalue, HEX); + Serial.flush(); +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void printPacketCounts() +{ + Serial.print(F("ValidPackets,")); + Serial.print(ValidPackets); + Serial.print(F(",Errors,")); + Serial.print(RXpacketErrors); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXpacketErrors++; + IRQStatus = LT.readIrqStatus(); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + Serial.println(); + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +void displayscreen1() +{ + //show sensor data on display + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(F("Sensor ")); + disp.print(RXSource); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(temperature, 1); + disp.print(F("c")); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(pressure, 0); + disp.print(F("Pa")); + disp.clearLine(3); + disp.setCursor(0, 3); + disp.print(humidity); + disp.print(F("%")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(voltage); + disp.print(F("mV")); + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("ValidPkts ")); + disp.print(ValidPackets); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + Serial.begin(9600); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Check LoRa")); + disp.setCursor(0, 1); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE)) + { + disp.print(F("LoRa OK")); + led_Flash(2, 125); + } + else + { + disp.print(F("Device error")); + Serial.println(F("Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/18_Sensor_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/18_Sensor_Receiver/Settings.h new file mode 100644 index 0000000..45f9a9f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sensor/18_Sensor_Receiver/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//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 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 BATVREADON 8 //when high turns on the resistor divider to measure voltage, -1 if not used +#define BATTERYAD A7 //Resitor divider for battery connected here, -1 if not used +#define ADMultiplier 10.00 //adjustment to convert AD value read into mV of battery voltage +#define DIODEMV 98 //mV voltage drop accross diode @ low idle current + +#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 This_Node 'B' //this is the node that the remote sensors send data to + +//**************** Setup Display Parameters Here **************** + +//const uint8_t dispfont = u8x8_font_chroma48medium8_r; //display font from u8g2 library diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/59_Play_Star_Wars_Tune.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/59_Play_Star_Wars_Tune.ino new file mode 100644 index 0000000..6e3a6f9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/59_Play_Star_Wars_Tune.ino @@ -0,0 +1,176 @@ +/******************************************************************************************************* + 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 - A silly program really, but does demonstrate that you can shift a carrier generated + by the LoRa device in FSK mode fast enought 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. + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the settings file, frequencies etc +#include "pitches.h" //lookup file for notes + +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("PlayTune> ")); + Serial.println(); + Serial.flush(); + + playpart1(); + + playpart2(); + + LT.toneFM(NOTE_F4, 250, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 375, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_E5, 650, deviation, adjustfreq, TXpower); + + delay(250); + + playpart2(); + + LT.toneFM(NOTE_F4, 250, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 375, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 375, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower); + + LT.setMode(MODE_STDBY_RC); //turns off carrier + + Serial.println(); + + delay(2000); //have a delay between packets +} + + +void playpart1() +{ + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower); + + delay(250); + + LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F5, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower); + + delay(250); +} + + +void playpart2() +{ + LT.toneFM(NOTE_A5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 300, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS5, 325, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_G5, 175, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_FS5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_FS5, 250, deviation, adjustfreq, TXpower); + + delay(250); + + LT.toneFM(NOTE_AS4, 250, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_DS5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F5, 325, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_CS5, 175, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_AS4, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 250, deviation, adjustfreq, TXpower); + + delay(500); +} + + +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("59_Play_Star_Wars_Tune 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/Settings.h new file mode 100644 index 0000000..fe8a725 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/Settings.h @@ -0,0 +1,35 @@ +/******************************************************************************************************* + 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 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 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 in hz, total frequency shift low to high +const float adjustfreq = 0.8; //adjustment to tone frequency + +const int8_t TXpower = 10; //LoRa transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/pitches.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/pitches.h new file mode 100644 index 0000000..2f733c7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Silly/59_Play_Star_Wars_Tune/pitches.h @@ -0,0 +1,94 @@ +//File from https://www.arduino.cc/en/Tutorial/toneMelody +//This note table was originally written by Brett Hagman, on whose work the Arduino tone() command was based. + +#define NOTE_B0 31 +#define NOTE_C1 33 +#define NOTE_CS1 35 +#define NOTE_D1 37 +#define NOTE_DS1 39 +#define NOTE_E1 41 +#define NOTE_F1 44 +#define NOTE_FS1 46 +#define NOTE_G1 49 +#define NOTE_GS1 52 +#define NOTE_A1 55 +#define NOTE_AS1 58 +#define NOTE_B1 62 +#define NOTE_C2 65 +#define NOTE_CS2 69 +#define NOTE_D2 73 +#define NOTE_DS2 78 +#define NOTE_E2 82 +#define NOTE_F2 87 +#define NOTE_FS2 93 +#define NOTE_G2 98 +#define NOTE_GS2 104 +#define NOTE_A2 110 +#define NOTE_AS2 117 +#define NOTE_B2 123 +#define NOTE_C3 131 +#define NOTE_CS3 139 +#define NOTE_D3 147 +#define NOTE_DS3 156 +#define NOTE_E3 165 +#define NOTE_F3 175 +#define NOTE_FS3 185 +#define NOTE_G3 196 +#define NOTE_GS3 208 +#define NOTE_A3 220 +#define NOTE_AS3 233 +#define NOTE_B3 247 +#define NOTE_C4 262 +#define NOTE_CS4 277 +#define NOTE_D4 294 +#define NOTE_DS4 311 +#define NOTE_E4 330 +#define NOTE_F4 349 +#define NOTE_FS4 370 +#define NOTE_G4 392 +#define NOTE_GS4 415 +#define NOTE_A4 440 +#define NOTE_AS4 466 +#define NOTE_B4 494 +#define NOTE_C5 523 +#define NOTE_CS5 554 +#define NOTE_D5 587 +#define NOTE_DS5 622 +#define NOTE_E5 659 +#define NOTE_F5 698 +#define NOTE_FS5 740 +#define NOTE_G5 784 +#define NOTE_GS5 831 +#define NOTE_A5 880 +#define NOTE_AS5 932 +#define NOTE_B5 988 +#define NOTE_C6 1047 +#define NOTE_CS6 1109 +#define NOTE_D6 1175 +#define NOTE_DS6 1245 +#define NOTE_E6 1319 +#define NOTE_F6 1397 +#define NOTE_FS6 1480 +#define NOTE_G6 1568 +#define NOTE_GS6 1661 +#define NOTE_A6 1760 +#define NOTE_AS6 1865 +#define NOTE_B6 1976 +#define NOTE_C7 2093 +#define NOTE_CS7 2217 +#define NOTE_D7 2349 +#define NOTE_DS7 2489 +#define NOTE_E7 2637 +#define NOTE_F7 2794 +#define NOTE_FS7 2960 +#define NOTE_G7 3136 +#define NOTE_GS7 3322 +#define NOTE_A7 3520 +#define NOTE_AS7 3729 +#define NOTE_B7 3951 +#define NOTE_C8 4186 +#define NOTE_CS8 4435 +#define NOTE_D8 4699 +#define NOTE_DS8 4978 + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino new file mode 100644 index 0000000..5c07947 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino @@ -0,0 +1,242 @@ +/******************************************************************************************************* + 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 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. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //watchdog timer library, integral to Arduino IDE +#include +#include //get the library here; https://github.com/rocketscream/Low-Power + +#include +#include "Settings.h" + +SX126XLT LT; + +boolean SendOK; +int8_t TestPower; +uint8_t TXPacketL; + + +void loop() +{ + digitalWrite(LED1, HIGH); + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket1> ")); + Serial.flush(); + + if (Send_Test_Packet1()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); + + LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep. + Serial.println(F("Sleeping zzzzz....")); + Serial.println(); + Serial.flush(); + digitalWrite(LED1, LOW); + + sleep1second(15); //goto sleep for 15 seconds + + Serial.println(F("Awake !")); + Serial.flush(); + digitalWrite(LED1, HIGH); + LT.wake(); + + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket2> ")); + Serial.flush(); + + if (Send_Test_Packet2()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); +} + + +void sleep1second(uint32_t sleeps) +{ + //uses the lowpower library + uint32_t index; + + for (index = 1; index <= sleeps; index++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep in 1 second steps + } +} + + +void packet_is_OK() +{ + Serial.print(F(" ")); + Serial.print(TXPacketL); + Serial.print(F(" Bytes SentOK")); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error +} + + +bool Send_Test_Packet1() +{ + uint8_t bufffersize; + + uint8_t buff[] = "Before Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +bool Send_Test_Packet2() +{ + uint8_t bufffersize; + + uint8_t buff[] = "After Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("5_LoRa_TX_Sleep_Timed_Wakeup_Atmel Starting")); + + SPI.begin(); + + 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 flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.print(F("Transmitter ready - TXBUFFER_SIZE ")); + Serial.println(TXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h new file mode 100644 index 0000000..e8da812 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h @@ -0,0 +1,45 @@ +/******************************************************************************************************* + 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 DIO2, +//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 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 TXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/62_LoRa_Wake_on_RX_Atmel.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/62_LoRa_Wake_on_RX_Atmel.ino new file mode 100644 index 0000000..eb73c6b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/62_LoRa_Wake_on_RX_Atmel.ino @@ -0,0 +1,224 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 - 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 setup to recieve packets with pin DIO1 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 DIO1 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 6.53mA. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include +#include +#include "Settings.h" + +#include +#include +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +#include + +SX126XLT LT; + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create a buffer for the received packet + +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, NO_WAIT); //setup LoRa device for receive with no timeout + + Serial.println(F("Waiting for RX - Sleeping")); + Serial.flush(); + + attachInterrupt(digitalPinToInterrupt(DIO1), wakeUp, HIGH); + + atmelSleepPermanent(); //sleep the processor + + detachInterrupt(digitalPinToInterrupt(DIO1)); + + //something has happened ? + Serial.println(F("Awake")); + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + + digitalWrite(BUZZER, LOW); + } + Serial.println(); +} + + +void wakeUp() +{ + //handler for the interrupt +} + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); + RXpacketCount++; + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + Serial.print(F("Packet> ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); + Serial.print(F(" 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); + Serial.println(); + led_Flash(2, 125); //LED flash for approx 10 seconds +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.println(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(); + Serial.println(); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("62_LoRa_Wake_on_RX_Atmel Starting")); + + if (BUZZER > 0) + { + pinMode(BUZZER, OUTPUT); + digitalWrite(BUZZER, HIGH); + delay(50); + digitalWrite(BUZZER, LOW); + } + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, 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.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/Settings.h new file mode 100644 index 0000000..708e00e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 19/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. +*******************************************************************************************************/ + +//******* 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. BUZZER may not be 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 LED1 8 //on board LED, high for on +#define BUZZER -1 //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 +const uint16_t packetCRCcheck = 0x3F83; //CRC to check RX packet for +const uint8_t packetCRClengthcheck = 23; //packet length to check for + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/6_LoRa_RX_and_Sleep_Atmel.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/6_LoRa_RX_and_Sleep_Atmel.ino new file mode 100644 index 0000000..7b48cef --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/6_LoRa_RX_and_Sleep_Atmel.ino @@ -0,0 +1,248 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 08/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. + + When the program starts the LoRa device is setup to recieve packets with pin DIO1 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 DIO1 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 6.51mA, or about half that on + a SX127X setup. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +#include +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +SX126XLT LT; + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create a buffer for the received packet + +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() +{ + LT.fillSXBuffer(0, 1, '#'); //make sure the first part of FIFO is cleared, so we can tell its a fresh packet + + RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 0, NO_WAIT); //setup LoRa device for receive and continue + + //receive is setup + + Serial.println(F("Going to sleep zzzz")); + Serial.println(); + Serial.flush(); //make sure all serial has gone, it can wake up processor + + sleep_permanent(); //put processor to sleep, with LoRa device listening, should + //wakeup when DIO1 goes high + + Serial.println(F("Awake !!!!")); + digitalWrite(LED1, HIGH); //something has happened ? + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + + digitalWrite(BUZZER, LOW); + } + + Serial.println(); +} + + +void sleep_permanent() +{ + LT.clearIrqStatus(IRQ_RADIO_ALL); //ensure the DIO1 low is cleared, otherwise there could be an immediate wakeup + attachPCINT(digitalPinToPCINT(DIO1), wakeUp, HIGH); //This is a hardware interrupt, the LoRa device is set for DIOo goes high on RXdone + ADCSRA = 0; //disable ADC + set_sleep_mode (SLEEP_MODE_PWR_DOWN); + noInterrupts (); //timed sequence follows + sleep_enable(); + + 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(); + + detachPCINT(digitalPinToPCINT(DIO1)); +} + + +void wakeUp() +{ + //handler for the interrupt +} + + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); + RXpacketCount++; + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + Serial.print(F("Packet> ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); + Serial.print(F(" 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(); //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); + LT.printIrqStatus(); + } +} + + +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("6_LoRa_RX_and_Sleep_Atmel Starting")); + Serial.println(); + + if (BUZZER > 0) + { + pinMode(BUZZER, OUTPUT); + digitalWrite(BUZZER, HIGH); + delay(50); + digitalWrite(BUZZER, LOW); + } + + SPI.begin(); + + 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(); + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/Settings.h new file mode 100644 index 0000000..14661c4 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as 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 RFBUSY 7 //SX126X busy pin +#define LED1 8 //on board LED, high for on +#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 -1 //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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino new file mode 100644 index 0000000..5cec8e1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino @@ -0,0 +1,407 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program is an example of a basic GPS tracker. The program reads the GPS, + waits for an updated fix and transmits location and altitude, number of satellites in view, the HDOP + value, the fix time of the GPS and the battery voltage. This transmitter can be also be used to + investigate GPS performance. At startup there should be a couple of seconds of recognisable text from + the GPS printed to the serial monitor. If you see garbage or funny characters its likley the GPS baud + rate is wrong. If the transmitter is turned on from cold, the receiver will pick up the cold fix time, + which is an indication of GPS performance. The GPS will be powered on for around 4 seconds before the + timing of the fix starts. Outside with a good view of the sky most GPSs should produce a fix in around + 45 seconds. The number of satellites and HDOP are good indications to how well a GPS is working. + + The program writes direct to the LoRa devices internal buffer, no memory buffer is used. + + The LoRa settings are configured in the Settings.h file. + + The program has the option of using a pin to control the power to the GPS (GPSPOWER), if the GPS module + or board being used has this feature. To not use this feature set the define for GPSPOWER in the + Settings.h file to '#define GPSPOWER -1'. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic + levels. + + There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on + and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON + in 'Settings.h' to the pin used. If not using the feature set the pin number to -1. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" +#define authorname "Stuart Robinson" + +#include +#include + +#include "Settings.h" +#include + +SX126XLT LT; + +#include //get library here > http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + + +#ifdef USE_SOFTSERIAL_GPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#else +#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file +#endif + + +uint8_t TXStatus = 0; //used to store current status flag bits of Tracker transmitter (TX) +uint8_t TXPacketL; //length of LoRa packet (TX) +float TXLat; //Latitude from GPS on Tracker transmitter (TX) +float TXLon; //Longitude from GPS on Tracker transmitter (TX) +float TXAlt; //Altitude from GPS on Tracker transmitter (TX) +uint8_t TXSats; //number of GPS satellites seen (TX) +uint32_t TXHdop; //HDOP from GPS on Tracker transmitter (TX) +uint16_t TXVolts; //Volts (battery) level on Tracker transmitter (TX) +uint32_t TXGPSFixTime; //GPS fix time in hot fix mode of GPS on Tracker transmitter (TX) +uint32_t TXPacketCount, TXErrorsCount; //keep count of OK packets and send errors + + +void loop() +{ + + if (gpsWaitFix(WaitGPSFixSeconds)) + { + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); + Serial.println(); + Serial.print(F("Waiting ")); + Serial.print(Sleepsecs); + Serial.println(F("s")); + delay(Sleepsecs * 1000); //this sleep is used to set overall transmission cycle time + } + else + { + send_Command(NoFix); //send notification of no GPS fix. + } +} + + +bool gpsWaitFix(uint32_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + uint32_t endwaitmS, GPSonTime; + bool GPSfix = false; + float tempfloat; + uint8_t GPSchar; + + GPSonTime = millis(); + GPSserial.begin(9600); //start GPSserial + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.println(F("s")); + + endwaitmS = millis() + (waitSecs * 1000); + + while (millis() < endwaitmS) + { + if (GPSserial.available() > 0) + { + GPSchar = GPSserial.read(); + gps.encode(GPSchar); + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + GPSfix = true; + Serial.print(F("Have GPS Fix ")); + TXGPSFixTime = millis() - GPSonTime; + Serial.print(TXGPSFixTime); + Serial.println(F("mS")); + + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = gps.altitude.meters(); + TXSats = gps.satellites.value(); + TXHdop = gps.hdop.value(); + tempfloat = ( (float) TXHdop / 100); + + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempfloat, 2); + Serial.println(); + + break; //exit while loop reading GPS + } + } + + //if here then there has either been a fix or no fix and a timeout + + if (GPSfix) + { + setStatusByte(GPSFix, 1); //set status bit to flag a GPS fix + } + else + { + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(); + Serial.println(F("Timeout - No GPSFix")); + Serial.println(); + GPSfix = false; + } + + GPSserial.end(); //serial RX interrupts interfere with SPI, so stop GPSserial + return GPSfix; +} + + +void sendLocation(float Lat, float Lon, float Alt, uint32_t Hdop, uint32_t fixtime) +{ + uint8_t len; + uint16_t IRQStatus; + + Serial.print(F("Send Location")); + + TXVolts = readSupplyVoltage(); //get the latest supply\battery volts + + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationPacket); //indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeFloat(Alt); //add altitude + LT.writeUint8(TXSats); //add number of satellites + LT.writeUint32(Hdop); //add hdop + LT.writeUint8(TXStatus); //add tracker status + LT.writeUint32(fixtime); //add GPS fix time in mS + LT.writeUint16(TXVolts); //add tracker supply volts + LT.writeUint32(millis()); //add uptime in mS + len = LT.endWriteSXBuffer(); //close buffer write + + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); + + if (TXPacketL) + { + TXPacketCount++; + Serial.println(F(" - Done ")); + Serial.print(F("SentOK,")); + Serial.print(TXPacketCount); + Serial.print(F(",Errors,")); + Serial.println(TXErrorsCount); + } + else + { + //if here there was an error transmitting packet + TXErrorsCount++; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + Serial.println(); + } +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void send_Command(char cmd) +{ + bool SendOK; + uint8_t len; + + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + + LT.startWriteSXBuffer(0); + LT.writeUint8(cmd); //packet addressing used indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent to + LT.writeUint8(ThisNode); //where is packet from + LT.writeUint16(TXVolts); + len = LT.endWriteSXBuffer(); + + digitalWrite(LED1, HIGH); + SendOK = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); //timeout set at 10 seconds + digitalWrite(LED1, LOW); + + if (SendOK) + { + Serial.println(F(" - Done")); + } + else + { + Serial.println(F(" - Error")); + } +} + + +uint16_t readSupplyVoltage() +{ + //relies on 1V internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t voltage = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + analogReference(INTERNAL); + temp = analogRead(SupplyAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(SupplyAD); + voltage = voltage + temp; + } + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + + voltage = ((voltage / 5) * ADMultiplier) + DIODEMV; + return voltage; +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void setup() +{ + uint32_t endmS; + + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + GPSON(); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("23_GPS_Tracker_Transmitter Starting")); + + SPI.begin(); + + 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 flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + + TXVolts = readSupplyVoltage(); + + Serial.print(F("Supply ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + + send_Command(PowerUp); //send power up command, includes supply mV + + Serial.println(F("Startup GPS check")); + + GPSserial.begin(9600); + + endmS = millis() + echomS; + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + + Serial.println(F("Wait for first GPS fix")); + gpsWaitFix(WaitFirstGPSFixSeconds); + + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); +} diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h new file mode 100644 index 0000000..5d884d7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h @@ -0,0 +1,68 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX126X busy pin +#define DIO1 3 //DIO1 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 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 + +#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 //On board LED, high for on +#define SupplyAD A7 //pin for reading supply\battery voltage +#define BATVREADON 8 //turns on battery resistor divider, high for on, -1 if not used + +const float ADMultiplier = 10.0; //multiplier for supply volts calculation +#define DIODEMV 98 //mV voltage drop accross diode at approx 8mA + + +#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_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power + +#define ThisNode '2' //a character that identifies this tracker + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +//#define HardwareSerialPort Serial1 //if using hardware serial enable this define for hardware serial port + +#define GPSBaud 9600 //GPS Baud rate + +#define WaitGPSFixSeconds 30 //time in seconds to wait for a new GPS fix +#define WaitFirstGPSFixSeconds 1800 //time to seconds to wait for the first GPS fix at startup +#define Sleepsecs 5 //seconds between transmissions, this delay is used to set overall transmission cycle time + +#define echomS 2000 //number of mS to run GPS echo at startup + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino new file mode 100644 index 0000000..df35e85 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino @@ -0,0 +1,322 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 22/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 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. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include +#include + +SX126XLT LT; + +#include "Settings.h" +#include + + +uint32_t RXpacketCount; //count of received packets + +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //A status byte +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint8_t TXSats; //number of sattelites in use +uint32_t TXupTimemS; //up time of TX in mS + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort + + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + + Serial.println(); +} + + +void readPacketAddressing() +{ + //the transmitter is using packet addressing, so read in the details + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + float tempHdop; + + RXpacketCount++; + Serial.print(F("Packet OK > ")); + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from FIFO, not used + LT.readUint8(); //read byte from FIFO, not used + LT.readUint8(); //read byte from FIFO, not used + TXVolts = LT.readUint16(); + LT.endReadSXBuffer(); + Serial.print(F("Tracker transmitter powerup - battery ")); + Serial.print(TXVolts); + Serial.print(F("mV")); + } + + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readFloat(); + TXSats = LT.readUint8(); + TXHdop = LT.readUint32(); + TXStatus = LT.readUint8(); + TXGPSFixTime = LT.readUint32(); + TXVolts = LT.readUint16(); + TXupTimemS = LT.readUint32(); + RXPacketL = LT.endReadSXBuffer(); + + tempHdop = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F("m,")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempHdop, 2); + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS / 1000)); + Serial.print(F("s,")); + printpacketDetails(); + return; + } + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + tempHdop = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + printpacketDetails(); + return; + } + + if (PacketType == NoFix) + { + Serial.print(F("No Tracker GPS fix ")); + printpacketDetails(); + return; + } + +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("PacketError,RSSI")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + 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("24_GPS_Tracker_Receiver Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + Serial.println(F("BUZZER Enabled")); + } + else + { + Serial.println(F("BUZZER Not Enabled")); + } + + 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(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h new file mode 100644 index 0000000..107b2b9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h @@ -0,0 +1,37 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 22/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. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX126X busy pin +#define DIO1 3 //DIO1 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 LED1 8 //On board LED, high for on + +#define BUZZER -1 //Buzzer if fitted, high for on. 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_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino new file mode 100644 index 0000000..d4bd445 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino @@ -0,0 +1,624 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20 + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program is an example of a functional GPS tracker receiver using lora. + It is capable of picking up the trackers location packets from many kilometres away with only basic antennas. + + The program receives the location packets from the remote tracker transmitter and writes them on an OLED + display and also prints the information to the Arduino IDE serial monitor. The program can read a locally + attached GPS and when that has a fix, will display the distance and direction to the remote tracker. + + The program writes direct to the lora devices internal buffer, no memory buffer is used. The lora settings + are configured in the Settings.h file. + + The receiver recognises two types of tracker packet, the one from the matching program '23_GPS_Tracker_Transmitter' + (LocationPacket, 27 bytes) which causes these fields to be printed to the serial monitor; + + Latitude, Longitude, Altitude, Satellites, HDOP, TrackerStatusByte, GPS Fixtime, Battery mV, Distance, Direction, + Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, PacketLength, IRQRegister. + + This is a long packet which at the long range LoRa settings takes just over 3 seconds to transmit. + + The receiver also recognises a much shorter location only packet (LocationBinaryPacket, 11 bytes) and when + received this is printed to the serial monitor; + + Latitude, Longitude, Altitude, TrackerStatusByte, Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, + PacketLength, IRQRegister. + + Most of the tracker information (for both types of packet) is shown on the OLED display. If there has been a + tracker transmitter GPS fix the number\identifier of that tracker is shown on row 0 right of screen and if there + is a recent local (receiver) GPS fix an 'R' is displayed row 1 right of screen. + + When the tracker transmitter starts up or is reset its sends a power up message containing the battery voltage + which is shown on the OLED and printer to the serial monitor. + + The program has the option of using a pin to control the power to the GPS, if the GPS module being used has this + feature. To use the option change the define in Settings.h; + + '#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE defines to + the appropriate logic levels. + + The program by default uses software serial to read the GPS, you can use hardware serial by commenting out this + line in the Settings.h file; + + #define USE_SOFTSERIAL_GPS + + And then defining the hardware serial port you are using, which defaults to Serial1. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + + +#define Program_Version "V1.1" + +#include +#include +SX126XLT LT; + +#include "Settings.h" +#include + +#include //https://github.com/olikraus/u8g2 +//U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 + + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USE_SOFTSERIAL_GPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#else +#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file +#endif + +uint32_t RXpacketCount; //count of received packets +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet +int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //status byte from tracker transmitter +uint8_t TXSats; //number of sattelites in use +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +float RXLat; //latitude +float RXLon; //longitude +float RXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint16_t RXVolts; //supply\battery voltage +float TXdistance; //calculated distance to tracker +uint16_t TXdirection; //calculated direction to tracker +uint16_t RXerrors; +uint32_t TXupTimemS; //up time of TX in mS + +uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix + +bool TXLocation = false; //set to true when at least one tracker location packet has been received +bool RXGPSfix = false; //set to true if the local GPS has a recent fix + +uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); //returns 0 if packet error of some sort + + while (!digitalRead(DIO1)) + { + readGPS(); //If the DIO pin is low, no packet arrived, so read the GPS + } + + //something has happened in receiver + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readRXPacketL(); + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + Serial.println(); +} + + +void readGPS() +{ + if (GPSserial.available() > 0) + { + gps.encode(GPSserial.read()); + } + + + if ( millis() > (LastRXGPSfixCheck + NoRXGPSfixms)) + { + RXGPSfix = false; + LastRXGPSfixCheck = millis(); + dispscreen1(); + } + + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + RXGPSfix = true; + RXLat = gps.location.lat(); + RXLon = gps.location.lng(); + RXAlt = gps.altitude.meters(); + printRXLocation(); + LastRXGPSfixCheck = millis(); + + if ( FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1 + { + FixCount = DisplayRate; + dispscreen1(); + } + FixCount--; + } +} + + +bool readTXStatus(byte bitnum) +{ + return bitRead(TXStatus, bitnum); +} + + +void printRXLocation() +{ + Serial.print(F("LocalGPS ")); + Serial.print(RXLat, 5); + Serial.print(F(",")); + Serial.print(RXLon, 5); + Serial.print(F(",")); + Serial.print(RXAlt, 1); + Serial.println(); +} + + +void readPacketAddressing() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + //uint16_t IRQStatus; + float tempfloat; + + RXpacketCount++; + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + TXVolts = LT.readUint16(); //read tracker transmitter voltage + LT.endReadSXBuffer(); + Serial.print(F("Tracker Powerup - Battery ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + dispscreen2(); + } + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + TXLocation = true; + LT.startReadSXBuffer(0); //start the read of received packet + PacketType = LT.readUint8(); //read in the PacketType + Destination = LT.readUint8(); //read in the Packet destination address + Source = LT.readUint8(); //read in the Packet source address + TXLat = LT.readFloat(); //read in the tracker latitude + TXLon = LT.readFloat(); //read in the tracker longitude + TXAlt = LT.readFloat(); //read in the tracker altitude + TXSats = LT.readUint8(); //read in the satellites in use by tracker GPS + TXHdop = LT.readUint32(); //read in the HDOP of tracker GPS + TXStatus = LT.readUint8(); //read in the tracker status byte + TXGPSFixTime = LT.readUint32(); //read in the last fix time of tracker GPS + TXVolts = LT.readUint16(); //read in the tracker supply\battery volts + TXupTimemS = LT.readUint32(); //read in the TX uptime in mS + RXPacketL = LT.endReadSXBuffer(); //end the read of received packet + + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + + tempfloat = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + Serial.print(tempfloat, 2); + + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS / 1000)); + Serial.print(F("s,")); + + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); //and show the packet detail it on screen + return; + } + + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + TXLocation = true; + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); + return; + } +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + RXerrors++; + Serial.print(F("PacketError,RSSI")); + + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void dispscreen1() +{ + //show received packet data on display + float tempfloat; + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(TXLat, 5); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(TXLon, 5); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(TXAlt, 0); + disp.print(F("m")); + disp.clearLine(3); + disp.setCursor(0, 3); + + disp.print(F("RSSI ")); + disp.print(PacketRSSI); + disp.print(F("dBm")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(F("SNR ")); + + if (PacketSNR > 0) + { + disp.print(F("+")); + } + + if (PacketSNR == 0) + { + disp.print(F(" ")); + } + + if (PacketSNR < 0) + { + disp.print(F("-")); + } + + disp.print(PacketSNR); + disp.print(F("dB")); + + if (PacketType == LocationPacket) + { + disp.clearLine(5); + disp.setCursor(0, 5); + tempfloat = ((float) TXVolts / 1000); + disp.print(F("Batt ")); + disp.print(tempfloat, 2); + disp.print(F("v")); + } + + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); + + disp.clearLine(7); + + if (RXGPSfix) + { + disp.setCursor(15, 1); + disp.print(F("R")); + } + else + { + disp.setCursor(15, 1); + disp.print(F(" ")); + disp.setCursor(0, 7); + disp.print(F("No Local Fix")); + } + + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(TXdistance, 0); + disp.print(F("m ")); + disp.print(TXdirection); + disp.print(F("d")); + } + + if (readTXStatus(GPSFix)) + { + disp.setCursor(15, 0); + disp.write(Source); + } + +} + + +void dispscreen2() +{ + //show tracker powerup data on display + float tempfloat; + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Tracker Powerup")); + disp.setCursor(0, 1); + disp.print(F("Battery ")); + tempfloat = ((float) TXVolts / 1000); + disp.print(tempfloat, 2); + disp.print(F("v")); +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void setup() +{ + uint32_t endmS; + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("25_GPS_Tracker_Receiver_With_Display_and_GPS Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + } + + SPI.begin(); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + Serial.print(F("Checking LoRa device - ")); //Initialize LoRa + disp.setCursor(0, 0); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, SW, LORA_DEVICE)) + { + Serial.println(F("Receiver ready")); + disp.print(F("Receiver ready")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No LoRa device responding")); + disp.print(F("No LoRa device")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + Serial.println(F("Startup GPS check")); + + endmS = millis() + echomS; + + //now startup GPS + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + } + + GPSON(); + GPSserial.begin(GPSBaud); + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h new file mode 100644 index 0000000..512c691 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h @@ -0,0 +1,67 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be +//connected and should be set to -1. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX126X busy pin +#define DIO1 3 //DIO1 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 LED1 8 //On board LED, high for on + +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used + +#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 4 //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 + +#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_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +//#define HardwareSerialPort Serial1 //if using hardware serial enable this define for hardware serial port + +#define GPSBaud 9600 //GPS Baud rate +#define WaitGPSFixSeconds 30 //time to wait for a new GPS fix +#define echomS 2000 //number of mS to run GPS echo for at startup + +#define NoRXGPSfixms 15000 //max number of mS to allow before no local fix flagged +#define DisplayRate 7 //when working OK the GPS will get a new fix every second or so + //this rate defines how often the display should be updated + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino new file mode 100644 index 0000000..0921913 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino @@ -0,0 +1,173 @@ +/******************************************************************************************************* + 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 will receive a lora packet and relay (re-transmit) it. The receiving + and transmitting can use different frequencies and lora settings, although in this example they are + the same. The receiving and transmitting settings are in the 'Settings.h' file. If the relay is located + in an advantageous position, for instance on top of a tall tree, building or in an radio controlled model + then the range at which trackers or nodes on the ground can be received is considerably increased. + In these circumstances the relay may listen at a long range setting using SF12 for example and then + re-transmit back to the ground at SF7. + + For an example of the use of such a program see this report; + + How to Search 500 Square Kilometres in 10 minutes.pdf in the libraries 'Test_Reports' folder. + + Serial monitor baud rate is set at 9600. + +*******************************************************************************************************/ + + +#include +#include +#include "Settings.h" + +SX126XLT LT; + +uint8_t RXPacketL, TXPacketL; +int8_t PacketRSSI, PacketSNR; +uint16_t RXPacketErrors; + + +void loop() +{ + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + if (BUZZER > 0) //turn buzzer on + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + PacketSNR = LT.readPacketSNR(); //read the received SNR value + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + Serial.println(); +} + + +void packet_is_OK() +{ + //a packet has been received, so change to relay settings and transmit buffer + + Serial.print(F("PacketOK ")); + printreceptionDetails(); + delay(packet_delay / 2); + digitalWrite(LED1, LOW); + delay(packet_delay / 2); + + Serial.print(F(" Retransmit")); + LT.setupLoRa(RelayFrequency, RelayOffset, RelaySpreadingFactor, RelayBandwidth, RelayCodeRate, RelayOptimisation); + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, RXPacketL, 10000, TXpower, WAIT_TX); + Serial.print(F(" - Done")); + digitalWrite(LED1, LOW); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXPacketErrors++; + IRQStatus = LT.readIrqStatus(); + + led_Flash(5, 50); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + } +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void led_Flash(uint16_t flashdelay, uint16_t flashes) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + + delay(flashdelay); + digitalWrite(LED1, HIGH); + delay(flashdelay); + digitalWrite(LED1, LOW); + } +} + + +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.print("ListenSettings,"); + LT.printModemSettings(); + Serial.println(); + LT.setupLoRa(RelayFrequency, RelayOffset, RelaySpreadingFactor, RelayBandwidth, RelayCodeRate, RelayOptimisation); + Serial.print("RelaySettings,"); + LT.printModemSettings(); + Serial.println(); + Serial.println("Relay Ready"); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/38_lora_Relay/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/38_lora_Relay/Settings.h new file mode 100644 index 0000000..9900918 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/38_lora_Relay/Settings.h @@ -0,0 +1,53 @@ +/******************************************************************************************************* + 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 definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 //SX126X 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 receiving parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +//LoRa relay (re-transmitting) parameters +const uint32_t RelayFrequency = 434000000; //frequency of transmissions +const uint32_t RelayOffset = 0; //offset frequency for calibration purposes + +const uint8_t RelayBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t RelaySpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t RelayCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t RelayOptimisation = LDRO_AUTO; //low data rate optimisation setting + + +const int8_t TXpower = 10; //LoRa TX power in dBm + +#define packet_delay 1000 //mS delay before received packet transmitted + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/67_Balloon_Tracker_Transmitter/67_Balloon_Tracker_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/67_Balloon_Tracker_Transmitter/67_Balloon_Tracker_Transmitter.ino new file mode 100644 index 0000000..6c1abd6 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/67_Balloon_Tracker_Transmitter/67_Balloon_Tracker_Transmitter.ino @@ -0,0 +1,744 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 is a tracker intended for use as a high altitude balloon (HAB) tracker. The + program sends out a standard format payload with LoRa that is compatible with the HABHUB online tracking + system. + + The HAB payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,Status,Errors,TXGPSfixms,Checksum + Field 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + + The LoRa and frequency settings can be changed in the Settings.h file. There is the option of sending + out a much shorter Search mode binary location only payload. This is intended for ground based searching + and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker + mode used by the HAB payload. There is also the option of sending the HAB payload in FSK RTTY format, + see the Settings.h file for all the options. FSK RTTY gets sent at the same frequency as the Tracker mode + HAB packet. The LT.transmitFSKRTTY() function sends at 1 start bit, 7 data bits, no parity and 2 stop bits. + For full control of the FSK RTTY setting you can use the following alternative function; + + LT.transmitFSKRTTY(chartosend, databits, stopbits, parity, baudPerioduS, pin) + + There is a matching Balloon Tracker Receiver program which writes received data to the Serial monitor as well + as a small OLED display. + + In the Settings.h file you can set the configuration for either a Ublox GPS or a Quectel L70\L80. The GPSs + are configured for high altitude balloon mode. + + It is strongly recommended that a FRAM option is fitted for this transmitter. The sequence, resets and error + nembers are stred in non-volatile memory. This defaults to EEPROM which has a limited endurance of only + 100,000 writes, so in theory the limt is reached after the transmission of 100,000 hab packets. The use of + a FRAM will extend the life of the tracker to circa 100,000,000,000,000 transmissions. + + Changes: + 240420 - Change to work with Easy Pro Mini style modules + 300420 - Improve error detection for UBLOX GPS library + + ToDo: + + Serial monitor baud rate is set at 115200 +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include +#include //include the appropriate library + +SX126XLT LT; //create a library class instance called LT + +#include "Settings.h" +#include "ProgramLT_Definitions.h" + +//************************************************************************************************** +// HAB tracker data - these are the variables transmitted in payload +//************************************************************************************************** +uint32_t TXSequence; //sequence number of payload +uint8_t TXHours; //Hours +uint8_t TXMinutes; //Minutes +uint8_t TXSeconds; //Seconds +float TXLat; //latitude from GPS +float TXLon; //longitude from GPS +uint16_t TXAlt; //altitude from GPS +uint8_t TXSatellites; //satellites used by GPS +uint16_t TXVolts; //measured tracker supply volts +int8_t TXTemperature; //measured temperature +uint16_t TXResets; //number of tracker resets +uint8_t TXStatus = 0; //used to store current status flag bits +uint16_t TXErrors; //number of tracker Errors +uint32_t TXGPSfixms; //fix time of GPS +//************************************************************************************************** + +uint8_t TXPacketL; //length of LoRa packet sent +uint8_t TXBUFFER[TXBUFFER_SIZE]; //buffer for packet to send + +#include Memory_Library + +#include + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USESOFTSERIALGPS +//#include //https://github.com/SlashDevin/NeoSWSerial +//NeoSWSerial GPSserial(RXpin, TXpin); //this library is more relaible at GPS init than software serial +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#endif + +#ifndef USESOFTSERIALGPS +#define GPSserial HARDWARESERIALPORT +#endif + +#include GPS_Library //include previously defined GPS Library + +#include //get library here > https://github.com/PaulStoffregen/OneWire +OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library +#include //get library here > https://github.com/milesburton/Arduino-TXTemperature-Control-Library +DallasTemperature sensor(&oneWire); //create instance of dallas library + +uint32_t GPSstartms; //start time waiting for GPS to get a fix + + +void loop() +{ + Serial.println(F("Start Loop")); + + GPSstartms = millis(); + + if (!gpsWaitFix(WaitGPSFixSeconds)) + { + GPS_OutputOff(); + sendCommand(NoFix); //report a GPS fix error + delay(1000); //give receiver enough time to report NoFix + } + Serial.println(); + + do_Transmissions(); //do the transmissions + + Serial.println(F("Sleep")); + LT.setSleep(CONFIGURATION_RETENTION); //put LoRa device to sleep, preserve lora register settings + Serial.flush(); //make sure no serial output pending before goint to sleep + + delay(SleepTimesecs * 1000); + + Serial.println(F("Wake")); + LT.wake(); //wake the LoRa device from sleep +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + uint32_t startTimemS; + uint8_t index; + + incMemoryUint32(addr_SequenceNum); //increment Sequence number + + if (readConfigByte(SearchEnable)) + { + setSearchMode(); + TXPacketL = buildLocationOnly(TXLat, TXLon, TXAlt, TXStatus); //put location data in SX12xx buffer + Serial.print(F("Search packet > ")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F(",")); + Serial.print(TXStatus); + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmitSXBuffer(0, TXPacketL, 10000, SearchTXpower, WAIT_TX); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + } + + delay(1000); //gap between transmissions + + setTrackerMode(); + + TXPacketL = buildHABPacket(); + Serial.print(F("HAB Packet > ")); + printBuffer(TXBUFFER, (TXPacketL + 1)); //print the buffer (the packet to send) as ASCII + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmit(TXBUFFER, (TXPacketL + 1), 10000, TrackerTXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error + digitalWrite(LED1, LOW); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + + delay(1000); //gap between transmissions + + if (readConfigByte(FSKRTTYEnable)) + { + LT.setupDirect(TrackerFrequency, Offset); + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + startTimemS = millis() - LeadinmS; + + Serial.print(F("FSK RTTY > $$$")); + Serial.flush(); + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + + for (index = 0; index <= (TXPacketL - 1); index++) //its TXPacketL-1 since we dont want to send the null at the end + { + LT.transmitFSKRTTY(TXBUFFER[index], BaudPerioduS, LED1); + Serial.write(TXBUFFER[index]); + } + + LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed + LT.endFSKRTTY(); //stop transmitting carrier + digitalWrite(LED1, LOW); //LED off + printTXtime(startTimemS, millis()); + TXPacketL += 4; //add the two $ at beginning and CR/LF at end + reportCompletion(); + Serial.println(); + } +} + + +void printTXtime(uint32_t startmS, uint32_t endmS) +{ +Serial.print(F(" ")); +Serial.print(endmS-startmS); +Serial.print(F("mS")); +} + + +void reportCompletion() +{ + Serial.print(F(" ")); + if (TXPacketL == 0) + { + Serial.println(); + reporttransmitError(); + } + else + { + Serial.print(TXPacketL); + Serial.print(F("bytes")); + setStatusByte(LORAError, 0); + } +} + + +void printBuffer(uint8_t *buffer, uint8_t size) +{ + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } +} + + +uint8_t buildHABPacket() +{ + //build the HAB tracker payload + uint16_t index, j, CRC; + uint8_t Count, len; + char LatArray[12], LonArray[12]; + + TXSequence = readMemoryUint32(addr_SequenceNum); //Sequence number is kept in non-volatile memory so it survives TXResets + TXResets = readMemoryUint16(addr_ResetCount); //reset count is kept in non-volatile memory so it survives TXResets + TXVolts = readSupplyVoltage(); + TXTemperature = (int8_t) readTempDS18B20(); + TXErrors = readMemoryUint16(addr_TXErrors); + + dtostrf(TXLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TXLon, 7, 5, LonArray); //converts float to character array + + len = sizeof(TXBUFFER); + memset(TXBUFFER, 0, len); //clear array to 0s + Count = snprintf((char*) TXBUFFER, + TXBUFFER_SIZE, + "$%s,%lu,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%d,%d,%d,%lu", + FlightID, + TXSequence, + TXHours, + TXMinutes, + TXSeconds, + LatArray, + LonArray, + TXAlt, + TXSatellites, + TXVolts, + TXTemperature, + TXResets, + TXStatus, + TXErrors, + TXGPSfixms + ); + + CRC = 0xffff; //start value for CRC16 + + for (index = 1; index < Count; index++) //element 1 is first character after $ at start (for LoRa) + { + CRC ^= (((uint16_t)TXBUFFER[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + TXBUFFER[Count++] = '*'; + TXBUFFER[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + TXBUFFER[Count++] = Hex((CRC >> 8) & 15); + TXBUFFER[Count++] = Hex((CRC >> 4) & 15); + TXBUFFER[Count] = Hex(CRC & 15); + return Count; +} + + +char Hex(uint8_t lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + +uint8_t buildLocationOnly(float Lat, float Lon, uint16_t Alt, uint8_t stat) +{ + uint8_t len; + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationBinaryPacket); //identify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeInt16(Alt); //add altitude + LT.writeUint8(stat); //add tracker status + len = LT.endWriteSXBuffer(); //close buffer write + return len; +} + + +void reporttransmitError() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F("TXError,")); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + incMemoryUint16(addr_TXErrors); //increase the error count + setStatusByte(LORAError, 1); +} + + +void incMemoryUint32(uint32_t addr) +{ + uint32_t val = readMemoryUint32(addr); + val++; + writeMemoryUint32(addr, val); +} + + +void incMemoryUint16(uint32_t addr) +{ + uint16_t val = readMemoryUint16(addr); + val++; + writeMemoryUint16(addr, val); +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +uint8_t readConfigByte(uint8_t bitnum) +{ + return bitRead(Default_config1, bitnum); +} + + +void setTrackerMode() +{ + Serial.println(F("setTrackerMode")); + LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation); +} + + +void setSearchMode() +{ + Serial.println(F("setSearchMode")); + LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation); +} + + +uint8_t sendCommand(char cmd) +{ + uint8_t len; + TXVolts = readSupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + LT.writeUint8(cmd); //this byte defines the packet type + LT.writeUint8(Broadcast); //destination address of the packet, the receivers address + LT.writeUint8(ThisNode); //source address of this node + LT.writeUint16(TXVolts); //add the battery voltage + LT.writeUint8(TXStatus); //add the status byte + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, len, 5000, TrackerTXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void clearAllMemory() +{ + //clears the whole of non-volatile + Serial.println(F("Clear Memory")); + fillMemory(addr_StartMemory, addr_EndMemory, 0); +} + + +float readTempDS18B20() +{ + float DS18B20TXTemperature; + sensor.requestTemperatures(); + DS18B20TXTemperature = sensor.getTempCByIndex(0); + return DS18B20TXTemperature; +} + + +void printTempDS18B20() +{ + float DS18B20TXTemperature; + DS18B20TXTemperature = readTempDS18B20(); + Serial.print(F("Temperature ")); + Serial.print(DS18B20TXTemperature, 1); + Serial.println(F("c")); +} + + +void printSupplyVoltage() +{ + //get and display supply volts on terminal or monitor + Serial.print(F("Volts ")); + Serial.print(readSupplyVoltage()); + Serial.println(F("mV")); +} + + +uint16_t readSupplyVoltage() +{ + //relies on internal 1v1 reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit + } + + 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; +} + + +//*********************************************************** +// Start GPS Functions +//*********************************************************** + +void GPSTest() +{ + uint32_t endmS; + + endmS = millis() + 2000; //run GPS echo for 2000mS + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +bool gpsWaitFix(uint16_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + + uint32_t endwaitmS, millistowait, currentmillis; + uint8_t GPSchar; + + Serial.flush(); + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.print(F("s ")); + Serial.flush(); + + GPS_OutputOn(); + Serial.flush(); + + currentmillis = millis(); + millistowait = waitSecs * 1000; + endwaitmS = currentmillis + millistowait; + + while (GPSserial.read() >= 0); //clear the GPS serial input buffer + + while (millis() < endwaitmS) + { + + if (GPSserial.available() > 0) + { + GPSchar = GPSserial.read(); + gps.encode(GPSchar); + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = (uint16_t) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TXAlt > 60000) + { + TXAlt = 0; + } + + TXHours = gps.time.hour(), + TXMinutes = gps.time.minute(), + TXSeconds = gps.time.second(), + TXSatellites = gps.satellites.value(); + + setStatusByte(GPSFix, 1); + + TXGPSfixms = millis() - GPSstartms; + + Serial.print(F("Have GPS Fix ")); + Serial.print(TXGPSfixms); + Serial.print(F("mS")); + Serial.println(); + + return true; + } + + } + + //if here then there has been no fix and a timeout + GPS_OutputOff(); + setStatusByte(GPSFix, 0); //set status bit to flag no fix + incMemoryUint16(addr_TXErrors); + Serial.println(F("Error No GPS Fix")); + return false; +} + +//*********************************************************** +// End GPS Functions +//*********************************************************** + + +void setup() +{ + uint32_t i; + uint16_t j; + + Serial.begin(115200); //Setup Serial console ouput + Serial.println(); + Serial.println(); + Serial.println(F("67_HAB_Balloon_Tracker_Transmitter Starting")); + + memoryStart(Memory_Address); //setup the memory + j = readMemoryUint16(addr_ResetCount); + j++; + writeMemoryUint16(addr_ResetCount, j); + j = readMemoryUint16(addr_ResetCount); + + Serial.print(F("TXResets ")); + Serial.println(j); + + if (GPSPOWER >= 0) //if GPS needs power switching, turn it on + { + pinMode(GPSPOWER, OUTPUT); + digitalWrite(GPSPOWER, GPSONSTATE); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); //for MOSFET controlling battery volts resistor divider + } + + #ifdef QUECTELINUSE + Serial.println(F("Quectel GPS library")); + #endif + + #ifdef UBLOXINUSE + Serial.println(F("UBLOX GPS library")); + #endif + +#ifdef ClearAllMemory + clearAllMemory(); +#endif + + SPI.begin(); //initialize SPI + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE)) + { + led_Flash(2, 125); + } + else + { + Serial.println(F("LoRa Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + setTrackerMode(); + + Serial.print(F("Config ")); + Serial.println(Default_config1, BIN); + + j = readMemoryUint16(addr_TXErrors); + Serial.print(F("TXErrors ")); + Serial.println(j); + + Serial.print(F("TXSequence ")); + i = readMemoryUint32(addr_SequenceNum); + Serial.println(i); + + Serial.print(F("ThisNode ")); + Serial.println(ThisNode); + + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + + Serial.println(); + printSupplyVoltage(); + printTempDS18B20(); + Serial.println(); + + //j = readSupplyVoltage(); //get supply mV + TXStatus = 0; //clear all TX status bits + + sendCommand(PowerUp); //send power up command, includes supply mV and config, on tracker settings + + GPS_OutputOn(); + GPSTest(); + GPS_Setup(); //GPS should have had plenty of time to initialise by now + + delay(2000); + + if (GPS_CheckConfiguration()) //Check that GPS is configured for high altitude mode + { + Serial.println(); + GPS_OutputOff(); //GPS interrupts cause problems with lora device, so turn off for now + setStatusByte(GPSError, 0); + setStatusByte(GPSConfigError, 0); + + //Alert user to GPS OK, turn LED on and send a FM tone. + digitalWrite(LED1, HIGH); + Serial.println(F("GPS Config OK")); //check tone indicates navigation model 6 set + Serial.println(); + Serial.flush(); + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + LT.toneFM(1500, 500, deviation, adjustfreq, TrackerTXpower); //Transmit an FM tone, 1000hz, 3000ms + delay(1000); + digitalWrite(LED1, LOW); + } + else + { + setStatusByte(GPSConfigError, 1); + incMemoryUint16(addr_TXErrors); + Serial.println(F("GPS Error")); + Serial.println(); + setTrackerMode(); + sendCommand(NoGPS); //make sure receiver knows about GPS error + led_Flash(100, 25); //long very rapid flash for GPS error + } + + GPSstartms = millis(); + + setTrackerMode(); //so that commands indicating wait for a GPS go out + + while (!gpsWaitFix(5)) //wait for the initial GPS fix, this could take a while + { + sendCommand(NoFix); + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + } + + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + digitalWrite(LED1, HIGH); + LT.toneFM(500, 2000, deviation, adjustfreq, TrackerTXpower); + digitalWrite(LED1, LOW); + GPS_OutputOn(); + delay(2000); //GPS may be in software backup allow time for it to wakeup + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled + GPS_OutputOff(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/67_Balloon_Tracker_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/67_Balloon_Tracker_Transmitter/Settings.h new file mode 100644 index 0000000..977427b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/67_Balloon_Tracker_Transmitter/Settings.h @@ -0,0 +1,141 @@ + /******************************************************************************************************* + 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. +*******************************************************************************************************/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify lora board type and pins here +//************************************************************************************************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done +#define RFBUSY 7 //busy pin on LoRa device +#define LED1 8 //On board LED, high for on +#define BATVREADON 8 //Pin that turns on the resistor divider to read battery volts +#define ONE_WIRE_BUS 4 //for DS18B20 temperature sensor +#define ADMultiplier 11.75 //adjustment to convert into mV of battery voltage. for 100K\10K divider +#define SupplyAD A0 //Resistor divider for battery connected here + +#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 powers GPS on\off, 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 + +#define LORA_DEVICE DEVICE_SX1262 //this is the device we are using + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +//#define ClearAllMemory //Clears memory of stored tracker information, counts, errors etc + +//************************************************************************************************** +// 3) LoRa modem settings +//************************************************************************************************** + +//LoRa Modem Parameters +const uint32_t Offset = 0; //offset frequency for calibration purposes + +//Tracker mode +const uint32_t TrackerFrequency = 434000000; //frequency of transmissions +const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t TrackerTXpower = 10; //LoRa TX power in dBm + +//Search mode +const uint32_t SearchFrequency = 434000000; //frequency of transmissionsconst +uint8_t SearchBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t SearchTXpower = 10; //LoRa TX power in dBm + +const uint16_t deviation = 10000; //deviation in hz for FM tones +const float adjustfreq = 0.9; //adjustment to tone frequency + +const byte TXBUFFER_SIZE = 128; //defines the maximum size of the trasnmit buffer; + + +//************************************************************************************************** +// 4) GPS Options +//************************************************************************************************** + +#define GPSBaud 9600 //GPS Baud rate + +#define USESOFTSERIALGPS //need to include this if using softserial for GPS, otherwise hardware serial assumed + +//#define HARDWARESERIALPORT Serial1 //if your using hardware serial for the GPS, define it here + +const uint16_t WaitGPSFixSeconds = 60; //when in flight the time to wait for a new GPS fix + +//#define GPS_Library //use library file for UBLOX GPS +#define GPS_Library //use library file for Quectel GPS + + +//************************************************************************************************** +// 5) FSK RTTY Settings +//************************************************************************************************** + +uint32_t FrequencyShift = 500; //hertz frequency shift, approx, sent at nearest 61.03515625hz step +uint8_t NumberofPips = 4; //number of marker pips to send +uint16_t PipDelaymS = 1000; //mS between pips when carrier is off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 1000; //ms of leadin constant shifted carrier + + +//**************************************************************************************************** +// 6) Program Default Option settings - This section determines which options are on or off by default, +// these are saved in the Default_config1 byte. These options are set in this way so that it is +// possible (in future program changes) to alter the options remotly. +//************************************************************************************************** + +uint8_t OptionOff = 0; +uint8_t OptionOn = 1; + +const char option_SearchEnable = OptionOn; //set to OptionOn to enable transmit of Search mode packet +const char option_FSKRTTYEnable = OptionOn; //set to OptionOn to enable transmit of FSKRTTY + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) + +const unsigned int Default_config1 = (option_SearchEnable_SUM + option_FSKRTTYEnable_SUM); +//const unsigned int Default_config1 = 0x05; //Phew, the default config can always be set manually........ + //0x05 would turn on transmit of search mode and FSKRTTY + + +//************************************************************************************************** +// 7) Memory settings - define the type of memory to use for non-Volatile storage. +// Default is internal ATmega device EEPROM but EEPROM has a limited write endurance of 'only' +// 100,000 writes. Since the non-Volatile memory selected is written to at each transmission loop +// and error, its highly recommended to use one of the FRAM options, these have an endurance of +// 100,000,000,000,000 writes. +//************************************************************************************************** + +#define Memory_Library +//#define Memory_Library +//#define Memory_Library + +int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM + +//************************************************************************************************** +// 8) HAB Flight Settings +//************************************************************************************************** + +char FlightID[] = "Flight1"; //flight ID for HAB packet + +const unsigned int SleepTimesecs = 13; //sleep time in seconds after each TX loop + +const char ThisNode = '1'; //tracker number for search packet + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/68_Balloon_Tracker_Receiver/68_Balloon_Tracker_Receiver.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/68_Balloon_Tracker_Receiver/68_Balloon_Tracker_Receiver.ino new file mode 100644 index 0000000..510f0b2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/68_Balloon_Tracker_Receiver/68_Balloon_Tracker_Receiver.ino @@ -0,0 +1,1038 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 is a LoRa tracker receiver intended to be used with the matching high altitude + balloon (HAB) tracker program '67_Balloon_Tracker_Transmitter'. The program receives a standard format + payload with LoRa that is compatible with the HABHUB online tracking system. + + The HAB payload sent by the tracker transmitter is assumed to be formatted like this; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,status,errors,Checksum + Field 0 1 2 3 4 5 6 7 8 9 10 11 12 + + The LoRa and frequency settings can be changed in the Settings.h file. There is the option of the transmitter + sending out a much shorter Search mode binary location only payload. This is intended for ground based searching + and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker + mode used by the HAB payload. To switch between standard tracker mode press the switch that is defined in the + Settings.h file. This receiver cannot receive the transmitted FSK RTTY payload. + + There is the option to enable an audio FSK RTTY uplaod into FLDIGI from where it can be sent to the HABHUB + online tracking system. + + The program will drive a SSD1306 or SH1106 OLED display for portable use. + + Not that the distance and direction to the tracker is only displayed when there has been at least one location + fix from the remote tracker and the locally attached GPS has a fix. + + Serial monitor baud rate is set at 9600. + + ToDo: + +*******************************************************************************************************/ + + +#define Program_Version "V1.2" + +#include +#include +SX126XLT LT; + +#include "Settings.h" +#include + +#include //https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + + +#ifdef USESOFTSERIALGPS +//#include //https://github.com/SlashDevin/NeoSWSerial +//NeoSWSerial GPSserial(RXpin, TXpin); //this library is more relaible with a GPS over SoftwareSerial +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#else +#define GPSserial HARDWARESERIALPORT //hardware serial port (eg Serial1) is configured in the Settings.h file +#endif + +#include + +//************************************************************************************************** +// HAB tracker data - these are the variables transmitted in payload +//************************************************************************************************** +uint32_t TXSequence; //sequence number of payload +uint8_t TXHours; //Hours +uint8_t TXMinutes; //Minutes +uint8_t TXSeconds; //Seconds +float TXLat; //latitude from GPS +float TXLon; //longitude from GPS +uint16_t TXAlt; //altitude from GPS +uint8_t TXSatellites; //satellites used by GPS +uint16_t TXVolts; //measured tracker supply volts +int8_t TXTemperature; //measured temperature +uint16_t TXResets; //number of tracker resets +uint8_t TXStatus; //used to store current status flag bits +uint16_t TXErrors; //number of tracker Errors +//************************************************************************************************** + +float RXLat; //latitude of RX +float RXLon; //longitude of RX +float RXAlt; //altitude of RX + +uint32_t RXpacketCount; //count of received packets +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet +int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet +uint16_t RXerrors; //count of packets received with errors +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +float TXdistance; //calculated distance to tracker +uint16_t TXdirection; //calculated direction to tracker +uint16_t RXVolts; //supply\battery voltage of this receiver +uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix +bool TXLocation = false; //set to true when at least one tracker location packet has been received +bool RXGPSfix = false; //set to true if the local GPS has a recent fix + +uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into +char FlightID[16]; //buffer for flight ID +uint8_t FlightIDlen; //length of received flight ID + +uint8_t modeNumber = 1; //mode receiver is in default to 1. (1 = Tracker, 2 = Search) + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); + + GPSserial.begin(GPSBaud); //startup GPS input + + while (!digitalRead(DIO1)) + { + readGPS(); //If the DIO pin is low, no packet has arrived, so read the GPS + + if (!digitalRead(SWITCH1)) + { + checkModeSwitch(); + break; + } + } + + if (digitalRead(DIO1)) + { + //something has happened in receiver + GPSserial.end(); //stop GPS input to use SPI reliably + digitalWrite(LED1, HIGH); + + RXPacketL = LT.readRXPacketL(); + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + Serial.println(); + printElapsedTime(); //print elapsed time to Serial Monitor + + if (LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID + IRQ_PREAMBLE_DETECTED)) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + + digitalWrite(LED1, LOW); + + Serial.println(); + } +} + + +void readGPS() +{ + + if (GPSserial.available() > 0) + { + gps.encode(GPSserial.read()); + } + + if ( millis() > (LastRXGPSfixCheck + NoRXGPSfixms)) + { + RXGPSfix = false; + LastRXGPSfixCheck = millis(); + if (TXLocation) //only display location screen if we have had an update + { + displayscreen1(); //shows the received location data and packet reception on display + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + } + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + RXGPSfix = true; + RXLat = gps.location.lat(); + RXLon = gps.location.lng(); + RXAlt = gps.altitude.meters(); + LastRXGPSfixCheck = millis(); + displayscreen4(); //put RX and TX GPS fix status on display + + if (FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1 + { + FixCount = DisplayRate; + if (TXLocation) //only display location screen if we have had an update + { + doDistanceDirectionCalc(); + displayscreen1(); //shows the received location data and packet reception on display + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + displayscreen5(); //put distance and direction on display + printDistanceDirection(); + } + } + FixCount--; + } +} + + +void checkModeSwitch() +{ + digitalWrite(LED1, LOW); + Serial.println(); + Serial.print(F("Listening in ")); + + modeNumber++; + + if (modeNumber == 3) + { + modeNumber = 1; + } + + if (modeNumber == 1) + { + setTrackerMode(); + Serial.println(F("Tracker Mode")); + } + + + if (modeNumber == 2) + { + setSearchMode(); + Serial.println(F("Search Mode")); + } + + displayscreen3(); //show receive mode on display + + LT.printModemSettings(); + Serial.println(); + Serial.println(); + delay(1500); //do a bit of switch de-bounce +} + + +bool readTXStatus(uint8_t bitnum) +{ + return bitRead(TXStatus, bitnum); +} + + +void readPacketAddressing() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + uint16_t includedCRC, actualCRC; + + RXpacketCount++; + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + read_Command(); + Serial.print(F("TrackerPowerup,Battery,")); + Serial.print(TXVolts); + Serial.print(F("mV")); + displayscreen2(); + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + displayscreen7(); //display received packet count + return; + } + + if (PacketType == HABPacket) + { + includedCRC = calcIncludedCRC(); + actualCRC = LT.CRCCCITTSX(1, RXPacketL - 6, 0xFFFF); + + if (actualCRC != includedCRC) + { + Serial.print(F("PayloadCRCError")); + Serial.print(F(",includedCRC,")); + Serial.print(includedCRC, HEX); + Serial.print(F(",actualCRC,")); + Serial.print(actualCRC, HEX); + Serial.print(F(",")); + LT.printSXBufferASCII(0, (RXPacketL - 1)); + printpacketDetails(); + displayscreen7(); //display received packet count + return; + } + + extractHABdata(0); + + TXLocation = true; + LT.printSXBufferASCII(0, (RXPacketL - 1)); + + TXdistance = 0; + TXdirection = 0; + + if (RXGPSfix) + { + doDistanceDirectionCalc(); + } + + printpacketDetails(); + Serial.println(); + + displayscreen1(); //shows the received location data and packet reception on display + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + displayscreen5(); //put distance and direction on display + printDistanceDirection(); + + //Serial.println(); + //printHABdata(); + //Serial.println(); + +#ifdef UPLOADHABPACKET + if (actualCRC == includedCRC) + { + Serial.println(); + uploadHABpacket(); + } +#endif + + return; + } + + if ((PacketType == LocationBinaryPacket) && (Destination == '*') && (RXPacketL == 14)) + { + //packet from tracker transmitter has been received, now read from the SX12XX FIFO in the correct order. + TXLocation = true; + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F("m,")); + Serial.println(TXStatus); + + TXdistance = 0; + TXdirection = 0; + + if (RXGPSfix) + { + doDistanceDirectionCalc(); + } + + displayscreen1(); //shows the received location data and packet reception on display + displayscreen5(); //put distance and direction on display + displayscreen7(); //display received packet count + printDistanceDirection(); + return; + } + + if (PacketType == NoFix) + { + read_Command(); + Serial.write(Source); + Serial.print(F(",NoTrackerGPSFix")); + Serial.write(7); //send a BELL to serial terminal + delay(250); + Serial.write(7); + displayscreen6(); //send a note about no tracker GPS fix to screen + displayscreen7(); //display received packet count + return; + } + + if (PacketType == NoGPS) + { + Serial.write(Source); + read_Command(); + Serial.print(F(",GPSError")); + return; + } + + Serial.print(F("PacketNotRecognised")); + printpacketDetails(); + printmorepacketDetails(); +} + + +void uploadHABpacket() +{ + uint8_t index; + uint8_t chartosend; + + Serial.print(F("Dl-Fldigi Upload $")); + Serial.flush(); + + startAFSKRTTY(AUDIOOUT, tonehighHz, leadinmS); + sendAFSKRTTY(13, AUDIOOUT, CHECK, tonelowHz, tonehighHz, AFSKRTTYperiod); + sendAFSKRTTY('$', AUDIOOUT, CHECK, tonelowHz, tonehighHz, AFSKRTTYperiod); + + for (index = 0; index <= (RXPacketL - 1); index++) + { + chartosend = LT.getByteSXBuffer(index); + sendAFSKRTTY(chartosend, AUDIOOUT, CHECK, tonelowHz, tonehighHz, AFSKRTTYperiod); + Serial.write(chartosend); + Serial.flush(); + } + + sendAFSKRTTY(13, AUDIOOUT, CHECK, tonelowHz, tonehighHz, AFSKRTTYperiod); + sendAFSKRTTY(10, AUDIOOUT, CHECK, tonelowHz, tonehighHz, AFSKRTTYperiod); + Serial.println(); + endAFSKRTTY(AUDIOOUT); +} + + +uint16_t calcIncludedCRC() +{ + uint8_t high, midhigh, midlow, low; + uint16_t crc; + high = LT.getByteSXBuffer(RXPacketL - 4); + midhigh = LT.getByteSXBuffer(RXPacketL - 3); + midlow = LT.getByteSXBuffer(RXPacketL - 2); + low = LT.getByteSXBuffer(RXPacketL - 1); + + high = convertASCIIbyte(high); + midhigh = convertASCIIbyte(midhigh); + midlow = convertASCIIbyte(midlow); + low = convertASCIIbyte(low); + + crc = (high * 4096) + (midhigh * 256) + (midlow * 16) + low; + return (uint16_t) crc; +} + + +uint8_t convertASCIIbyte(uint8_t val) +{ + if (val > 0x40) + { + val = (val - 0x41) + 10; + return val; + } + else + { + val = (val - 0x30); + return val; + } +} + + +void read_Command() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXVolts = LT.readUint16(); //read tracker transmitter voltage + LT.endReadSXBuffer(); +} + + +void printDistanceDirection() +{ + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + Serial.print(F("Distance,")); + Serial.print(TXdistance, 0); + Serial.print(F("m,Direction,")); + Serial.print(TXdirection); + Serial.println(F("d")); + } +} + + +void doDistanceDirectionCalc() +{ + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); +} + + +void printpacketDetails() +{ + int32_t hertzerror; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,FreqErr,")); + hertzerror = LT.getFrequencyErrorHz(); + Serial.print(hertzerror); + Serial.print(F("hz,PacketErrs,")); + Serial.print(RXerrors); + Serial.print(F(",PacketsOK,")); + Serial.print(RXpacketCount); +} + + +void printmorepacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + RXerrors++; + Serial.print(F(",PacketError,RSSI")); + + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); +} + + +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 extractHABdata(uint8_t startaddr) +{ + //extracts data from received HAB packets where first fields are lat,lon,alt + //all varialbles are extracted, not all are used. + + uint8_t ptr = startaddr; //pointer to current location in SXbuffer + uint8_t buffData; + + //Skip leading $ + do + { + buffData = LT.getByteSXBuffer(ptr++); + } + while ( buffData == '$'); + + ptr--; //so ptr is at location of first non $ + + FlightIDlen = extractBuffer(FlightID, sizeof(FlightID), ptr); //extract flight ID + + ptr = nextComma(ptr); //step to next comma in SX buffer + TXSequence = extractUint(ptr); //extract sequence + + ptr = nextComma(ptr); + TXHours = (uint32_t) extractUint(ptr); + + ptr = nextComma(ptr); + TXMinutes = (uint32_t) extractUint(ptr); + + ptr = nextComma(ptr); + TXSeconds = (uint32_t) extractUint(ptr); + + //ptr = nextComma(ptr); + ptr = nextComma(ptr); + TXLat = extractFloat(ptr); + + ptr = nextComma(ptr); + TXLon = extractFloat(ptr); + + ptr = nextComma(ptr); + TXAlt = extractUint(ptr); + + ptr = nextComma(ptr); + TXSatellites = extractUint(ptr); + + ptr = nextComma(ptr); + TXVolts = extractUint(ptr); + + ptr = nextComma(ptr); + TXTemperature = extractUint(ptr); + + ptr = nextComma(ptr); + TXResets = extractUint(ptr); + + ptr = nextComma(ptr); + TXStatus = extractUint(ptr); + + ptr = nextComma(ptr); + TXErrors = extractUint(ptr); +} + + +void printHABdata() +{ + printBuffer(FlightID, FlightIDlen); + Serial.print(F(",")); + Serial.print(TXSequence); + Serial.print(F(",")); + + Serial.print(TXHours); + Serial.print(F(",")); + Serial.print(TXMinutes); + Serial.print(F(",")); + Serial.print(TXSeconds); + Serial.print(F(",")); + + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F(",")); + Serial.print(TXSatellites); + Serial.print(F(",")); + Serial.print(TXVolts); + Serial.print(F(",")); + Serial.print(TXTemperature); + Serial.print(F(",")); + Serial.print(TXResets); + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXErrors); +} + + +uint8_t extractBuffer(char *mybuffer, size_t bufferSize, uint8_t startptr) +{ + //extracts a character buffer in ASCII format from lora device RX buffer, returns the length of the buffer to , char + uint16_t index; + + memset(mybuffer, 0, bufferSize); //clear array to 0s + + bufferSize--; //last index location is one less than buffer size + + for (index = 0; index <= bufferSize; index++) + { + mybuffer[index] = LT.getByteSXBuffer(startptr++); + if ((mybuffer[index] == ',') || (mybuffer[index] == '*')) + { + break; + } + } + mybuffer[index] = 0; //it was a , so clear it + return index++; //buffer length is one more than index location +} + + +void printBuffer(char *buff, uint8_t len) +{ + //send buffer to serial terminal + uint8_t index; + + for (index = 0; index < len; index++) + { + Serial.write(buff[index]); + } + +} + + +uint8_t nextComma(uint8_t localpointer) +{ + //skips through HAB packet (in SX device buffer) to next comma + uint8_t bufferdata; + do + { + bufferdata = LT.getByteSXBuffer(localpointer++); + } + while ((bufferdata != ',') && (bufferdata != ':') && (localpointer < RXPacketL)); + return localpointer; //note returns start of next field +} + + +uint8_t nextColon(uint8_t localpointer) +{ + //skips through HAB packet (in SX device buffer) to next colon + uint8_t bufferdata; + do + { + bufferdata = LT.getByteSXBuffer(localpointer++); + } + while ((bufferdata != ':') && (localpointer < RXPacketL)); + return localpointer; +} + + +int32_t extractUint(uint16_t localpointer) +{ + //extracts an unsigned int in ASCII format from buffer + + char temp[16]; + uint8_t tempptr = 0; + uint8_t buffdata; + uint32_t tempint; + do + { + buffdata = LT.getByteSXBuffer(localpointer++);; + temp[tempptr++] = buffdata; + } + while ((buffdata != ',') && (buffdata != '*') && (localpointer < 256) ); + temp[tempptr] = 0; //terminator for string + tempint = (int32_t) atof(temp); + return tempint; +} + + +float extractFloat(uint16_t localpointer) +{ + //extracts a float in ASCII format from buffer + char temp[16]; + uint8_t tempptr = 0; + uint8_t buffdata; + float tempfloat; + do + { + buffdata = LT.getByteSXBuffer(localpointer++);; + temp[tempptr++] = buffdata; + } + while ((buffdata != ',') && (buffdata != '*') && (localpointer < 256) ); + temp[tempptr] = 0; //terminator for string + tempfloat = (float)atof(temp); + return tempfloat; +} + + +void setTrackerMode() +{ + LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation); +} + + +void setSearchMode() +{ + LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation); +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F(",")); +} + + +void GPSPowerOn(int8_t pin, uint8_t state) +{ + if (pin >= 0) + { + digitalWrite(pin, state); + } +} + +//************************************************************************ +// Display screen functions +//************************************************************************ + +void displayscreen1() +{ + //shows the received location data and packet reception on display + uint8_t index; + + disp.clearLine(0); + disp.setCursor(0, 0); + + if (PacketType == HABPacket) + { + for (index = 0; index < FlightIDlen; index++) + { + disp.write(FlightID[index]); + } + } + + if (PacketType == LocationBinaryPacket) + { + disp.print(Source); + } + + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(F("Lat ")); + disp.print(TXLat, 5); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(F("Lon ")); + disp.print(TXLon, 5); + disp.clearLine(3); + disp.setCursor(0, 3); + disp.print(F("Alt ")); + disp.print(TXAlt); + disp.print(F("m")); + + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(F("RSSI ")); + disp.print(PacketRSSI); + disp.print(F("dBm")); + disp.clearLine(5); + disp.setCursor(0, 5); + disp.print(F("SNR ")); + + if (PacketSNR > 0) + { + disp.print(F("+")); + } + + if (PacketSNR == 0) + { + disp.print(F(" ")); + } + + if (PacketSNR < 0) + { + disp.print(F("-")); + } + + disp.print(PacketSNR); + disp.print(F("dB")); + + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); +} + + +void displayscreen2() +{ + //show tracker transmitter powerup data on display + float tempfloat; + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("TXPowerup")); + disp.setCursor(0, 1); + disp.print(F("Battery,")); + tempfloat = ((float) TXVolts / 1000); + disp.print(tempfloat, 2); + disp.print(F("v")); +} + + +void displayscreen3() +{ + //show receive mode on display + disp.setCursor(14, 0); + + if (modeNumber == TrackerMode) + { + disp.print(F("TR")); + return; + } + + if (modeNumber == SearchMode) + { + disp.print(F("SE")); + return; + } + + disp.print(modeNumber); +} + + +void displayscreen4() +{ + //put RX and TX GPS fix status on display + + disp.setCursor(14, 1); + + if (RXGPSfix) + { + disp.print(F("RG")); + } + else + { + disp.setCursor(14, 1); + disp.print(F("R?")); + } + + disp.setCursor(14, 2); + + if (readTXStatus(GPSFix)) + { + disp.print(F("TG")); + } + else + { + disp.print(F("T?")); + } +} + + +void displayscreen5() +{ + //put distance and direction on display + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("D&D ")); + disp.print(TXdistance, 0); + disp.print(F("m ")); + disp.print(TXdirection); + disp.print(F("d")); + } +} + + +void displayscreen6() +{ + //no GPS fix + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("No GPS Fix")); +} + + +void displayscreen7() +{ + //display received packet count + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); +} + + +void setup() +{ + uint32_t endmS; + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + pinMode(SWITCH1, INPUT_PULLUP); //setup pin as switch input + + if (CHECK <= 0) + { + pinMode(CHECK, OUTPUT); + } + + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, 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("68_Balloon_Tracker_Receiver Starting")); + + SPI.begin(); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + Serial.print(F("Checking LoRa device - ")); + disp.setCursor(0, 0); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE)) //Initialize LoRa device + { + Serial.println(F("Receiver ready")); + disp.print(F("Ready")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No LoRa device responding")); + disp.print(F("No LoRa device")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + Serial.println(); + Serial.println(F("Startup GPS check")); + + endmS = millis() + 2000; + + //now startup GPS + GPSPowerOn(GPSPOWER, GPSONSTATE); + + GPSserial.begin(GPSBaud); + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(F("Done")); + Serial.println(); + Serial.flush(); + + GPSserial.end(); //software serial interferes with SPI for LoRa device + + setTrackerMode(); + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + + LT.printModemSettings(); + Serial.println(); + Serial.println(F("Listening in Tracker mode")); + Serial.println(); + Serial.write(7); //send a BELL to serial terminal + TXStatus = 4; //set default flag of no TX GPS fix +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/68_Balloon_Tracker_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/68_Balloon_Tracker_Receiver/Settings.h new file mode 100644 index 0000000..7ab3fda --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/68_Balloon_Tracker_Receiver/Settings.h @@ -0,0 +1,97 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 12/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. +*******************************************************************************************************/ + + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify lora board type and pins here +//************************************************************************************************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done +#define RFBUSY 7 //busy pin on LoRa device +#define LED1 8 //On board LED, high for on +#define SWITCH1 2 //if pin shorted to ground, switch is active + +#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 + +#define AUDIOOUT 4 //pin used to output Audio tones for HAB packet upload +#define CHECK -1 //this pin is toggled inside the AFSKRTTY library, high for logic 1, low for logic 0, so it can be used to check the timing. + +#define LORA_DEVICE DEVICE_SX1262 //this is the LoRa device we are using + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + + + +//************************************************************************************************** +// 3) LoRa modem settings +//************************************************************************************************** + +const uint32_t Offset = 0; //offset frequency for calibration purposes + +//Tracker mode +const uint32_t TrackerFrequency = 434000000; //frequency of transmissions +const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t TrackerTXpower = 10; //LoRa TX power in dBm +const uint8_t TrackerMode = 1; //used for receiver to tell whatmode it is in + +//Search mode +const uint32_t SearchFrequency = 434000000; //frequency of transmissions +const uint8_t SearchBandwidth = LORA_BW_062;; //LoRa bandwidth +const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t SearchTXpower = 10; //LoRa TX power in dBm +const uint8_t SearchMode = 2; //used for receiver to tell whatmode it is in + +const uint8_t RXBUFFER_SIZE = 128; //RX buffer size + +//************************************************************************************************** +// 4) GPS Options +//************************************************************************************************** + +const uint16_t GPSBaud = 9600; //GPS Baud rate + +#define USESOFTSERIALGPS //need to include this if we are using softserial for GPS +//#define HARDWARESERIALPORT Serial1 //if using hardware serial enable this define for hardware serial port + +const uint16_t WaitGPSFixSeconds = 30; //time to wait for a new GPS fix + +const uint16_t NoRXGPSfixms = 15000; //max number of mS to allow before no local fix flagged +const uint8_t DisplayRate = 7; //when working OK the GPS will get a new fix every second or so + //this rate defines how often the display should be updated + + +//************************************************************************************************** +// 6) AFSK RTTY Settings - For PC upload into Dl-Fldigi in HAB mode. +// Sent at 300baud, 7 bit, no parity, 2 stop bits. +// Shift 500hz, low tone 800hz, high tone 1300hz. +//************************************************************************************************** + +//#define UPLOADHABPACKET //comment in define to output HAB packet as AFSKRTTY for PC upload + +const uint16_t AFSKRTTYperiod = 3333; //period in uS for 1 bit at chosen baud rate, e.g. 10000 for 100baud, 3333 for 300baud +const uint16_t leadinmS = 500; //number of ms for AFSK constant lead in tone +const uint16_t tonehighHz = 1300; //high tone in Hertz +const uint16_t tonelowHz = 800; //low tone in Hertz + + + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/71_FSKRTTY_Transmitter_Test/71_FSKRTTY_Transmitter_Test.ino b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/71_FSKRTTY_Transmitter_Test/71_FSKRTTY_Transmitter_Test.ino new file mode 100644 index 0000000..0c6d337 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/71_FSKRTTY_Transmitter_Test/71_FSKRTTY_Transmitter_Test.ino @@ -0,0 +1,194 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 02/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 is a test program for using the LoRa device to transmit upper side band FSK + RTTY. With the LoRa device in FSK direct mode, the frequency of the generated carrier is shifted up + or down at the correct baud rate depending on whether a logic 0 or 1 is being sent. + + The desired shift in frequency is defined in the Settings.h file as 'FrequencyShift'. When the program + starts the actual frequency shift will be calculated according to the discrete frequency steps the + LoRa device can be set to. There are settings for number of data bits, number of start bits and the + value of parity which can be ParityNone, ParityOdd, ParityEven, ParityZero or ParityOne. + + Before the actual data transmission starts you can send a series of marker pips which are short bursts + of up shifted carrier which will be heard as beeps in a correctly tuned receiver. These pips can aid + in setting the receiver decode frequemcy to match the transmission. on some LoRa devices, such as the SX127x + series there can be considerable temperature induced frequency drift. This drift can be caused by outside + temperature changes or the RF device self heating when transmit is turned on. The duration of the pips, + the gaps between them and the period of leadin carrier before the data starts can all be set. To send no + pips just set the number to 0. + + The FSK RTTY routines use the micros() function for timing, and a check is made at the begging of a + character to send to see if micros() migh overflow during the transmission of the character. This check + assumes the lowest baud rate of 45baud, and if an overflow is likley, there will be a short in transmission + pause to allow the overflow to occur. + + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based +#include //include the appropriate SX12XX library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX126XLT LT; //create a library class instance called LT + +//Choose whichever test pattern takes your fancy +//uint8_t testBuffer[] = "0123456789* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"; //This string is sent as AFSK RTTY, 7 bit, 2 Stop bit, no parity, 300 baud. + +//uint8_t testBuffer[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789"; +//uint8_t testBuffer[] = "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"; +uint8_t testBuffer[] = "$$$$MyFlight1,2213,14:54:37,51.48230,-3.18136,15,6,3680,23,66,3,0*2935"; + +uint8_t freqShiftRegs[4]; //to hold returned registers that set frequency + + +void loop() +{ + uint8_t index; + + printRegisterSetup(FrequencyShift); + Serial.println(); + + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + if (micros() > 0xF8000000) + { + Serial.print(F("Waiting micros()")); + while(micros() < 0xFFFB6000); + } + + Serial.print(F("Start RTTY micros() = ")); + Serial.println(micros(),HEX); + LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed + for (index = 0; index < (sizeof(testBuffer)-1); index++) + { + LT.transmitFSKRTTY(testBuffer[index], DataBits, StopBits, Parity, BaudPerioduS, LED1); + Serial.write(testBuffer[index]); + } + + LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed + + Serial.println(); + Serial.print(F("END RTTY micros() = ")); + Serial.println(micros(),HEX); + digitalWrite(LED1, LOW); + Serial.println(); + Serial.println(); + + Serial.println(micros(),HEX); + + LT.setMode(MODE_STDBY_RC); + + delay(2000); +} + + +void printRegisterSetup(uint32_t shift) +{ + + uint32_t nonShiftedFreq, ShiftedFreq; + uint32_t freqShift; + float exactfreqShift; + + LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set + LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values + nonShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 24 ) + ( (uint32_t) freqShiftRegs[1] << 16 ) + ( (uint32_t) freqShiftRegs[2] << 8 ) + freqShiftRegs[3]; + Serial.print(F("NoShift Registers 0x")); + Serial.println(nonShiftedFreq, HEX); + + LT.setRfFrequency((Frequency + shift), Offset); //set shifted frequecy + LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values + ShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 24 ) + ( (uint32_t) freqShiftRegs[1] << 16 ) + ( (uint32_t) freqShiftRegs[2] << 8 ) + freqShiftRegs[3]; + Serial.print(F("Shifted Registers 0x")); + Serial.println(ShiftedFreq, HEX); + + freqShift = ShiftedFreq - nonShiftedFreq; + exactfreqShift = freqShift * FREQ_STEP; + Serial.print(F("FSKRTTY register shift ")); + Serial.println(freqShift,HEX); + Serial.print(F("FSKRTTY frequency shift ")); + Serial.print(exactfreqShift, 8); + Serial.println(F("hZ")); + + LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set +} + + +void printRegisterBuffer() +{ +Serial.print(freqShiftRegs[0],HEX); +Serial.print(F(" ")); +Serial.print(freqShiftRegs[1],HEX); +Serial.print(F(" ")); +Serial.print(freqShiftRegs[2],HEX); +Serial.println(); +Serial.print(freqShiftRegs[2],HEX); +Serial.println(); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("71_FSKRTTY_Transmitter_Test")); + + 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); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.setupDirect(Frequency, Offset); + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/71_FSKRTTY_Transmitter_Test/Settings.h b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/71_FSKRTTY_Transmitter_Test/Settings.h new file mode 100644 index 0000000..5f537ce --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX126x_examples/Tracker/71_FSKRTTY_Transmitter_Test/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + 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 are not used by this particular sketch so they are set to -1 and not connected. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 4 //on board LED, high for on +#define DIO1 3 //DIO1 pin on LoRa device, used for RX and TX done +#define RFBUSY 7 //busy pin on LoRa device + +#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 + + +//******* Setup FSKRTTY Settings here ! *************** + +uint32_t FrequencyShift = 500; //hertz frequency shift, approx, sent at nearest 0.95367431640625hz step +uint8_t NumberofPips = 2; //number of marker pips to send +uint16_t PipDelaymS = 500; //mS between pips, carrier off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 5000; //ms of leadin, shifted carrier +uint8_t DataBits = 7; //number of databits, normally 7 or 8 +uint8_t StopBits = 2; //number of stopbits, normally 1 or 2 +uint8_t Parity = ParityNone; //parity on data bits, ParityNone, ParityOdd, ParityEven, ParityZero, ParityOne + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/103_Lora_Transmitter_Detailed_Setup/103_Lora_Transmitter_Detailed_Setup.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/103_Lora_Transmitter_Detailed_Setup/103_Lora_Transmitter_Detailed_Setup.ino new file mode 100644 index 0000000..5332fbb --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/103_Lora_Transmitter_Detailed_Setup/103_Lora_Transmitter_Detailed_Setup.ino @@ -0,0 +1,183 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint8_t TXPacketL; +uint32_t TXPacketCount, startmS, endmS; + +uint8_t buff[] = "Hello World 1234567890"; + +void loop() +{ + Serial.print(TXpower); //print the transmit power defined + Serial.print(F("dBm ")); + Serial.print(F("Packet> ")); + Serial.flush(); + + TXPacketL = sizeof(buff); //set TXPacketL to length of array + buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver + + LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII + + digitalWrite(LED1, HIGH); + startmS = millis(); //start transmit timer + if (LT.transmit(buff, TXPacketL, 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, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //The function call list below shows the complete setup for the LoRa device using the information defined in the + //Settings.h file. + //The 'Setup LoRa device' list below can be replaced with a single function call; + //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done + //*************************************************************************************************** + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + Serial.println(); + LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/103_Lora_Transmitter_Detailed_Setup/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/103_Lora_Transmitter_Detailed_Setup/Settings.h new file mode 100644 index 0000000..5b38e9b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/103_Lora_Transmitter_Detailed_Setup/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + 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 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 LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/104_Lora_Receiver_Detailed_Setup/104_Lora_Receiver_Detailed_Setup.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/104_Lora_Receiver_Detailed_Setup/104_Lora_Receiver_Detailed_Setup.ino new file mode 100644 index 0000000..af97e74 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/104_Lora_Receiver_Detailed_Setup/104_Lora_Receiver_Detailed_Setup.ino @@ -0,0 +1,250 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int16_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 + } + + delay(10); //so we can see LED flash more easily on fast processors + 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, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("Lora Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //The function call list below shows the complete setup for the LoRa device using the information defined in the + //Settings.h file. + //The 'Setup Lora device' list below can be replaced with a single function call; + //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + //*************************************************************************************************** + //Setup Lora device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done + //*************************************************************************************************** + + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check + Serial.println(); + Serial.println(); + LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/104_Lora_Receiver_Detailed_Setup/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/104_Lora_Receiver_Detailed_Setup/Settings.h new file mode 100644 index 0000000..60f933f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/104_Lora_Receiver_Detailed_Setup/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + 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 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 pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 2; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino new file mode 100644 index 0000000..845f658 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino @@ -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 +#include +#include "Settings.h" + +SX127XLT 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, DIO0, DIO1, DIO2, 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/14_LoRa_Structure_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/14_LoRa_Structure_TX/Settings.h new file mode 100644 index 0000000..5387024 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/14_LoRa_Structure_TX/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power + +#define packet_delay 1000 //mS delay between packets diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino new file mode 100644 index 0000000..393b041 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino @@ -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 +#include +#include "Settings.h" + +SX127XLT LT; + +uint8_t RXPacketL; //stores length of packet received +uint32_t RXpacketCount; //count of received packets +int16_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, DIO0, DIO1, DIO2, 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/15_LoRa_Structure_RX/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/15_LoRa_Structure_RX/Settings.h new file mode 100644 index 0000000..d3dc3d9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/15_LoRa_Structure_RX/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power in dBm + +#define packet_delay 1000 //mS delay between packets diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/1_LED_Blink/1_LED_Blink.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/1_LED_Blink/1_LED_Blink.ino new file mode 100644 index 0000000..d80c1e5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/1_LED_Blink/1_LED_Blink.ino @@ -0,0 +1,72 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This programs is supplied as is, it is up to the user of the program to decide if the programs are + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program blinks an LED connected the pin number defined below. The 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 + digitalWrite(LED1, HIGH); + digitalWrite(13, HIGH); + + 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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/2_Register_Test/2_Register_Test.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/2_Register_Test/2_Register_Test.ino new file mode 100644 index 0000000..6f93f8d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/2_Register_Test/2_Register_Test.ino @@ -0,0 +1,266 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 18/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 stand alone, it is not necessary to install the SX12XX-LoRa library + to use it. This test program is for the SX127X LoRa devices. + + 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 and the program then changes the frequency between two values and prints + out the registers. This is to prove that the device registers are being read and written correctly. + There is a copy of the 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. Although the program sets the frequency in the 434Mhz band, it will work on 868Mhz and + 915Mhz devices and there is no attempt to confugure the device for transmission or reception. + + The Arduino pin number that NSS on the LoRa device is connected to must be specified in #define NSS + line below. Leave the NRESET and DIOx pins not connected. + + Typical printout; + + 2_Register_Test Starting + LoRa Device found + Device version 0x12 + Frequency at Start 434000000 + Registers at Start + 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 FD 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 FD 06 00 5C 78 + 0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + Change Frequency to 434100000 + 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 FD 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 FD 06 00 5C 78 + 0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Change Frequency to 434200000 + Changed Frequency 434199936 + 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 8C CC 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 FD 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 FD 06 00 5C 78 + 0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Note: An SX1272 will report as version 0x22 and the frequency at power up is 915000000hz. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +const uint8_t REG_FRMSB = 0x06; //register number for setting and reading frequency, high byte +const uint8_t REG_FRMID = 0x07; //register number for setting and reading frequency, mid byte +const uint8_t REG_FRLSB = 0x08; //register number for setting and reading frequency, low byte +const uint8_t REG_VERSION = 0x42; //register containg version number of device + + +//********* Setup hardware pin definition here ! ************** + +#define NSS 10 //lora device select + +//**************************************************************/ + + +#include + +uint32_t frequency; + + +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 + + if (begin(NSS)) + { + Serial.println(F("LoRa Device found")); + } + else + { + Serial.println(F("No device responding")); + } + + Serial.print(F("Device version 0x")); + uint8_t deviceversion = readRegister(REG_VERSION); + if (deviceversion < 0x10) + { + Serial.print(F("0")); + } + Serial.println(deviceversion, HEX); + + frequency = getFreqInt(); //read the set frequency following a reset + Serial.print(F("Frequency at Start ")); + Serial.println(frequency); + + Serial.println(F("Registers at Start ")); //show the all registers following a power up + printRegisters(0x00, 0x7F); +} + + +void loop() +{ + Serial.println(); + Serial.println(); + + Serial.println(F("Change Frequency to 434100000")); + setRfFrequency(434100000, 0); //change the frequency at reset, in hertz + frequency = getFreqInt(); //read back the changed frequency + Serial.print(F("Changed Frequency ")); + Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ? + printRegisters(0x00, 0x7F); //show the registers after frequency change + Serial.println(); + + Serial.println(F("Change Frequency to 434200000")); + setRfFrequency(434200000, 0); //change the frequency at reset, in hertz + frequency = getFreqInt(); //read back the changed frequency + Serial.print(F("Changed Frequency ")); + Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ? + printRegisters(0x00, 0x7F); //show the registers after frequency change + Serial.println(); + + delay(5000); +} + + +uint8_t readRegister(uint8_t address) +{ + uint8_t regdata; + digitalWrite(NSS, LOW); //set NSS low + SPI.transfer(address & 0x7F); //mask address for read + regdata = SPI.transfer(0); //read the byte + digitalWrite(NSS, HIGH); //set NSS high + return regdata; +} + + +void writeRegister(uint8_t address, uint8_t value) +{ + digitalWrite(NSS, LOW); //set NSS low + SPI.transfer(address | 0x80); //mask address for write + SPI.transfer(value); //write the byte + digitalWrite(NSS, HIGH); //set NSS high +} + + +uint32_t getFreqInt() +{ + //get the current set LoRa device frequency, return as long integer + + uint8_t Msb, Mid, Lsb; + uint32_t uinttemp; + float floattemp; + Msb = readRegister(REG_FRMSB); + Mid = readRegister(REG_FRMID); + Lsb = readRegister(REG_FRLSB); + floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb); + floattemp = ((floattemp * 61.03515625) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +void printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of lora device registers to serial monitor + + uint16_t Loopv1, Loopv2, RegData; + + Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F")); + Serial.println(); + + for (Loopv1 = Start; Loopv1 <= End;) + { + Serial.print(F("0x")); + if (Loopv1 < 0x10) + { + Serial.print(F("0")); + } + Serial.print((Loopv1), HEX); + Serial.print(F(" ")); + for (Loopv2 = 0; Loopv2 <= 15; Loopv2++) + { + RegData = readRegister(Loopv1); + if (RegData < 0x10) + { + Serial.print(F("0")); + } + Serial.print(RegData, HEX); + Serial.print(F(" ")); + Loopv1++; + } + Serial.println(); + } +} + + +void setRfFrequency(uint64_t freq64, int32_t offset) +{ + freq64 = freq64 + offset; + freq64 = ((uint64_t)freq64 << 19) / 32000000; + writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16)); + writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8)); + writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0)); +} + + +bool begin(int8_t pinNSS) +{ + pinMode(pinNSS, OUTPUT); + digitalWrite(pinNSS, HIGH); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool checkDevice() +{ + //check there is a device out there, writes a register and reads back + + uint8_t Regdata1, Regdata2; + Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting + writeRegister(REG_FRMID, (Regdata1 + 1)); + Regdata2 = readRegister(REG_FRMID); //read changed value back + writeRegister(REG_FRMID, Regdata1); //restore register to original value + + if (Regdata2 == (Regdata1 + 1)) + { + return true; + } + else + { + return false; + } +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino new file mode 100644 index 0000000..3884ab4 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino @@ -0,0 +1,121 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library + +SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for sensing RX and TX done +#define LORA_DEVICE DEVICE_SX1278 //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, DIO0, 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 +} + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino new file mode 100644 index 0000000..93bda37 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino @@ -0,0 +1,168 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library + +SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using +#define RXBUFFER_SIZE 255 //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 +int16_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, DIO0, 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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/58_FM_Tone/58_FM_Tone.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/58_FM_Tone/58_FM_Tone.ino new file mode 100644 index 0000000..e19742f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/58_FM_Tone/58_FM_Tone.ino @@ -0,0 +1,93 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT 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 + + 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, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.setupDirect(Frequency, Offset); + Serial.print(F("Tone Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/58_FM_Tone/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/58_FM_Tone/Settings.h new file mode 100644 index 0000000..75650d2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/58_FM_Tone/Settings.h @@ -0,0 +1,32 @@ +/******************************************************************************************************* + 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 are not used by this particular sketch so they are set to -1 and not connected. + +#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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup Direct Modem Parameters Here ! *************** + +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes +const uint16_t deviation = 10000; //deviation, total frequency shift low to high +const float adjustfreq = 0.9; //adjustment to tone frequency + +const int8_t TXpower = 10; //LoRa transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/73_LoRa_Receiver_AFC/73_LoRa_Receiver_AFC.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/73_LoRa_Receiver_AFC/73_LoRa_Receiver_AFC.ino new file mode 100644 index 0000000..d0453d7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/73_LoRa_Receiver_AFC/73_LoRa_Receiver_AFC.ino @@ -0,0 +1,200 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 10/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 demonstration of using automatic frequency adjustments (AFC) on a receiver + to keep the frequency difference between transmitter and receiver as low as possible. The LoRa settings + used are defined in the Settings.h file. + + If a packet is received OK, then all that is needed is a call to the LT.doAFC() function, that reads the + last frequency error, calculates the new offset and changes the set frequency accordingly. + + When the receiver starts the frequency error may be as large as 4000hz, when the AFC operates the error + should reduce to 100hz or so. The first AFC correction to run is doAFCPPM(); which based on the frequency + error also adjusts the PPM setting. If doAFC(); were only used then as the frequency error is reduced then + the PPM adjustment would reduce. + + Note that the maximum permitted frequency error between transmitter and receiver is 25% of the bandwidth + in use. So at 125000hz bandwidth the maximum frequency error is 31500hz, if the bandwidth is 7800hz the + maximum frequency error is 1950hz. Whilst the AFC functionality can keep transmitter and receiver close + together when reception is working if the transmitter and receiver are to far apart in frequency for + reception to work in the first place then AFC cannot operate to correct for the frequency differences. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int16_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet +int32_t frequencyerror; //frequency error of receved packet + +bool FirstAFC = true; //used to note that AFC has been called more than once + +void loop() +{ + + Serial.print(F("SetFrequency,")); + Serial.print(Frequency); + Serial.print(F("hz,Offset,")); + Serial.print(LT.getOffset()); + Serial.print(F("hz ")); + + 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(); + if (FirstAFC) + { + LT.doAFCPPM(); //the first time AFC is called do the PPM adjust also + FirstAFC = false; + } + else + { + LT.doAFC(); //PPM adjust has been done so now just adjust frequency + } + } + + Serial.println(); +} + + +void packet_is_OK() +{ + uint16_t IRQStatus; + + + RXpacketCount++; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + frequencyerror = LT.getFrequencyErrorHz(); + printElapsedTime(); //print elapsed time to Serial Monitor + + Serial.print(F(" ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters + Serial.print(F(",")); + Serial.print(LT.readRegister(REG_FEIMSB),HEX); + Serial.print(F(",")); + Serial.print(LT.readRegister(REG_FEIMID),HEX); + Serial.print(F(",")); + Serial.print(LT.readRegister(REG_FEILSB),HEX); + Serial.print(F(",Regval,")); + Serial.print(LT.getFrequencyErrorRegValue(),HEX); + Serial.print(F(",FreqErrror,")); + Serial.print(frequencyerror); + Serial.print(F("hz,PpmCorrection,")); + Serial.print(LT.readRegister(REG_PPMCORRECTION)); + 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")); +} + + +void setup() +{ + Serial.begin(9600); + Serial.println(); + Serial.println(F("73_LoRa_Receiver_AFC starting")); + Serial.println(); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1); + } + + 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.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/73_LoRa_Receiver_AFC/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/73_LoRa_Receiver_AFC/Settings.h new file mode 100644 index 0000000..99b3506 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/73_LoRa_Receiver_AFC/Settings.h @@ -0,0 +1,41 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 10/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. +*******************************************************************************************************/ + +//******* 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 pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup 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 128 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/80_Direct_DIO2_Tone/80_Direct_DIO2_Tone.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/80_Direct_DIO2_Tone/80_Direct_DIO2_Tone.ino new file mode 100644 index 0000000..9a3ceeb --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/80_Direct_DIO2_Tone/80_Direct_DIO2_Tone.ino @@ -0,0 +1,106 @@ +/******************************************************************************************************* + 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 generated in direct mode by applying a pulse using the Arduino tone() + function (not supported by all Arduinos) to the DIO2 pin. + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LoRa; //create a library class instance called LoRa + + +void loop() +{ + Serial.print(TXpower); //print the transmit power defined + Serial.print(F("dBm ")); + Serial.println(F("PlayTones> ")); + Serial.println(); + + LoRa.setupDirect(Frequency, Offset); + LoRa.setTXDirect(); //turn on transmit + LoRa.setTxParams(TXpower, RADIO_RAMP_DEFAULT); //set TX power + LoRa.writeRegister(REG_FDEVLSB, deviation); //set the deviation + LoRa.writeRegister(REG_PLLHOP, 0xAD); //set fast hop mode, needed for fast changes of frequency + + + while(1) //repeat forever + { + digitalWrite(LED1, HIGH); + tone(DIO2, 1000); //pin, frequency, durationmS + delay(1000); + digitalWrite(LED1, LOW); + noTone(DIO2); + 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 + pinMode(6, OUTPUT); + + 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("80_Direct_DIO2_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 (LoRa.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + Serial.print(F("Tone Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/80_Direct_DIO2_Tone/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/80_Direct_DIO2_Tone/Settings.h new file mode 100644 index 0000000..4f78e28 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Basics/80_Direct_DIO2_Tone/Settings.h @@ -0,0 +1,31 @@ +/******************************************************************************************************* + 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 are not used by this particular sketch so they are set to -1 and not connected. + +#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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 6 //DIO2 pin on LoRa device can be used for tone + + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup Direct Modem Parameters Here ! *************** + +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t deviation = 0x52; //set approx 5khz deviation +const int8_t TXpower = 10; //LoRa transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino new file mode 100644 index 0000000..8c9d438 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino @@ -0,0 +1,266 @@ +/******************************************************************************************************* + 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 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 +#include +#include +#include "Settings.h" + +SX127XLT 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, DIO0, DIO1, DIO2, 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(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h new file mode 100644 index 0000000..2af3e21 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2 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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 17; //Transmit power used when sending packet starting test sequence +const int8_t start_power = 17; //link test starts at this transmit power +const int8_t end_power = 2; //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 + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino new file mode 100644 index 0000000..46e1a2b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino @@ -0,0 +1,223 @@ +/******************************************************************************************************* + 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 - 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 +#include +#include "Settings.h" +#include //get the library here; https://github.com/PaulStoffregen/Time +time_t recordtime; //used to record the current time, preventing displayed rollover on printing + +SX127XLT LT; + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXPacketL; //stores length of packet received +int16_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_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, DIO0, DIO1, DIO2, 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h new file mode 100644 index 0000000..8e94b8d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be connected +//and should be set to -1. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on +#define BUZZER 4 //Buzzer if fitted, high for on. Set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 2; //LoRa TX power + +#define packet_delay 1000 //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/13_Frequency_and_Power_Check_TX/13_Frequency_and_Power_Check_TX.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/13_Frequency_and_Power_Check_TX/13_Frequency_and_Power_Check_TX.ino new file mode 100644 index 0000000..7878ba9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/13_Frequency_and_Power_Check_TX/13_Frequency_and_Power_Check_TX.ino @@ -0,0 +1,138 @@ +/******************************************************************************************************* + 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 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 powwer, are specified in the 'Settings.h' file. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +SX127XLT LT; + +uint8_t TXPacketL; +uint32_t TXPacketCount; + + +void loop() +{ + Serial.print(F("Sending ")); + Serial.print(TXpower); + Serial.print(F("dBm Packet > ")); + Serial.flush(); + + uint8_t buff[] = "Hello World!1234Hello World!1234"; //use a longish packet to measure + TXPacketL = sizeof(buff); + + LT.printASCIIPacket(buff, TXPacketL); //print the packet + + digitalWrite(LED1, HIGH); + if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 + { + TXPacketCount++; + packet_is_OK(); + digitalWrite(LED1, LOW); + } + else + { + packet_is_Error(); + digitalWrite(LED1, LOW); + } + + Serial.println(); + delay(packet_delay); +} + + +void packet_is_OK() +{ + Serial.print(F(" ")); + Serial.print(TXPacketL); + Serial.print(F(" Bytes SentOK")); + Serial.print(F(" PacketsSent ")); + Serial.print(TXPacketCount); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet send error +} + + +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("13_Frequency_and_Power_Check_TX Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.print(F("Transmitter ready - TXBUFFER_SIZE ")); + Serial.println(TXBUFFER_SIZE); + + LT.printModemSettings(); + Serial.println(); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/13_Frequency_and_Power_Check_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/13_Frequency_and_Power_Check_TX/Settings.h new file mode 100644 index 0000000..6fa1eac --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/13_Frequency_and_Power_Check_TX/Settings.h @@ -0,0 +1,41 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be +//connected and should be set to -1. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_010; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_8; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power in dBm, 10dBm = 10mW + +#define packet_delay 2500 //mS delay between transmissions + +#define TXBUFFER_SIZE 64 //TX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino new file mode 100644 index 0000000..1fa01e5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino @@ -0,0 +1,183 @@ +/******************************************************************************************************* + 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 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'. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +SX127XLT 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 +int16_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, DIO0, DIO1, DIO2, 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(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h new file mode 100644 index 0000000..0d2e943 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER 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 on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power + +#define packet_delay 1000 //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino new file mode 100644 index 0000000..a04453d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino @@ -0,0 +1,298 @@ +/******************************************************************************************************* + 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 - 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.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc +#include + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int16_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio of received packet + +uint32_t Test1Count[21]; //buffer where counts of received packets are stored, +2dbm to +20dBm +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) + { + lTXpower = ((RXBUFFER[1] - 48) * 10) + (RXBUFFER[2] - 48); //convert packet text to power + + Serial.print(F(" (")); + Serial.print(lTXpower); + Serial.print(F("dBm)")); + + if (updateCounts) + { + temp = (Test1Count[lTXpower]); + Test1Count[lTXpower] = 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 = 20; index >= 2; index--) + { + Serial.print(index); + Serial.print(F("dBm,")); + j = Test1Count[index]; + Serial.print(j); + Serial.print(F(" ")); + } + Serial.println(); + + Serial.print(F("CSV")); + for (index = 20; index >= 2; 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, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h new file mode 100644 index 0000000..70fce03 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino new file mode 100644 index 0000000..c8088b9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino @@ -0,0 +1,283 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/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 - 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +#include //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 + +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 +int16_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(DEFAULTFONT); + + 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, DIO0, DIO1, DIO2, 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h new file mode 100644 index 0000000..314d367 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 2; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 255 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino new file mode 100644 index 0000000..92399f9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino @@ -0,0 +1,282 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a program that can be used to test the throughput of a LoRa transmitter. + Whilst the various LoRa calculators tell you the on air data rate, in practice the achievable data + rate will be less than that due to the overhead of the software routines to load and send a packet + and internal delays in the LoRa device itself. + + A buffer is filled with characters and that buffer is then transmitted. The total time for a number of + transmissions is recorded and the bit rate calculated. The packet size (1 - 255 bytes) and the number of + packets to send in the test are specified in the 'Settings.h' file, see the 'Setup packet parameters Here !' + section. The setting file also has the lora settings to use. A lower spreading factors and higher + bandwidths will result in higher bitrates. + + There is the option of turning on an a requirement for an acknowledgement from a remote receiver, before + the transmitter sends the next packet, set this; 'const bool waitforACK = true;' definition in the + settings file. The 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; + + SX1278,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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t startmS, endmS, sendtimemS, bitspersecond, bitsPerpacket; +uint32_t TXPacketCount; +float averagePacketTime; +uint8_t packetNumber; +uint8_t RXPacketL; //length of received packet +uint8_t PacketType; //for packet addressing, identifies packet type received +uint32_t packetCheck; +bool loopFail = false; + + +void loop() +{ + uint16_t index, index2; + uint8_t TXBUFFER[TXPacketL + 1]; //create buffer for transmitted packet + loopFail = false; + + Serial.println(F("Start transmit test")); + + startmS = millis(); //start transmit timer + + for (index = 0; index < numberPackets; index++) + { + //fill the buffer + for (index2 = 0; index2 < TXPacketL; index2++) + { + TXBUFFER[index2] = index2; + } + + TXBUFFER[0] = TestPacket; //set first byte to identify this test packet + TXBUFFER[1] = index; //put the index as packet number in second byte of packet + Serial.print(index); //print number of packet sent + + if (waitforACK) + { + packetCheck = ( (uint32_t) TXBUFFER[4] << 24) + ( (uint32_t) TXBUFFER[3] << 16) + ( (uint32_t) TXBUFFER[2] << 8) + (uint32_t) TXBUFFER[1]; + Serial.print(F(",Checkvalue,")); + Serial.print(packetCheck, HEX); + Serial.print(F(",")); + } + + digitalWrite(LED1, HIGH); + + if (LT.transmit(TXBUFFER, TXPacketL, 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, DIO0, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h new file mode 100644 index 0000000..6d46521 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h @@ -0,0 +1,42 @@ +/******************************************************************************************************* + 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 LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 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 = 16; //length of packet to send +const bool waitforACK = true; //set to true to have transmit wait for ack before continuing + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/43_LoRa_Data_Throughput_Acknowledge_Receiver/43_LoRa_Data_Throughput_Acknowledge_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/43_LoRa_Data_Throughput_Acknowledge_Receiver/43_LoRa_Data_Throughput_Acknowledge_Receiver.ino new file mode 100644 index 0000000..80baabd --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/43_LoRa_Data_Throughput_Acknowledge_Receiver/43_LoRa_Data_Throughput_Acknowledge_Receiver.ino @@ -0,0 +1,174 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 25/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 receiver program that can be used to test the throughput of a LoRa + transmitter. The matching program '42_LoRa_Data_Throughput_Test_Transmitter' is setup to send packets + that require an acknowledgement before sending the next packet. This will slow down the effective + throughput. Make sure the lora settings in the 'Settings.h' file match those used in the transmitter. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[255]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +uint8_t TXPacketL; //stores length of packet sent +int16_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet + +uint8_t PacketType; //for packet addressing, identifies packet type +uint32_t packetCheck; + +void loop() +{ + RXPacketL = LT.receive(RXBUFFER, 255, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout + + digitalWrite(LED1, HIGH); //something has happened + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL is 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); //LED off + + Serial.println(); +} + + +void packet_is_OK() +{ + RXpacketCount++; + Serial.print(RXBUFFER[1]); + Serial.print(F(" RX")); + packetCheck = ( (uint32_t) RXBUFFER[4] << 24) + ( (uint32_t) RXBUFFER[3] << 16) + ( (uint32_t) RXBUFFER[2] << 8 ) + (uint32_t) RXBUFFER[1]; + Serial.print(F(",SendACK")); + sendAck(packetCheck); +} + + +void sendAck(uint32_t num) +{ + //acknowledge the packet received + uint8_t len; + + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(ACK); //identify type of packet + LT.writeUint32(num); //send the packet check, bytes 1 to 5 of packet + len = LT.endWriteSXBuffer(); //close buffer write + + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F(",RXTimeout")); + } + else + { + errors++; + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + Serial.print(F("Error")); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,Len,")); + Serial.print(LT.readRXPacketL()); //get the device packet length + } +} + + +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("43_LoRa_Data_Throughput_Acknowledge_Receiver Starting")); + Serial.println(); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, 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 + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/43_LoRa_Data_Throughput_Acknowledge_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/43_LoRa_Data_Throughput_Acknowledge_Receiver/Settings.h new file mode 100644 index 0000000..0f3216a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/43_LoRa_Data_Throughput_Acknowledge_Receiver/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 25/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 pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done + + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/60_LoRa_Packet_Logger_Receiver_SD.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/60_LoRa_Packet_Logger_Receiver_SD.ino new file mode 100644 index 0000000..fd1a5df --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/60_LoRa_Packet_Logger_Receiver_SD.ino @@ -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 + +#include //https://github.com/greiman/SdFat +SdFat SD; +File logFile; +char filename[] = "Log000.txt"; + +bool SD_Found = false; //set if SD card found at program startup +uint8_t lognumber; + + +#include +SX127XLT LT; + +#include "Settings.h" +#include //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 +int16_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, DIO0, 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/SD_Logger_Library.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/SD_Logger_Library.h new file mode 100644 index 0000000..cfa0313 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/SD_Logger_Library.h @@ -0,0 +1,410 @@ +//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; + + if (LORA_DEVICE == DEVICE_SX1272) + { + regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_2); + } + else + { + regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_X); + } + + //get al the data frome the lora device in one go to avoid swapping + //devices on the SPI bus all the time + + if (LORA_DEVICE == DEVICE_SX1272) + { + regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_2); + } + else + { + regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_X); + } + + bandwidth = LT.returnBandwidth(regdata); + freqint = LT.getFreqInt(); + sf = LT.getLoRaSF(); + cr = LT.getLoRaCodingRate(); + 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 ver = LT.getVersion(); + uint8_t pm = LT.getPacketMode(); + uint8_t hm = LT.getHeaderMode(); + uint8_t crcm = LT.getCRCMode(); + uint8_t agc = LT.getAGC(); + uint8_t lnag = LT.getLNAgain(); + uint8_t boosthf = LT.getLNAboostHF(); + uint8_t boostlf = LT.getLNAboostLF(); + uint8_t opmode = LT.getOpmode(); + + printDeviceSD(); + logFile.print(F(",")); + + printOperatingModeSD(opmode); + + logFile.print(F(",Version_")); + logFile.print(ver, HEX); + + 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(",AGCauto_")); + if (agc) + { + logFile.print(F("On")); + } + else + { + logFile.print(F("Off")); + } + + logFile.print(F(",LNAgain_")); + logFile.print(lnag); + + logFile.print(F(",LNAboostHF_")); + if (boosthf) + { + logFile.print(F("On")); + } + else + { + logFile.print(F("Off")); + } + + logFile.print(F(",LNAboostLF_")); + if (boostlf) + { + logFile.print(F("On")); + } + else + { + logFile.print(F("Off")); + } + 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_SX1272: + logFile.print(F("SX1272")); + break; + + case DEVICE_SX1276: + logFile.print(F("SX1276")); + break; + + case DEVICE_SX1277: + logFile.print(F("SX1277")); + break; + + case DEVICE_SX1278: + logFile.print(F("SX1278")); + break; + + case DEVICE_SX1279: + logFile.print(F("SX1279")); + 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)); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/Settings.h new file mode 100644 index 0000000..9b98cff --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/60_LoRa_Packet_Logger_Receiver_SD/Settings.h @@ -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 base for my BBF modules. +//Be sure to change the definitions to match your own setup. Some pins such as DIO1, DIO210 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 on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on +#define BUZZER 4 //Buzzer if fitted, high for on. Set to -1 if not used +#define SDCS 30 //CS pin for SD card + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power + +#define packet_delay 1000 //mS delay between packets + + +#define RXBUFFER_SIZE 255 //RX buffer size diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/66_FSK_Carrier_Generator/66_FSK_Carrier_Generator.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/66_FSK_Carrier_Generator/66_FSK_Carrier_Generator.ino new file mode 100644 index 0000000..c69df8e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/66_FSK_Carrier_Generator/66_FSK_Carrier_Generator.ino @@ -0,0 +1,98 @@ +/******************************************************************************************************* + 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 an FSK carrier on a single frequency. Useful for checking the output + of a LoRa device. View the output level on a low cost SDR or spectrum analyser. + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + + +void loop() +{ + Serial.print(TXpower); //print the transmit power defined + Serial.print(F("dBm ")); + + digitalWrite(LED1, HIGH); + Serial.print(F("Transmit Carrier > On ")); + + LT.setupDirect(Frequency, Offset); + LT.fskCarrierOn(TXpower); + delay(2000); + LT.fskCarrierOff(); + + digitalWrite(LED1, LOW); + Serial.println(F("off")); + + 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 + + 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("66_FSK_Carrier_Generator Starting")); + + SPI.begin(); + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //LT.setupDirect(Frequency, Offset); + //Serial.print(F("Transmitter ready")); + //Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/66_FSK_Carrier_Generator/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/66_FSK_Carrier_Generator/Settings.h new file mode 100644 index 0000000..c1f51f0 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Diagnostic_and_Test/66_FSK_Carrier_Generator/Settings.h @@ -0,0 +1,28 @@ +/******************************************************************************************************* + 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 are not used by this particular sketch so they are set to -1 and not connected. + +#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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup Direct Modem Parameters Here ! *************** + +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const int8_t TXpower = 2; //LoRa transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/1_LED_Blink_ESP32/1_LED_Blink_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/1_LED_Blink_ESP32/1_LED_Blink_ESP32.ino new file mode 100644 index 0000000..e9a69bf --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/1_LED_Blink_ESP32/1_LED_Blink_ESP32.ino @@ -0,0 +1,63 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/19 + + This programs is supplied as is, it is up to the user of the program to decide if the programs are + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program blinks an LED connected the pin number defined below. The blinks + should be close to one per second. messages are sent to the Serial Monitor also. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define LED1 2 //pin number for LED, set logic level high for on + +#define Program_Version "V1.0" + +uint16_t seconds; //used to display time elapsed on Serial Monitor + +void loop() +{ + Serial.print(seconds); + Serial.println(F(" Seconds")); //this message should print on console at close to once per second + seconds++; + digitalWrite(LED1, HIGH); + delay(100); + digitalWrite(LED1, LOW); + delay(890); //should give approx 1 second flash +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //general purpose routine for flashing LED as indicator + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); //LED on + delay(delaymS); + digitalWrite(LED1, LOW); //LED off + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("1_LED_Blink_ESP32 Starting")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/2_Register_Test_ESP32/2_Register_Test_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/2_Register_Test_ESP32/2_Register_Test_ESP32.ino new file mode 100644 index 0000000..e7cee2f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/2_Register_Test_ESP32/2_Register_Test_ESP32.ino @@ -0,0 +1,300 @@ +/******************************************************************************************************* + + Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program is stand alone, it is not necessary to install the SX12XX-LoRa library + to use it. + + The program checks that a SX127X LoRa device can be accessed by doing a test register write and read. + If there is no device found a message is printed on the serial monitor. The contents of the registers + from 0x00 to 0x7F are printed, there is a copy of a typical printout below. Note that the read back + changed frequency may be slightly different to the programmed frequency, there is a rounding error due + to the use of floats to calculate the frequency. + + The Arduino pin numbers that the NSS and NRESET pins on the LoRa device are connected to must be + specified in the hardware definitions section below. The LoRa device type in use, SX1272, SX1276, + SX1277, SX1278 or SX1279 must be specified also. + + Typical printout; + + 2_Register_Test Starting + SX1276-79 Selected + LoRa Device found + Device version 0x12 + + Frequency at reset 434000000 + Registers at reset + Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x00 00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A + 0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40 + 0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55 + 0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40 + 0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B + 0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78 + 0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Changed Frequency 434099968 + Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x00 00 09 1A 0B 00 52 6C 86 66 4F 09 2B 20 08 02 0A + 0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40 + 0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55 + 0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40 + 0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B + 0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78 + 0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +const uint8_t REG_FRMSB = 0x06; //register number for setting setting and reading frequency, high byte +const uint8_t REG_FRMID = 0x07; //register number for setting setting and reading frequency, mid byte +const uint8_t REG_FRLSB = 0x08; //register number for setting setting and reading frequency, low byte +const uint8_t REG_VERSION = 0x42; //register containg version number of device + +const uint8_t DEVICE_SX1272 = 0x10; //SX1272 +const uint8_t DEVICE_SX1276 = 0x11; //SX1276 +const uint8_t DEVICE_SX1277 = 0x12; //SX1277 +const uint8_t DEVICE_SX1278 = 0x13; //SX1278 +const uint8_t DEVICE_SX1279 = 0x14; //SX1279 + +//********* Setup hardware definitions here ! ***************** + +//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change +//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the +//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. + +#define NSS 5 //SX127X device select +#define NRESET 27 //SX127X reset pin +#define DIO0 -1 //DIO0 pin on LoRa device, not used here so set to -1 +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //defines the type of LoRa device used, needed for correct program operation + +//**************************************************************/ + + +#include + + +void setup() +{ + Serial.begin(9600); + Serial.println(F("2_Register_Test_ESP32 Starting")); + + SPI.begin(); + SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //The begin function setups the hardware pins used by device and then checks if device is found + //the DIO0, DIO1 and DIO2 pins are not used in this example so are set to -1 + //the LT.begin fuction can define the pins and device type directly in this way (for SX1278); + //LT.begin(10, 9, -1, -1, -1, DEVICE_SX1278) + + if (begin(NSS, NRESET, -1, -1, -1, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + } + else + { + Serial.println(F("No device responding")); + } + + Serial.print(F("Device version 0x")); + uint8_t deviceversion = readRegister(REG_VERSION); + if (deviceversion < 0x10) + { + Serial.print(F("0")); + } + Serial.println(deviceversion, HEX); +} + + +void loop() +{ + uint32_t frequency; + + frequency = getFreqInt(); //read the set frequency following a reset + Serial.print(F("Frequency at reset ")); + Serial.println(frequency); + + Serial.println(F("Registers at reset")); //show the all registers following a reset + printRegisters(0x00, 0x7F); + + Serial.println(); + Serial.println(); + + setRfFrequency(434100000, 0); //change the frequency at reset, in hertz + frequency = getFreqInt(); //read back the changed frequency + Serial.print(F("Changed Frequency ")); + Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ? + printRegisters(0x00, 0x7F); //show the registers after frequency change + Serial.println(); + delay(5000); + resetDevice(LORA_DEVICE); //reset the device and start again +} + + +uint8_t readRegister(uint8_t address) +{ + uint8_t regdata; + digitalWrite(NSS, LOW); //set NSS low + SPI.transfer(address & 0x7F); //mask address for read + regdata = SPI.transfer(0); //read the byte + digitalWrite(NSS, HIGH); //set NSS high + return regdata; +} + + +void writeRegister(uint8_t address, uint8_t value) +{ + digitalWrite(NSS, LOW); //set NSS low + SPI.transfer(address | 0x80); //mask address for write + SPI.transfer(value); //write the byte + digitalWrite(NSS, HIGH); //set NSS high +} + + +uint32_t getFreqInt() +{ + //get the current set LoRa device frequency, return as long integer + + uint8_t Msb, Mid, Lsb; + uint32_t uinttemp; + float floattemp; + Msb = readRegister(REG_FRMSB); + Mid = readRegister(REG_FRMID); + Lsb = readRegister(REG_FRLSB); + floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb); + floattemp = ((floattemp * 61.03515625) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +void printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of SX127x registers to serial monitor + + uint16_t Loopv1, Loopv2, RegData; + + Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F")); + Serial.println(); + + for (Loopv1 = Start; Loopv1 <= End;) + { + Serial.print(F("0x")); + if (Loopv1 < 0x10) + { + Serial.print(F("0")); + } + Serial.print((Loopv1), HEX); + Serial.print(F(" ")); + for (Loopv2 = 0; Loopv2 <= 15; Loopv2++) + { + RegData = readRegister(Loopv1); + if (RegData < 0x10) + { + Serial.print(F("0")); + } + Serial.print(RegData, HEX); + Serial.print(F(" ")); + Loopv1++; + } + Serial.println(); + } +} + + +void setRfFrequency(uint64_t freq64, int32_t offset) +{ + freq64 = freq64 + offset; + freq64 = ((uint64_t)freq64 << 19) / 32000000; + writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16)); + writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8)); + writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0)); +} + + +void resetDevice(uint8_t device) +{ + if (device == DEVICE_SX1272) + { + digitalWrite(NRESET, HIGH); + delay(2); + digitalWrite(NRESET, LOW); + delay(20); + Serial.println(F("SX1272 Selected")); + } + else + { + digitalWrite(NRESET, LOW); + delay(2); + digitalWrite(NRESET, HIGH); + delay(20); + Serial.println(F("SX1276-79 Selected")); + } +} + + +bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device) +{ + pinMode(pinNSS, OUTPUT); + digitalWrite(pinNSS, HIGH); + pinMode(pinNRESET, OUTPUT); + digitalWrite(pinNRESET, LOW); + + if (pinDIO0 >= 0) + { + pinMode( pinDIO0, INPUT); + } + + if (pinDIO1 >= 0) + { + pinMode( pinDIO1, INPUT); + } + + if (pinDIO2 >= 0) + { + pinMode( pinDIO2, INPUT); + } + + resetDevice(device); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool checkDevice() +{ + //check there is a device out there, writes a register and reads back + + uint8_t Regdata1, Regdata2; + Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting + writeRegister(REG_FRMID, (Regdata1 + 1)); + Regdata2 = readRegister(REG_FRMID); //read changed value back + writeRegister(REG_FRMID, Regdata1); //restore register to original value + + if (Regdata2 == (Regdata1 + 1)) + { + return true; + } + else + { + return false; + } +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/3_LoRa_Transmitter_ESP32/3_LoRa_Transmitter_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/3_LoRa_Transmitter_ESP32/3_LoRa_Transmitter_ESP32.ino new file mode 100644 index 0000000..ff68d53 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/3_LoRa_Transmitter_ESP32/3_LoRa_Transmitter_ESP32.ino @@ -0,0 +1,193 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a simple LoRa test transmitter for an ESP32 device. A packet containing + ASCII text is sent according to the frequency and LoRa settings specified in the 'Settings.h' file. + The pins to access the SX127X need to be defined in the 'Settings.h' file also. + + The program also has the option of using a logic pin to control the power to the lora and SD card + devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are + powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1. + + The details of the packet sent and any errors are shown on the Serial Monitor, together with the transmit + power used, the packet length and the CRC of the packet. The matching receive program, '4_LoRa_Receive' + can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h) + must be the same for the Transmit and Receive program. Sample Serial Monitor output; + + 10dBm Packet> {packet contents*} BytesSent,23 CRC,DAAB TransmitTime,54mS PacketsSent,1 + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the SX127X device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint8_t TXPacketL; +uint32_t TXPacketCount, startmS, endmS; + +uint8_t buff[] = "Hello World 1234567890"; + +void loop() +{ + Serial.print(TXpower); //print the transmit power defined + Serial.print(F("dBm ")); + Serial.print(F("Packet> ")); + Serial.flush(); + + TXPacketL = sizeof(buff); //set TXPacketL to length of array + buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver + + LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII + + digitalWrite(LED1, HIGH); + startmS = millis(); //start transmit timer + if (LT.transmit(buff, TXPacketL, 5000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error + { + endmS = millis(); //packet sent, note end time + TXPacketCount++; + packet_is_OK(); + } + else + { + packet_is_Error(); //transmit packet returned 0, there was an error + } + + digitalWrite(LED1, LOW); + Serial.println(); + delay(packet_delay); //have a delay between packets +} + + +void packet_is_OK() +{ + //if here packet has been sent OK + uint16_t localCRC; + + Serial.print(F(" BytesSent,")); + Serial.print(TXPacketL); //print transmitted packet length + localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF); + Serial.print(F(" CRC,")); + Serial.print(localCRC, HEX); //print CRC of sent packet + Serial.print(F(" TransmitTime,")); + Serial.print(endmS - startmS); //print transmit time of packet + Serial.print(F("mS")); + Serial.print(F(" PacketsSent,")); + Serial.print(TXPacketCount); //print total of packets sent OK +} + + +void packet_is_Error() +{ + //if here there was an error transmitting packet + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + if (VCCPOWER >= 0) + { + pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices + digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on + } + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("3_LoRa_Transmitter_ESP32 Starting")); + + //SPI.begin(); //default setup can be used be used + SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS) + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //The function call list below shows the complete setup for the LoRa device using the information defined in the + //Settings.h file. + //The 'Setup LoRa device' list below can be replaced with a single function call; + //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done + //*************************************************************************************************** + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + Serial.println(); + LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/3_LoRa_Transmitter_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/3_LoRa_Transmitter_ESP32/Settings.h new file mode 100644 index 0000000..6e1a5d8 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/3_LoRa_Transmitter_ESP32/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change +//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the +//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and +//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1. + +#define NSS 5 //select pin on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 27 //reset pin on LoRa device +#define LED1 2 //on board LED, high for on +#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define VCCPOWER 14 //pin controls power to external devices + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/4_LoRa_Receiver_ESP32/4_LoRa_Receiver_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/4_LoRa_Receiver_ESP32/4_LoRa_Receiver_ESP32.ino new file mode 100644 index 0000000..0b07e41 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/4_LoRa_Receiver_ESP32/4_LoRa_Receiver_ESP32.ino @@ -0,0 +1,258 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 20/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - The program listens for incoming packets using the LoRa settings in the 'Settings.h' + file. The pins to access the SX127X need to be defined in the 'Settings.h' file also. + + The program also has the option of using a logic pin to control the power to the lora and SD card + devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are + powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1. + + There is a printout of the valid packets received, the packet is assumed to be in ASCII printable text, + if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor. + The LED will flash for each packet received and the buzzer will sound, if fitted. + + Sample serial monitor output; + + 1109s Hello World 1234567890*,CRC,DAAB,RSSI,-61dBm,SNR,9dB,Length,23,Packets,1026,Errors,0,IRQreg,50 + + If there is a packet error it might look like this, which is showing a CRC error, + + 1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the SX127X device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int8_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio of received packet + + +void loop() +{ + RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout + + digitalWrite(LED1, HIGH); //something has happened + + if (BUZZER > 0) //turn buzzer on + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + PacketSNR = LT.readPacketSNR(); //read the received SNR value + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + digitalWrite(LED1, LOW); //LED off + + Serial.println(); +} + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + RXpacketCount++; + + printElapsedTime(); //print elapsed time to Serial Monitor + Serial.print(F(" ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER + Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC + Serial.print(localCRC, HEX); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(RXPacketL); + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + printElapsedTime(); //print elapsed time to Serial Monitor + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F(" RXTimeout")); + } + else + { + errors++; + Serial.print(F(" PacketError")); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); //print the names of the IRQ registers set + } + + delay(250); //gives a longer buzzer and LED flash for error + +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F("s")); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + if (VCCPOWER >= 0) + { + pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices + digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on + } + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("4_LoRa_Receiver_ESP32 Starting")); + Serial.println(); + + if (BUZZER > 0) + { + pinMode(BUZZER, OUTPUT); + digitalWrite(BUZZER, HIGH); + delay(50); + digitalWrite(BUZZER, LOW); + } + + //SPI.begin(); //default setup can be used be used + SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS) + + //SPI beginTranscation is normally part of library routines, but if it is disabled in the library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //The function call list below shows the complete setup for the LoRa device using the information defined in the + //Settings.h file. + //The 'Setup LoRa device' list below can be replaced with a single function call; + //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done + //*************************************************************************************************** + + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check + Serial.println(); + Serial.println(); + LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/4_LoRa_Receiver_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/4_LoRa_Receiver_ESP32/Settings.h new file mode 100644 index 0000000..fc231e7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Basics/4_LoRa_Receiver_ESP32/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 15/01/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change +//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the +//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and +//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1. + +#define NSS 5 //select pin on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 27 //reset pin on LoRa device +#define RFBUSY 25 //busy line + +#define LED1 2 //on board LED, high for on +#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER -1 //pin for buzzer, set to -1 if not used +#define VCCPOWER 14 //pin controls power to external devices + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Diagnostic_and_Test/42_LoRa_Data_Throughput_Transmitter_Test_ESP32/42_LoRa_Data_Throughput_Transmitter_Test_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Diagnostic_and_Test/42_LoRa_Data_Throughput_Transmitter_Test_ESP32/42_LoRa_Data_Throughput_Transmitter_Test_ESP32.ino new file mode 100644 index 0000000..c2ca1cc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Diagnostic_and_Test/42_LoRa_Data_Throughput_Transmitter_Test_ESP32/42_LoRa_Data_Throughput_Transmitter_Test_ESP32.ino @@ -0,0 +1,277 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a program that can be used to test the throughput of a LoRa transmitter. + Whilst the various LoRa calculators tell you the on air data rate, in practice the achievable data + rate will be less than that due to the overhead of the software routines to load and send a packet + and internal delays in the LoRa device itself. + + A buffer is filled with characters and that buffer is then transmitted. The total time for a number of + transmissions is recorded and the bit rate calculated. The packet size (1 - 255 bytes) and the number of + packets to send in the test are specified in the 'Settings.h' file, see the 'Setup packet parameters Here !' + section. The setting file also has the lora settings to use. A lower spreading factors and higher + bandwidths will result in higher bitrates. + + There is the option of turning on an a requirement for an acknowledgement from a remote receiver, before + the transmitter sends the next packet, set this; 'const bool waitforACK = true;' definition in the + settings file. + + The results of the test are printed out thus; + + SX1278,434000000hz,SF7,BW500000,CR4:5,LDRO_Off,SyncWord_0x12,IQNormal,Preamble_8 + Total Transmit time 50 packets = 567mS + Average 10 byte packet transmit time = 11.34mS + Bits per packet sent = 80 + Data rate = 7055bps + + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t startmS, endmS, sendtimemS, bitspersecond, bitsPerpacket; +uint32_t TXPacketCount; +float averagePacketTime; +uint8_t packetNumber; +uint8_t RXPacketL; //length of received packet +uint8_t PacketType; //for packet addressing, identifies packet type received +uint32_t packetCheck; +bool loopFail = false; + + +void loop() +{ + uint16_t index, index2; + uint8_t TXBUFFER[TXPacketL + 1]; //create buffer for transmitted packet + loopFail = false; + + Serial.println(F("Start transmit test")); + + startmS = millis(); //start transmit timer + + for (index = 0; index < numberPackets; index++) + { + //fill the buffer + for (index2 = 0; index2 < TXPacketL; index2++) + { + TXBUFFER[index2] = index2; + } + + TXBUFFER[0] = TestPacket; //set first byte to identify this test packet + TXBUFFER[1] = index; //put the index as packet number in second byte of packet + Serial.print(index); //print number of packet sent + + if (waitforACK) + { + packetCheck = ( (uint32_t) TXBUFFER[4] << 24) + ( (uint32_t) TXBUFFER[3] << 16) + ( (uint32_t) TXBUFFER[2] << 8) + (uint32_t) TXBUFFER[1]; + Serial.print(F(",Checkvalue,")); + Serial.print(packetCheck, HEX); + Serial.print(F(",")); + } + + digitalWrite(LED1, HIGH); + + if (LT.transmit(TXBUFFER, TXPacketL, 2000, TXpower, WAIT_TX)) //will return 0 if transmit error + { + digitalWrite(LED1, LOW); + + if (waitforACK) + { + if (!waitAck(packetCheck)) + { + Serial.print(F("NoACKreceived,")); + loopFail = true; + break; + } + } + + } + else + { + packet_is_Error(); //transmit packet returned 0, there was an error + loopFail = true; + } + + Serial.println(); + + } + + if (!loopFail) + { + endmS = millis(); //all packets sent, note end time + digitalWrite(LED1, LOW); + Serial.println(); + LT.printModemSettings(); + sendtimemS = endmS - startmS; + Serial.println(); + Serial.print(F("Total transmit time ")); + Serial.print(numberPackets); + Serial.print(F(" packets = ")); + Serial.print(sendtimemS); + Serial.println(F("mS")); + + averagePacketTime = (float) (endmS - startmS) / numberPackets; + + if (waitforACK) + { + Serial.print(F("Average ")); + Serial.print(TXPacketL); + Serial.print(F(" byte packet transmit and acknowledge time = ")); + } + else + { + Serial.print(F("Average ")); + Serial.print(TXPacketL); + Serial.print(F(" byte packet transmit time = ")); + } + + Serial.print(averagePacketTime, 2); + Serial.println(F("mS")); + + bitsPerpacket = (uint32_t) (TXPacketL * 8); + Serial.print(F("Bits per packet sent = ")); + Serial.println(bitsPerpacket); + + Serial.print(F("Data rate = ")); + Serial.print((bitsPerpacket / (averagePacketTime / 1000)), 0); + Serial.print(F("bps")); + Serial.println(); + Serial.println(); + delay(10000); //have a delay between loops so we can see result + } + else + { + Serial.println(F("Transmit test failed, trying again")); + Serial.println(); + delay(1000); + } + +} + + +bool waitAck(uint32_t TXnum) +{ + uint32_t RXnum; + uint16_t IRQStatus; + + RXPacketL = LT.receiveSXBuffer(0, 1000, WAIT_RX); //returns 0 if packet error of some sort + + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F("RXTimeout,")); + return false; + } + else + { + Serial.print(F("ACKRX,")); + } + + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + RXnum = LT.readUint32(); + RXPacketL = LT.endReadSXBuffer(); + + if ( (PacketType != ACK) || (RXnum != TXnum)) + { + Serial.print(F("NotValidACK,")); + return false; + } + else + { + Serial.print(RXnum, HEX); + Serial.print(F(",OK")); + return true; + } + +} + + + +void packet_is_Error() +{ + //if here there was an error transmitting packet + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("42_LoRa_Data_Throughput_Transmitter_Test_ESP32 Starting")); + + SPI.begin(); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO1, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Diagnostic_and_Test/42_LoRa_Data_Throughput_Transmitter_Test_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Diagnostic_and_Test/42_LoRa_Data_Throughput_Transmitter_Test_ESP32/Settings.h new file mode 100644 index 0000000..e4b4ef9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Diagnostic_and_Test/42_LoRa_Data_Throughput_Transmitter_Test_ESP32/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the an ESP32 shield base. + +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NSS 5 //select pin on LoRa device +#define NRESET 27 //reset pin on LoRa device +#define RFBUSY 25 //busy line +#define DIO1 35 //DIO1 pin on LoRa device, used for RX and TX done + +#define LED1 2 //on board LED, high for on + + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 14; //LoRa transmit power in dBm + + +//******* Setup packet parameters Here ! *************** +const uint8_t numberPackets = 100; //number of packets to send in transmit loop +const uint8_t TXPacketL = 255; //length of packet to send +const bool waitforACK = false; //set to true to have transmit wait for ack before continuing + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg new file mode 100644 index 0000000..19b2873 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg new file mode 100644 index 0000000..ff18459 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Shield.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Shield.jpg new file mode 100644 index 0000000..1ad823b Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Pictures/ESP32_Shield.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/ReadMe.md b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/ReadMe.md new file mode 100644 index 0000000..f33e6f5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/ReadMe.md @@ -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. + +
+ +**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 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 + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/17_Sensor_Transmitter_ESP32/17_Sensor_Transmitter_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/17_Sensor_Transmitter_ESP32/17_Sensor_Transmitter_ESP32.ino new file mode 100644 index 0000000..8bc04a2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/17_Sensor_Transmitter_ESP32/17_Sensor_Transmitter_ESP32.ino @@ -0,0 +1,308 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - The program transmits a LoRa packet without using a processor buffer, the LoRa + devices internal buffer is filled directly with variables. + + The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There + is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end. + + Although the LoRa packet transmitted and received has its own internal CRC error checking, you could + still receive packets of the same length from another source. If this valid packet were to be used + to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet + is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet. + This CRC value is read by the receiver and used to check that the received CRC matches the supposed + sensor data in the packet. As an additional check there is some addressing information at the beginning + of the packet which is also checked for validity. Thus we can be relatively confident when reading the + received packet that its genuine and from this transmitter. The packet is built and sent in the + sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to + the packet. + + Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of + 8 seconds using the Atmel processor internal watchdog. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + The program also has the option of using a logic pin to control the power to the lora and SD card + devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are + powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1. + + There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on + and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON + in 'Settings.h' to the pin used. If not using the feature set the pin number to -1. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +SX127XLT LT; + +#include //get library here; https://github.com/Seeed-Studio/Grove_BME280 +BME280 bme280; //create an instance of the BME280 senosor +#include + +uint32_t TXpacketCount; +uint8_t TXPacketL; + +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t CRCvalue; //the CRC value of the packet data up to this point +uint8_t packetlength; //the packet length that was sent, checked against length received + + +#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds + +void loop() +{ + TXpacketCount++; + Serial.print(TXpacketCount); //print the numbers of sends + Serial.print(F(" Sending > ")); + + readSensors(); //read the sensor values + printSensorValues(); //print the sensor values + + if (sendSensorPacket()) + { + Serial.println(F("SentOK")); + } + else + { + Serial.print(F("Send Error - IRQreg,")); + Serial.println(LT.readIrqStatus(), HEX); + } + + Serial.print(F("Sleeping zzzz")); + Serial.flush(); //make sure all serial output has gone + + //now put the sensor, LoRa device and processor to sleep + sleepBME280(); //sleep the BME280 + + digitalWrite(VCCPOWER, HIGH); //VCCOUT off. lora device off + esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); + esp_deep_sleep_start(); + + //wait a bit ................ + Serial.println(F("Why are we here, ESP32 should re-start on wakeup ?")); //the processor has woken up ? + Serial.println(); + normalBME280(); //BME280 sensor to normal mode +} + + +uint8_t sendSensorPacket() +{ + //The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the + //receiver uses the same variable types and sequence to read variables out of the receive buffer. + uint8_t len; + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + + LT.writeUint8(Sensor1); //this byte defines the packet type + LT.writeUint8('B'); //this byte identifies the destination node of the packet + LT.writeUint8(1); //this byte identifies the source node of the packet + + /************************************************************************ + Highlighted section - this is where the actual sensor data is added to the packet + ************************************************************************/ + LT.writeFloat(temperature); //add the BME280 temperature + LT.writeFloat(pressure); //add the BME280 pressure + LT.writeUint16(humidity); //add the BME280 humididty + LT.writeUint16(voltage); //add the battery voltage + LT.writeUint8(statusbyte); //add the status byte + /************************************************************************/ + + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + addPacketErrorCheck(len); //add the additional CRC error checking to the packet end + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, (len + 2), 5000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void addPacketErrorCheck(uint8_t len) +{ + //calculate the CRC of packet sensor data + CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF); + + Serial.print(F("Calculated CRC value ")); + Serial.println(CRCvalue, HEX); + + LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data + LT.writeUint16(CRCvalue); //add the actual CRC value + LT.endWriteSXBuffer(); //close the packet +} + + +void readSensors() +{ + //read the sensor values into the global variables + temperature = bme280.getTemperature(); + pressure = bme280.getPressure(); + humidity = bme280.getHumidity(); + + if (BATVREADON >= 0) + { + voltage = readBatteryVoltage(); //read resistor divider across battery + } + else + { + voltage = 9999; //set a default value + } + statusbyte = 0x55; //manually set this for now, its a test +} + + +void printSensorValues() +{ + Serial.print(F("Temperature,")); + Serial.print(temperature, 1); + Serial.print(F("c,Pressure,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(" ")); + Serial.flush(); +} + + +void sleepBME280() +{ + //write this register value to BME280 to put it to sleep + writeBME280reg(BME280_REGISTER_CONTROL, B01111100); +} + + +void normalBME280() +{ + //write this register value to BME280 to put it to read mode + writeBME280reg(BME280_REGISTER_CONTROL, B01111111); +} + + +void writeBME280reg(byte reg, byte regvalue) +{ + //write a register value to the BME280 + Wire.beginTransmission((uint8_t) BME280_ADDRESS); + Wire.write((uint8_t)reg); + Wire.write((uint8_t)regvalue); + Wire.endTransmission(); +} + + +uint16_t readBatteryVoltage() +{ + uint16_t temp; + uint16_t volts = 0; + byte index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + temp = analogRead(BATTERYAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(BATTERYAD); + volts = volts + temp; + } + volts = ((volts / 5) * ADMultiplier); + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + return volts; +} + + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //for PCB LED + led_Flash(2, 125); + + if (VCCPOWER >= 0) + { + pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices + digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + Serial.begin(9600); + Serial.println(); + Serial.println(F("Reset")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("lora Device pins initialised")); + led_Flash(2, 125); + } + else + { + Serial.println(F("Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates LoRa device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + Serial.println(F("Setup lora device")); + + if (!bme280.init()) + { + Serial.println("BME280 Device error!"); + led_Flash(100, 15); //long very fast speed flash indicates BME280 device error + } + + Serial.println(F("Initialised BME280")); + + Serial.println(); + Serial.println(F("Transmitter ready")); + Serial.println(); + + readSensors(); //do an initial sensor read +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/17_Sensor_Transmitter_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/17_Sensor_Transmitter_ESP32/Settings.h new file mode 100644 index 0000000..96c3255 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/17_Sensor_Transmitter_ESP32/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change +//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the +//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and +//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1. + +#define NSS 5 //select pin on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 27 //reset pin on LoRa device +#define LED1 2 //on board LED, high for on +#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER -1 //pin for buzzer, set to -1 if not used +#define VCCPOWER 14 //pin controls power to external devices +#define BATTERYAD 36 //pin for reading supply voltage +#define BATVREADON 25 //when high turns on the resistor divider to measure voltage, -1 if not used +#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 14; //LoRa transmit power in dBm + +#define BME280_ADDRESS 0x76 //I2C bus address of BME280 +#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control + +const uint16_t TIME_TO_SLEEP = 16; //Time ESP32 will go to sleep (in seconds) diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/18_Sensor_Receiver_ESP32/18_Sensor_Receiver_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/18_Sensor_Receiver_ESP32/18_Sensor_Receiver_ESP32.ino new file mode 100644 index 0000000..037a40b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/18_Sensor_Receiver_ESP32/18_Sensor_Receiver_ESP32.ino @@ -0,0 +1,358 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/01/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - The program receives a LoRa packet without using a processor buffer, the LoRa devices + internal buffer is read direct for the received sensor data. + + The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity, + and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status + value at the end of the packet. + + When a packet is received its printed and assuming the packet is validated, the sensor results are printed + to the serial monitor and screen. + + For the sensor data to be accepted as valid the folowing need to match; + + The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet. + The packet must start with a byte that matches the packet type sent, 'Sensor1' + The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node' + + In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid + packet is acted on and erroneous values displayed. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +SX127XLT LT; + +#include //get library here > https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306 + +uint32_t RXpacketCount; //count of all packets received +uint32_t ValidPackets; //count of packets received with valid data +uint32_t RXpacketErrors; //count of all packets with errors received +bool packetisgood; + +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet + +uint8_t RXPacketType; +uint8_t RXDestination; +uint8_t RXSource; +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want + } + + digitalWrite(LED1, LOW); + Serial.println(); + //SPI.endTransaction(); +} + + +void packet_Received_OK() +{ + //a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from + //an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data + + uint8_t len; + uint8_t contenterrors; //keep a count of errors found in packet + + RXpacketCount++; + Serial.print(RXpacketCount); + Serial.print(F(",PacketsReceived,")); + + LT.startReadSXBuffer(0); + RXPacketType = LT.readUint8(); + RXDestination = LT.readUint8(); + RXSource = LT.readUint8(); + + /************************************************************************ + Highlighted section - this is where the actual sensor data is read from + the packet + ************************************************************************/ + temperature = LT.readFloat(); //the BME280 temperature value + pressure = LT.readFloat(); //the BME280 pressure value + humidity = LT.readUint16(); //the BME280 humididty value + voltage = LT.readUint16(); //the battery voltage value + statusbyte = LT.readUint8(); //a status byte, not currently used + /************************************************************************/ + + len = LT.endReadSXBuffer(); //note len is bytes read from packet, may be different to actual packet length + + printreceptionDetails(); //print details of reception, RSSI etc + Serial.println(); + + contenterrors = checkPacketValid(len); //pass length of packet to check routine + + if (contenterrors == 0) + { + Serial.println(F(" Packet is good")); + ValidPackets++; + printSensorValues(); //print the sensor values + Serial.println(); + printPacketCounts(); //print count of valid packets and errors + displayscreen1(); + Serial.println(); + } + else + { + Serial.println(F(" Packet is not valid")); + RXpacketErrors++; + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +uint8_t checkPacketValid(uint8_t len) +{ + //this function checks if the packet is valid and will be displayed + + uint8_t errors = 0; + + if (RXPacketType != Sensor1) //is it a Sensor1 type packet + { + errors++; + } + + if (RXDestination != This_Node) //was the packet sent to this receiver node ? + { + errors++; + } + + if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ? + { + errors++; + } + + Serial.println(); + Serial.print(F("Error Check Count = ")); + Serial.print(errors); + return errors; +} + + +bool checkCRCvalue(uint8_t len) +{ + uint16_t CRCSensorData; + //uint8_t msb, lsb; + + CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data + + Serial.print(F("(CRC of Received sensor data ")); + Serial.print(CRCSensorData, HEX); + Serial.print(F(")" )); + + //SPI.endTransaction(); + + TXCRCvalue = ((LT.getByteSXBuffer(17) << 8) + (LT.getByteSXBuffer(16))); + + Serial.print(F("(CRC transmitted ")); + Serial.print(TXCRCvalue, HEX); + Serial.print(F(")" )); + + if (TXCRCvalue != CRCSensorData) + { + Serial.print(F(" Sensor Data Not Valid")); + return false; + } + else + { + Serial.print(F(" Sensor Data is Valid")); + return true; + } + +} + + +void printSensorValues() +{ + Serial.print(F("Temperature,")); + Serial.print(temperature, 1); + Serial.print(F("c,Pressure,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(",CRC,")); + Serial.print(TXCRCvalue, HEX); + Serial.flush(); +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void printPacketCounts() +{ + Serial.print(F("ValidPackets,")); + Serial.print(ValidPackets); + Serial.print(F(",Errors,")); + Serial.print(RXpacketErrors); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXpacketErrors++; + IRQStatus = LT.readIrqStatus(); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + Serial.println(); + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +void displayscreen1() +{ + //show sensor data on display + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(F("Sensor ")); + disp.print(RXSource); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(temperature, 1); + disp.print(F("c")); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(pressure, 0); + disp.print(F("Pa")); + disp.clearLine(3); + disp.setCursor(0, 3); + disp.print(humidity); + disp.print(F("%")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(voltage); + disp.print(F("mV")); + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("ValidPkts ")); + disp.print(ValidPackets); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(VCCPOWER, OUTPUT); //this pin switches power for external devices, lora and SD card + digitalWrite(VCCPOWER, LOW); //turn power on + + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + Serial.begin(9600); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Check LoRa")); + disp.setCursor(0, 1); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + disp.print(F("LoRa OK")); + led_Flash(2, 125); + } + else + { + disp.print(F("Device error")); + Serial.println(F("Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/18_Sensor_Receiver_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/18_Sensor_Receiver_ESP32/Settings.h new file mode 100644 index 0000000..3707e40 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sensor/18_Sensor_Receiver_ESP32/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change +//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the +//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and +//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1. + +#define NSS 5 //select pin on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 27 //reset pin on LoRa device +#define LED1 2 //on board LED, high for on +#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER -1 //pin for buzzer, set to -1 if not used +#define VCCPOWER 14 //pin controls power to external devices +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//*************** Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 2; //LoRa TX power + +#define packet_delay 1000 //mS delay between packets +#define This_Node 'B' //this is the node that the remote sensors send data to + +//**************** Setup Display Parameters Here **************** + +//const uint8_t dispfont = u8x8_font_chroma48medium8_r; //display font from u8g2 library diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32.ino new file mode 100644 index 0000000..bc0de39 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32.ino @@ -0,0 +1,268 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program tests the sleep mode and register retention of the SX127X in sleep mode, + it assumes an ESP32 processor module. The LoRa settings to use are specified in the 'Settings.h' file. + To retain the program memory, so that the program restarts after sleep at the next instructions after + going into sleep mode the ESP32 light sleep function is used. + + A packet is sent, containing the text 'Before Device Sleep' and the LoRa device and ESP32 are put to sleep. + The ESP32 internal RTC timer should wakeup the processor in 15 seconds (approx) and lora register + values should be retained. The device then attempts to transmit another packet 'After Device Sleep' + without re-loading all the lora settings. The receiver should see 'After Device Sleep' for the first + packet and 'After Device Sleep' for the second. + + For unknown reasons the ESP32 pulses the pin used by NRESET when going into sleep modes, so the program + turns it into an input for the duration of the sleep to avoid resetting the lora device. + + The program also has the option of using a logic pin to control the power to the lora and SD card + devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are + powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1. + + Tested on a 'bare bones' ESP32 the current in light sleep mode was 1670uA. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +SX127XLT LT; + +boolean SendOK; +int8_t TestPower; +uint8_t TXPacketL; + +/*********************************************************** + //ESP32 specific settings +***********************************************************/ +#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds +#define TIME_TO_SLEEP 15 //Time ESP32 will go to sleep (in seconds) +RTC_DATA_ATTR int16_t bootCount = 0; +RTC_DATA_ATTR uint16_t sleepcount = 0; + + +void loop() +{ + Serial.print(F("Bootcount ")); + Serial.println(bootCount); + Serial.print(F("Sleepcount ")); + Serial.println(sleepcount); + + Serial.println(); + LT.printRegisters(0x00, 0x7F); + Serial.println(); + + digitalWrite(LED1, HIGH); + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket1> ")); + Serial.flush(); + + if (Send_Test_Packet1()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); + + pinMode(NRESET, INPUT); //change NRESET pin to INPUT mode + + + LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep. + + esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); + Serial.println(F("Start Sleep")); + Serial.flush(); + sleepcount++; + + esp_light_sleep_start(); + + Serial.println(); + Serial.println(); + Serial.println(F("Awake !")); + Serial.flush(); + digitalWrite(LED1, HIGH); + + LT.wake(); + + digitalWrite(NRESET, HIGH); //set NRESET high before turning it back to an output + pinMode(NRESET, INPUT); //set NRESET as an output + + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket2> ")); + Serial.flush(); + + if (Send_Test_Packet2()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); +} + + +void packet_is_OK() +{ + Serial.print(F(" ")); + Serial.print(TXPacketL); + Serial.print(F(" Bytes SentOK")); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error +} + + +bool Send_Test_Packet1() +{ + uint8_t bufffersize; + + uint8_t buff[] = "Before Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +bool Send_Test_Packet2() +{ + uint8_t bufffersize; + + uint8_t buff[] = "After Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + if (VCCPOWER >= 0) + { + pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices + digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on + } + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("5_LoRa_TX_Sleep_Timed_Wakeup_ESP32 Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.print(F("Transmitter ready - TXBUFFER_SIZE ")); + Serial.println(TXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32/Settings.h new file mode 100644 index 0000000..9214976 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_ESP32/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 5 //select pin on LoRa device +#define NRESET 27 //reset pin on LoRa device +#define LED1 2 //on board LED, high for on +#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define VCCPOWER 14 //pin controls power to external devices + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup lora Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define TXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/23_Simple_GPS_Tracker_Transmitter_ESP32/23_Simple_GPS_Tracker_Transmitter_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/23_Simple_GPS_Tracker_Transmitter_ESP32/23_Simple_GPS_Tracker_Transmitter_ESP32.ino new file mode 100644 index 0000000..b9de953 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/23_Simple_GPS_Tracker_Transmitter_ESP32/23_Simple_GPS_Tracker_Transmitter_ESP32.ino @@ -0,0 +1,408 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program is an example of a basic GPS tracker. The program reads the GPS, + waits for an updated fix and transmits location and altitude, number of satellites in view, the HDOP + value, the fix time of the GPS and the battery voltage. This transmitter can be also be used to + investigate GPS performance. At startup there should be a couple of seconds of recognisable text from + the GPS printed to the serial monitor. If you see garbage or funny characters its likley the GPS baud + rate is wrong. If the transmitter is turned on from cold, the receiver will pick up the cold fix time, + which is an indication of GPS performance. The GPS will be powered on for around 4 seconds before the + timing of the fix starts. Outside with a good view of the sky most GPSs should produce a fix in around + 45 seconds. The number of satellites and HDOP are good indications to how well a GPS is working. + + The program writes direct to the LoRa devices internal buffer, no memory buffer is used. + + The LoRa settings are configured in the Settings.h file. + + The program has the option of using a pin to control the power to the GPS (GPSPOWER), if the GPS module + or board being used has this feature. To not use this feature set the define for GPSPOWER in the + Settings.h file to '#define GPSPOWER -1'. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic + levels. + + The program also has the option of using a logic pin to control the power to the lora and SD card + devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are + powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1. + + There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on + and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON + in 'Settings.h' to the pin used. If not using the feature set the pin number to -1. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" +#define authorname "Stuart Robinson" + +#include +#include + +#include "Settings.h" +#include + +SX127XLT LT; + +#include //get library here > http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + + +uint8_t TXStatus = 0; //used to store current status flag bits of Tracker transmitter (TX) +uint8_t TXPacketL; //length of LoRa packet (TX) +float TXLat; //Latitude from GPS on Tracker transmitter (TX) +float TXLon; //Longitude from GPS on Tracker transmitter (TX) +float TXAlt; //Altitude from GPS on Tracker transmitter (TX) +uint8_t TXSats; //number of GPS satellites seen (TX) +uint32_t TXHdop; //HDOP from GPS on Tracker transmitter (TX) +uint16_t TXVolts; //Volts (battery) level on Tracker transmitter (TX) +uint32_t TXGPSFixTime; //GPS fix time in hot fix mode of GPS on Tracker transmitter (TX) +uint32_t TXPacketCount, TXErrorsCount; //keep count of OK packets and send errors + + +void loop() +{ + + if (gpsWaitFix(WaitGPSFixSeconds)) + { + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); + Serial.println(); + Serial.print(F("Waiting ")); + Serial.print(Sleepsecs); + Serial.println(F("s")); + delay(Sleepsecs * 1000); //this sleep is used to set overall transmission cycle time + } + else + { + send_Command(NoFix); //send notification of no GPS fix. + } +} + + +bool gpsWaitFix(uint16_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + uint32_t endwaitmS, GPSonTime; + bool GPSfix; + float tempfloat; + uint8_t GPSchar; + + GPSonTime = millis(); + GPSserial.begin(9600); //start GPSserial + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.println(F("s")); + + endwaitmS = millis() + (waitSecs * 1000); + + while (millis() < endwaitmS) + { + if (GPSserial.available() > 0) + { + GPSchar = GPSserial.read(); + gps.encode(GPSchar); + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + GPSfix = true; + Serial.print(F("Have GPS Fix ")); + TXGPSFixTime = millis() - GPSonTime; + Serial.print(TXGPSFixTime); + Serial.println(F("mS")); + + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = gps.altitude.meters(); + TXSats = gps.satellites.value(); + TXHdop = gps.hdop.value(); + tempfloat = ( (float) TXHdop / 100); + + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempfloat, 2); + Serial.println(); + + break; //exit while loop reading GPS + } + } + + //if here then there has either been a fix or no fix and a timeout + + if (GPSfix) + { + setStatusByte(GPSFix, 1); //set status bit to flag a GPS fix + } + else + { + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(); + Serial.println(F("Timeout - No GPSFix")); + Serial.println(); + GPSfix = false; + } + + GPSserial.end(); //serial RX interrupts interfere with SPI, so stop GPSserial + return GPSfix; +} + + +void sendLocation(float Lat, float Lon, float Alt, uint32_t Hdop, uint32_t fixtime) +{ + uint8_t len; + uint16_t IRQStatus; + + Serial.print(F("Send Location")); + + TXVolts = readSupplyVoltage(); //get the latest supply\battery volts + + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationPacket); //indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeFloat(Alt); //add altitude + LT.writeUint8(TXSats); //add number of satellites + LT.writeUint32(Hdop); //add hdop + LT.writeUint8(TXStatus); //add tracker status + LT.writeUint32(fixtime); //add GPS fix time in mS + LT.writeUint16(TXVolts); //add tracker supply volts + len = LT.endWriteSXBuffer(); //close buffer write + + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); + + if (TXPacketL) + { + TXPacketCount++; + Serial.println(F(" - Done ")); + Serial.print(F("SentOK,")); + Serial.print(TXPacketCount); + Serial.print(F(",Errors,")); + Serial.println(TXErrorsCount); + } + else + { + //if here there was an error transmitting packet + TXErrorsCount++; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + Serial.println(); + } +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void send_Command(char cmd) +{ + bool SendOK; + uint8_t len; + + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + + LT.startWriteSXBuffer(0); + LT.writeUint8(cmd); //packet addressing used indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent to + LT.writeUint8(ThisNode); //where is packet from + LT.writeUint16(TXVolts); + len = LT.endWriteSXBuffer(); + + digitalWrite(LED1, HIGH); + SendOK = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); //timeout set at 10 seconds + digitalWrite(LED1, LOW); + + if (SendOK) + { + Serial.println(F(" - Done")); + } + else + { + Serial.println(F(" - Error")); + } +} + + +uint16_t readSupplyVoltage() +{ + //ESP32 uses the 3.3V VCC as reference + + uint16_t temp; + uint16_t volts = 0; + byte index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + temp = analogRead(SupplyAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(SupplyAD); + volts = volts + temp; + } + volts = ((volts / 5) * ADMultiplier); + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + return volts; +} + + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void setup() +{ + uint32_t endmS; + + if (VCCPOWER >= 0) + { + pinMode(VCCPOWER, OUTPUT); //this pin switches power for external devices, lora and SD card + digitalWrite(VCCPOWER, LOW); //turn device power on + } + + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + GPSON(); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("23_Simple_GPS_Tracker_Transmitter_ESP32 Starting")); + + //SPI.begin(); + SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS) + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + + TXVolts = readSupplyVoltage(); + + Serial.print(F("Supply ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + + send_Command(PowerUp); //send power up command, includes supply mV + + Serial.println(F("Startup GPS check")); + + GPSserial.begin(9600); + + endmS = millis() + echomS; + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + + Serial.println(F("Wait for first GPS fix")); + gpsWaitFix(WaitFirstGPSFixSeconds); + + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); +} diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/23_Simple_GPS_Tracker_Transmitter_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/23_Simple_GPS_Tracker_Transmitter_ESP32/Settings.h new file mode 100644 index 0000000..06a6b63 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/23_Simple_GPS_Tracker_Transmitter_ESP32/Settings.h @@ -0,0 +1,71 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change +//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the +//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and +//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1. + + +#define NSS 5 //select on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 27 //reset on LoRa device +#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 2 //On board LED, high for on +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used +#define VCCPOWER 14 //controls power to lora and SD card, set to -1 if not used +#define SupplyAD 36 //pin for reading supply\battery voltage +#define BATVREADON 25 //turns on battery resistor divider, high for on +#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV + +#define RXpin 17 //pin number for GPS RX input into Arduino - TX from GPS +#define TXpin 16 //pin number for GPS TX output from Arduino- RX into GPS + +#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used +#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER +#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER +#define GPSserial Serial2 //define GPSserial as ESP32 Serial2 + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + +#define ThisNode 'T' //a character that identifies this tracker + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define GPSBaud 9600 //GPS Baud rate + +#define WaitGPSFixSeconds 30 //time in seconds to wait for a new GPS fix +#define WaitFirstGPSFixSeconds 1800 //time to seconds to wait for the first GPS fix at startup +#define Sleepsecs 5 //seconds between transmissions, this delay is used to set overall transmission cycle time + +#define echomS 2000 //number of mS to run GPS echo at startup + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32.ino new file mode 100644 index 0000000..853a504 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32.ino @@ -0,0 +1,624 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20 + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* +Program Operation - TThis program is an example of a functional GPS tracker receiver using lora. +It is capable of picking up the trackers location packets from many kilometres away with only basic antennas. + +The program receives the location packets from the remote tracker transmitter and writes them on an OLED +display and also prints the information to the Arduino IDE serial monitor. The program can read a locally +attached GPS and when that has a fix, will display the distance and direction to the remote tracker. + +The program writes direct to the lora devices internal buffer, no memory buffer is used. The lora settings +are configured in the Settings.h file. + +The receiver recognises two types of tracker packet, the one from the matching program '23_GPS_Tracker_Transmitter' +(LocationPacket, 27 bytes) which causes these fields to be printed to the serial monitor; + +Latitude, Longitude, Altitude, Satellites, HDOP, TrackerStatusByte, GPS Fixtime, Battery mV, Distance, Direction, +Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, PacketLength, IRQRegister. + +This is a long packet which at the long range LoRa settings takes just over 3 seconds to transmit. + +The receiver also recognises a much shorter location only packet (LocationBinaryPacket, 11 bytes) and when +received this is printed to the serial monitor; + +Latitude, Longitude, Altitude, TrackerStatusByte, Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, +PacketLength, IRQRegister. + +Most of the tracker information (for both types of packet) is shown on the OLED display. If there has been a +tracker transmitter GPS fix the number\identifier of that tracker is shown on row 0 right of screen and if there +is a recent local (receiver) GPS fix an 'R' is displayed row 1 right of screen. + +When the tracker transmitter starts up or is reset its sends a power up message containing the battery voltage +which is shown on the OLED and printer to the serial monitor. + +The program has the option of using a pin to control the power to the GPS, if the GPS module being used has this +feature. To use the option change the define in Settings.h; + +'#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE defines to +the appropriate logic levels. + +The program by default uses software serial to read the GPS, you can use hardware serial by commenting out this +line in the Settings.h file; + +#define USE_SOFTSERIAL_GPS + +And then defining the hardware serial port you are using, which defaults to Serial1. + +Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + + +#define Program_Version "V1.1" + +#include +#include +SX127XLT LT; + +#include "Settings.h" +#include + +#include //https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 + + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USE_SOFTSERIAL_GPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#else +#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file +#endif + +uint32_t RXpacketCount; //count of received packets +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet +int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //status byte from tracker transmitter +uint8_t TXSats; //number of sattelites in use +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +float RXLat; //latitude +float RXLon; //longitude +float RXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint16_t RXVolts; //supply\battery voltage +float TXdistance; //calculated distance to tracker +uint16_t TXdirection; //calculated direction to tracker +uint16_t RXerrors; +uint32_t TXupTimemS; //up time of TX in mS + +uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix + +bool TXLocation = false; //set to true when at least one tracker location packet has been received +bool RXGPSfix = false; //set to true if the local GPS has a recent fix + +uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); //returns 0 if packet error of some sort + + while (!digitalRead(DIO0)) + { + readGPS(); //If the DIO pin is low, no packet arrived, so read the GPS + } + + //something has happened in receiver + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readRXPacketL(); + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + Serial.println(); +} + + +void readGPS() +{ + if (GPSserial.available() > 0) + { + gps.encode(GPSserial.read()); + } + + + if ( millis() > (LastRXGPSfixCheck + NoRXGPSfixms)) + { + RXGPSfix = false; + LastRXGPSfixCheck = millis(); + dispscreen1(); + } + + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + RXGPSfix = true; + RXLat = gps.location.lat(); + RXLon = gps.location.lng(); + RXAlt = gps.altitude.meters(); + printRXLocation(); + LastRXGPSfixCheck = millis(); + + if ( FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1 + { + FixCount = DisplayRate; + dispscreen1(); + } + FixCount--; + } +} + + +bool readTXStatus(byte bitnum) +{ + return bitRead(TXStatus, bitnum); +} + + +void printRXLocation() +{ + Serial.print(F("LocalGPS ")); + Serial.print(RXLat, 5); + Serial.print(F(",")); + Serial.print(RXLon, 5); + Serial.print(F(",")); + Serial.print(RXAlt, 1); + Serial.println(); +} + + +void readPacketAddressing() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + //uint16_t IRQStatus; + float tempfloat; + + RXpacketCount++; + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + TXVolts = LT.readUint16(); //read tracker transmitter voltage + LT.endReadSXBuffer(); + Serial.print(F("Tracker Powerup - Battery ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + dispscreen2(); + } + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + TXLocation = true; + LT.startReadSXBuffer(0); //start the read of received packet + PacketType = LT.readUint8(); //read in the PacketType + Destination = LT.readUint8(); //read in the Packet destination address + Source = LT.readUint8(); //read in the Packet source address + TXLat = LT.readFloat(); //read in the tracker latitude + TXLon = LT.readFloat(); //read in the tracker longitude + TXAlt = LT.readFloat(); //read in the tracker altitude + TXSats = LT.readUint8(); //read in the satellites in use by tracker GPS + TXHdop = LT.readUint32(); //read in the HDOP of tracker GPS + TXStatus = LT.readUint8(); //read in the tracker status byte + TXGPSFixTime = LT.readUint32(); //read in the last fix time of tracker GPS + TXVolts = LT.readUint16(); //read in the tracker supply\battery volts + TXupTimemS = LT.readUint32(); //read in the TX uptime in mS + RXPacketL = LT.endReadSXBuffer(); //end the read of received packet + + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + + tempfloat = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + Serial.print(tempfloat, 2); + + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS/1000)); + Serial.print(F("s,")); + + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); //and show the packet detail it on screen + return; + } + + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + TXLocation = true; + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); + return; + } +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + RXerrors++; + Serial.print(F("PacketError,RSSI")); + + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void dispscreen1() +{ + //show received packet data on display + float tempfloat; + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(TXLat, 5); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(TXLon, 5); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(TXAlt,0); + disp.print(F("m")); + disp.clearLine(3); + disp.setCursor(0, 3); + + disp.print(F("RSSI ")); + disp.print(PacketRSSI); + disp.print(F("dBm")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(F("SNR ")); + + if (PacketSNR > 0) + { + disp.print(F("+")); + } + + if (PacketSNR == 0) + { + disp.print(F(" ")); + } + + if (PacketSNR < 0) + { + disp.print(F("-")); + } + + disp.print(PacketSNR); + disp.print(F("dB")); + + if (PacketType == LocationPacket) + { + disp.clearLine(5); + disp.setCursor(0, 5); + tempfloat = ((float) TXVolts / 1000); + disp.print(F("Batt ")); + disp.print(tempfloat, 2); + disp.print(F("v")); + } + + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); + + disp.clearLine(7); + + if (RXGPSfix) + { + disp.setCursor(15, 1); + disp.print(F("R")); + } + else + { + disp.setCursor(15, 1); + disp.print(F(" ")); + disp.setCursor(0, 7); + disp.print(F("No Local Fix")); + } + + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(TXdistance, 0); + disp.print(F("m ")); + disp.print(TXdirection); + disp.print(F("d")); + } + + if (readTXStatus(GPSFix)) + { + disp.setCursor(15, 0); + disp.write(Source); + } + +} + + +void dispscreen2() +{ + //show tracker powerup data on display + float tempfloat; + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Tracker Powerup")); + disp.setCursor(0, 1); + disp.print(F("Battery ")); + tempfloat = ((float) TXVolts / 1000); + disp.print(tempfloat, 2); + disp.print(F("v")); +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void setup() +{ + uint32_t endmS; + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32 Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + } + + SPI.begin(); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + Serial.print(F("Checking LoRa device - ")); //Initialize LoRa + disp.setCursor(0, 0); + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("Receiver ready")); + disp.print(F("Receiver ready")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No LoRa device responding")); + disp.print(F("No LoRa device")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + Serial.println(F("Startup GPS check")); + + endmS = millis() + echomS; + + //now startup GPS + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + } + + GPSON(); + GPSserial.begin(GPSBaud); + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32/Settings.h new file mode 100644 index 0000000..0d7598d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32/Settings.h @@ -0,0 +1,60 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be +//connected and should be set to -1. + +#define NSS 5 //select on LoRa device +#define NRESET 27 //reset on LoRa device +#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done +#define LED1 82 //On board LED, high for on +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used + +#define RXpin 16 //pin number for GPS RX input into Arduino - TX from GPS +#define TXpin 17 //pin number for GPS TX output from Arduino- RX into GPS + +#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used +#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER +#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +//#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +#define HardwareSerialPort Serial2 //if using hardware serial enable this define for hardware serial port + +#define GPSBaud 9600 //GPS Baud rate +#define WaitGPSFixSeconds 30 //time to wait for a new GPS fix +#define echomS 2000 //number of mS to run GPS echo for at startup + +#define NoRXGPSfixms 15000 //max number of mS to allow before no local fix flagged +#define DisplayRate 7 //when working OK the GPS will get a new fix every second or so + //this rate defines how often the display should be updated + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/71_FSKRTTY_Transmitter_Test_ESP32/71_FSKRTTY_Transmitter_Test_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/71_FSKRTTY_Transmitter_Test_ESP32/71_FSKRTTY_Transmitter_Test_ESP32.ino new file mode 100644 index 0000000..4a07ea3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/71_FSKRTTY_Transmitter_Test_ESP32/71_FSKRTTY_Transmitter_Test_ESP32.ino @@ -0,0 +1,192 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a test program for using the LoRa device to transmit upper side band FSK + RTTY. With the LoRa device in FSK direct mode, the frequency of the generated carrier is shifted up + or down at the correct baud rate depending on whether a logic 0 or 1 is being sent. + + The desired shift in frequency is defined in the Settings.h file as 'FrequencyShift'. When the program + starts the actual frequency shift will be calculated according to the discrete frequency steps the + LoRa device can be set to. There are settings for number of data bits, number of start bits and the + value of parity which can be ParityNone, ParityOdd, ParityEven, ParityZero or ParityOne. + + Before the actual data transmission starts you can send a series of marker pips which are short bursts + of up shifted carrier which will be heard as beeps in a correctly tuned receiver. These pips can aid + in setting the receiver decode frequemcy to match the transmission. on some LoRa devices, such as the SX127x + series there can be considerable temperature induced frequency drift. This drift can be caused by outside + temperature changes or the RF device self heating when transmit is turned on. The duration of the pips, + the gaps between them and the period of leadin carrier before the data starts can all be set. To send no + pips just set the number to 0. + + The FSK RTTY routines use the micros() function for timing, and a check is made at the begging of a + character to send to see if micros() migh overflow during the transmission of the character. This check + assumes the lowest baud rate of 45baud, and if an overflow is likley, there will be a short in transmission + pause to allow the overflow to occur. + + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based +#include //include the appropriate SX12XX library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +//Choose whichever test pattern takes your fancy +//uint8_t testBuffer[] = "0123456789* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"; //This string is sent as AFSK RTTY, 7 bit, 2 Stop bit, no parity, 300 baud. +//uint8_t testBuffer[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789"; +//uint8_t testBuffer[] = "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"; +uint8_t testBuffer[] = "$$MyFlight1,2213,14:54:37,51.48230,-3.18136,15,6,3680,23,66,3,0*2935"; + +uint8_t freqShiftRegs[3]; //to hold returned registers that set frequency + + +void loop() +{ + uint8_t index; + + printRegisterSetup(FrequencyShift); + Serial.println(); + + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + if (micros() > 0xF8000000) + { + Serial.print(F("Waiting micros()")); + while(micros() < 0xFFFB6000); + } + + Serial.print(F("Start RTTY micros() = ")); + Serial.println(micros(),HEX); + + LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed + for (index = 0; index < (sizeof(testBuffer)-1); index++) + { + LT.transmitFSKRTTY(testBuffer[index], DataBits, StopBits, Parity, BaudPerioduS, LED1); + Serial.write(testBuffer[index]); + } + LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed + + Serial.println(); + Serial.print(F("END RTTY micros() = ")); + Serial.println(micros(),HEX); + digitalWrite(LED1, LOW); + Serial.println(); + Serial.println(); + + + Serial.println(micros(),HEX); + + LT.setMode(MODE_STDBY_RC); + + delay(2000); +} + + +void printRegisterSetup(uint32_t shift) +{ + + uint32_t nonShiftedFreq, ShiftedFreq; + uint32_t freqShift; + float exactfreqShift; + + LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set + LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values + nonShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2]; + Serial.print(F("NoShift Registers 0x")); + Serial.println(nonShiftedFreq, HEX); + + LT.setRfFrequency((Frequency + shift), Offset); //set shifted frequecy + LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values + ShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2]; + Serial.print(F("Shifted Registers 0x")); + Serial.println(ShiftedFreq, HEX); + + freqShift = ShiftedFreq - nonShiftedFreq; + exactfreqShift = freqShift * FREQ_STEP; + Serial.print(F("FSKRTTY register shift ")); + Serial.println(freqShift,HEX); + Serial.print(F("FSKRTTY frequency shift ")); + Serial.print(exactfreqShift, 8); + Serial.println(F("hZ")); + + LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set +} + + +void printRegisterBuffer() +{ +Serial.print(freqShiftRegs[0],HEX); +Serial.print(F(" ")); +Serial.print(freqShiftRegs[1],HEX); +Serial.print(F(" ")); +Serial.print(freqShiftRegs[2],HEX); +Serial.println(); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("71_FSKRTTY_Transmitter_Test_ESP32 Starting")); + + SPI.begin(); + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.setupDirect(Frequency, Offset); + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/71_FSKRTTY_Transmitter_Test_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/71_FSKRTTY_Transmitter_Test_ESP32/Settings.h new file mode 100644 index 0000000..afe569e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/71_FSKRTTY_Transmitter_Test_ESP32/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions needed. You will also need to connect up the pins for the SPI bus, which +//are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. + +#define NSS 5 //select pin on LoRa device +#define NRESET 27 //reset pin on LoRa device +#define LED1 2 //on board LED, high for on +#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + +//******* Setup Direct Modem Parameters Here ! *************** + +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes +const uint16_t deviation = 10000; //deviation, total frequency shift low to high +const float adjustfreq = 0.9; //adjustment to tone frequency + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + +//******* Setup FSKRTTY Settings here ! *************** + +uint32_t FrequencyShift = 400; //hertz frequency shift, approx, in 61.03515625hz steps +uint8_t NumberofPips = 2; //number of marker pips to send +uint16_t PipDelaymS = 500; //mS between pips, carrier off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 1000; //ms of leadin, shifted carrier +uint8_t DataBits = 7; //number of databits, normally 7 or 8 +uint8_t StopBits = 2; //number of stopbits, normally 1 or 2 +uint8_t Parity = ParityNone; //parity on data bits, ParityNone, ParityOdd, ParityEven, ParityZero, ParityOne + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/75_Balloon_Tracker_Transmitter_SDLogger_ESP32/75_Balloon_Tracker_Transmitter_SDLogger_ESP32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/75_Balloon_Tracker_Transmitter_SDLogger_ESP32/75_Balloon_Tracker_Transmitter_SDLogger_ESP32.ino new file mode 100644 index 0000000..998c44e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/75_Balloon_Tracker_Transmitter_SDLogger_ESP32/75_Balloon_Tracker_Transmitter_SDLogger_ESP32.ino @@ -0,0 +1,898 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 08/06/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a tracker intended for use as a high altitude balloon (HAB) tracker. The + program sends out a standard format payload with LoRa that is compatible with the HABHUB online tracking + system. + + The HAB payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,Status,Errors,TXGPSfixms,Checksum + Field 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + + The LoRa and frequency settings can be changed in the Settings.h file. There is the option of sending + out a much shorter Search mode binary location only payload. This is intended for ground based searching + and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker + mode used by the HAB payload. There is also the option of sending the HAB payload in FSK RTTY format, + see the Settings.h file for all the options. FSK RTTY gets sent at the same frequency as the Tracker mode + HAB packet. + + There is a matching Balloon Tracker Receiver program which writes received data to the Serial monitor as well + as a small OLED display. + + In the Settings.h file you can set the configuration for either a Ublox GPS or a Quectel L70\L80. The GPSs + are configured for high altitude balloon mode. + + It is strongly recommended that a FRAM option is fitted for this transmitter. The sequence, resets and error + nembers are stred in non-volatile memory. This defaults to EEPROM which has a limited endurance of only + 100,000 writes, so in theory the limt is reached after the transmission of 100,000 hab packets. The use of + a FRAM will extend the life of the tracker to circa 100,000,000,000,000 transmissions. + + Changes: + 240420 - Change to work with Easy Pro Mini style modules + 300420 - Improve error detection for UBLOX GPS library + + ToDo: + + Serial monitor baud rate is set at 115200 +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include +#include //include the appropriate library + +SX127XLT LT; //create a library class instance called LT + +#include "Settings.h" +#include "ProgramLT_Definitions.h" + +//************************************************************************************************** +// HAB tracker data - these are the variables transmitted in payload +//************************************************************************************************** +uint32_t TXSequence; //sequence number of payload +uint8_t TXHours; //Hours +uint8_t TXMinutes; //Minutes +uint8_t TXSeconds; //Seconds +float TXLat; //latitude from GPS +float TXLon; //longitude from GPS +uint16_t TXAlt; //altitude from GPS +uint8_t TXSatellites; //satellites used by GPS +uint16_t TXVolts; //measured tracker supply volts +int8_t TXTemperature; //measured temperature +uint16_t TXResets; //number of tracker resets +uint8_t TXStatus = 0; //used to store current status flag bits +uint16_t TXErrors; //number of tracker Errors +uint32_t TXGPSfixms; //fix time of GPS +uint32_t TXGPSHdop; //HDOP value of GPS +uint8_t hours, mins, secs, day, month; +uint16_t year; +//************************************************************************************************** + +uint8_t TXPacketL; //length of LoRa packet sent +uint8_t TXBUFFER[TXBUFFER_SIZE]; //buffer for packet to send + +#include Memory_Library + +#include +#include +File logFile; +char filename[] = "/LOG0000.txt"; //filename used as base for creating logfile, 0000 replaced with numbers +bool SDfound; + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object +#define GPSserial HARDWARESERIALPORT + +#include GPS_Library //include previously defined GPS Library + +#include //get library here > https://github.com/PaulStoffregen/OneWire +OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library +#include //get library here > https://github.com/milesburton/Arduino-TXTemperature-Control-Library +DallasTemperature sensor(&oneWire); //create instance of dallas library + +uint32_t GPSstartms; //start time waiting for GPS to get a fix + + +void loop() +{ + Serial.println(F("Start Loop")); + + GPSstartms = millis(); + + if (!gpsWaitFix(WaitGPSFixSeconds)) + { + GPS_OutputOff(); + sendCommand(NoFix); //report a GPS fix error + delay(1000); //give receiver enough time to report NoFix + } + Serial.println(); + + if (SDfound) + { + Serial.print(F("Write data to ")); + Serial.print(filename); + + if (logGPSfix(filename)) //log fix data to SD card + { + setStatusByte(SDError, 0); //write to SD OK, clear error flag + } + else + { + cardFail(2); + setStatusByte(SDError, 1); //flag SD card error + } + + Serial.println(); + } + + do_Transmissions(); //do the transmissions + + Serial.println(F("Sleep")); + LT.setSleep(CONFIGURATION_RETENTION); //put LoRa device to sleep, preserve lora register settings + Serial.flush(); //make sure no serial output pending before goint to sleep + + delay(SleepTimesecs * 1000); + + Serial.println(F("Wake")); + LT.wake(); //wake the LoRa device from sleep +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + uint32_t startTimemS; + uint8_t index; + + incMemoryUint32(addr_SequenceNum); //increment Sequence number + + if (readConfigByte(SearchEnable)) + { + setSearchMode(); + TXPacketL = buildLocationOnly(TXLat, TXLon, TXAlt, TXStatus); //put location data in SX12xx buffer + Serial.print(F("Search packet > ")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F(",")); + Serial.print(TXStatus); + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmitSXBuffer(0, TXPacketL, 10000, SearchTXpower, WAIT_TX); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + } + + delay(1000); //gap between transmissions + + setTrackerMode(); + + TXPacketL = buildHABPacket(); + Serial.print(F("HAB Packet > ")); + printBuffer(TXBUFFER, (TXPacketL + 1)); //print the buffer (the packet to send) as ASCII + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmit(TXBUFFER, (TXPacketL + 1), 10000, TrackerTXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error + digitalWrite(LED1, LOW); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + + delay(1000); //gap between transmissions + + if (readConfigByte(FSKRTTYEnable)) + { + LT.setupDirect(TrackerFrequency, Offset); + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + startTimemS = millis() - LeadinmS; + + Serial.print(F("FSK RTTY > $$")); + Serial.flush(); + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + + for (index = 0; index <= (TXPacketL - 1); index++) //its TXPacketL-1 since we dont want to send the null at the end + { + LT.transmitFSKRTTY(TXBUFFER[index], BaudPerioduS, LED1); + Serial.write(TXBUFFER[index]); + } + + LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed + LT.endFSKRTTY(); //stop transmitting carrier + digitalWrite(LED1, LOW); //LED off + printTXtime(startTimemS, millis()); + TXPacketL += 4; //add the two $ at beginning and CR/LF at end + reportCompletion(); + Serial.println(); + } +} + + +void printTXtime(uint32_t startmS, uint32_t endmS) +{ + Serial.print(F(" ")); + Serial.print(endmS - startmS); + Serial.print(F("mS")); +} + + +void reportCompletion() +{ + Serial.print(F(" ")); + if (TXPacketL == 0) + { + Serial.println(); + reporttransmitError(); + } + else + { + Serial.print(TXPacketL); + Serial.print(F("bytes")); + setStatusByte(LORAError, 0); + } +} + + +void printBuffer(uint8_t *buffer, uint8_t size) +{ + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } +} + + +uint8_t buildHABPacket() +{ + //build the HAB tracker payload + uint16_t index, j, CRC; + uint8_t Count, len; + char LatArray[12], LonArray[12]; + + TXSequence = readMemoryUint32(addr_SequenceNum); //Sequence number is kept in non-volatile memory so it survives TXResets + TXResets = readMemoryUint16(addr_ResetCount); //reset count is kept in non-volatile memory so it survives TXResets + TXVolts = readSupplyVoltage(); + TXTemperature = (int8_t) readTempDS18B20(); + TXErrors = readMemoryUint16(addr_TXErrors); + + dtostrf(TXLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TXLon, 7, 5, LonArray); //converts float to character array + + len = sizeof(TXBUFFER); + memset(TXBUFFER, 0, len); //clear array to 0s + Count = snprintf((char*) TXBUFFER, + TXBUFFER_SIZE, + "$$%s,%u,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%u,%u,%u,%u", + FlightID, + TXSequence, + TXHours, + TXMinutes, + TXSeconds, + LatArray, + LonArray, + TXAlt, + TXSatellites, + TXVolts, + TXTemperature, + TXResets, + TXStatus, + TXErrors, + TXGPSfixms + ); + + CRC = 0xffff; //start value for CRC16 + + for (index = 2; index < Count; index++) //element 2 is first character after $$ at start (for LoRa) + { + CRC ^= (((uint16_t)TXBUFFER[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + TXBUFFER[Count++] = '*'; + TXBUFFER[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + TXBUFFER[Count++] = Hex((CRC >> 8) & 15); + TXBUFFER[Count++] = Hex((CRC >> 4) & 15); + TXBUFFER[Count] = Hex(CRC & 15); + return Count; +} + + +char Hex(uint8_t lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + +uint8_t buildLocationOnly(float Lat, float Lon, uint16_t Alt, uint8_t stat) +{ + uint8_t len; + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationBinaryPacket); //identify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeInt16(Alt); //add altitude + LT.writeUint8(stat); //add tracker status + len = LT.endWriteSXBuffer(); //close buffer write + return len; +} + + +void reporttransmitError() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F("TXError,")); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + incMemoryUint16(addr_TXErrors); //increase the error count + setStatusByte(LORAError, 1); +} + + +void incMemoryUint32(uint32_t addr) +{ + uint32_t val = readMemoryUint32(addr); + val++; + writeMemoryUint32(addr, val); +} + + +void incMemoryUint16(uint32_t addr) +{ + uint16_t val = readMemoryUint16(addr); + val++; + writeMemoryUint16(addr, val); +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +uint8_t readConfigByte(uint8_t bitnum) +{ + return bitRead(Default_config1, bitnum); +} + + +void setTrackerMode() +{ + Serial.println(F("setTrackerMode")); + LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation); +} + + +void setSearchMode() +{ + Serial.println(F("setSearchMode")); + LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation); +} + + +uint8_t sendCommand(char cmd) +{ + uint8_t len; + TXVolts = readSupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + LT.writeUint8(cmd); //this byte defines the packet type + LT.writeUint8(Broadcast); //destination address of the packet, the receivers address + LT.writeUint8(ThisNode); //source address of this node + LT.writeUint16(TXVolts); //add the battery voltage + LT.writeUint8(TXStatus); //add the status byte + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, len, 5000, TrackerTXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void clearAllMemory() +{ + //clears the whole of non-volatile + Serial.println(F("Clear Memory")); + fillMemory(addr_StartMemory, addr_EndMemory, 0); +} + + +float readTempDS18B20() +{ + float DS18B20TXTemperature; + sensor.requestTemperatures(); + DS18B20TXTemperature = sensor.getTempCByIndex(0); + return DS18B20TXTemperature; +} + + +void printTempDS18B20() +{ + float DS18B20TXTemperature; + DS18B20TXTemperature = readTempDS18B20(); + Serial.print(F("Temperature ")); + Serial.print(DS18B20TXTemperature, 1); + Serial.println(F("c")); +} + + +void printSupplyVoltage() +{ + //get and display supply volts on terminal or monitor + Serial.print(F("Volts ")); + Serial.print(readSupplyVoltage()); + Serial.println(F("mV")); +} + + +uint16_t readSupplyVoltage() +{ + //relies on 1V1 internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit + } + + temp = analogRead(SupplyAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(SupplyAD); + volts = volts + temp; + } + volts = ((volts / 5) * ADMultiplier); + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn MOSFET connection resitor divider in circuit + } + + return volts; +} + + +//*********************************************************** +// Start GPS Functions +//*********************************************************** + +void GPSTest() +{ + uint32_t endmS; + + endmS = millis() + 2000; //run GPS echo for 2000mS + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +bool gpsWaitFix(uint16_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + + uint32_t endwaitmS, millistowait, currentmillis; + uint8_t GPSchar; + + Serial.flush(); + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.print(F("s ")); + Serial.flush(); + + GPS_OutputOn(); + Serial.flush(); + + currentmillis = millis(); + millistowait = waitSecs * 1000; + endwaitmS = currentmillis + millistowait; + + while (GPSserial.read() >= 0); //clear the GPS serial input buffer + + while (millis() < endwaitmS) + { + + if (GPSserial.available() > 0) + { + GPSchar = GPSserial.read(); + gps.encode(GPSchar); + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = (uint16_t) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TXAlt > 60000) + { + TXAlt = 0; + } + + TXHours = gps.time.hour(), + TXMinutes = gps.time.minute(), + TXSeconds = gps.time.second(), + TXSatellites = gps.satellites.value(); + TXGPSHdop = gps.hdop.value(); + + hours = gps.time.hour(); + mins = gps.time.minute(); + secs = gps.time.second(); + day = gps.date.day(); + month = gps.date.month(); + year = gps.date.year(); + + setStatusByte(GPSFix, 1); + + TXGPSfixms = millis() - GPSstartms; + + Serial.print(F("Have GPS Fix ")); + Serial.print(TXGPSfixms); + Serial.print(F("mS")); + Serial.println(); + + return true; + } + + } + + //if here then there has been no fix and a timeout + GPS_OutputOff(); + setStatusByte(GPSFix, 0); //set status bit to flag no fix + incMemoryUint16(addr_TXErrors); + Serial.println(F("Error No GPS Fix")); + return false; +} + +//*********************************************************** +// End GPS Functions +//*********************************************************** + + +//******************************************************************************* +// Start SD card routines +//******************************************************************************* + +bool logGPSfix(char *buf ) +{ + float tempfloat; + + logFile = SD.open(buf, FILE_APPEND); + + if (!logFile) + { + return false; + } + + tempfloat = ( (float) TXGPSHdop / 100); + + if (hours < 10) + { + logFile.print(F("0")); + } + + logFile.print(hours); + logFile.print(F(":")); + + if (mins < 10) + { + logFile.print(F("0")); + } + + logFile.print(mins); + logFile.print(F(":")); + + if (secs < 10) + { + logFile.print(F("0")); + } + + logFile.print(secs); + logFile.print(F(",")); + + logFile.print(day); + logFile.print(F("/")); + logFile.print(month); + logFile.print(F("/")); + logFile.print(year); + + logFile.print(F(",")); + logFile.print(TXLat, 6); + logFile.print(F(",")); + logFile.print(TXLon, 6); + logFile.print(F(",")); + logFile.print(TXAlt, 1); + logFile.print(F(",")); + logFile.print(TXSatellites); + logFile.print(F(",")); + logFile.print(tempfloat, 2); + logFile.print(F(",")); + logFile.print(TXVolts); + logFile.print(F(",")); + logFile.print(TXTemperature); + logFile.print(F(",")); + logFile.print(TXResets); + logFile.print(F(",")); + logFile.print(TXStatus); + logFile.print(F(",")); + logFile.print(TXErrors); + logFile.print(F(",")); + logFile.print(TXGPSfixms); + logFile.println(); + logFile.close(); + return true; +} + + +uint8_t setupSDLOG(char *buf) +{ + //creats a new filename + + uint16_t index; + + for (index = 1; index <= 9999; index++) { + buf[4] = index / 1000 + '0'; + buf[5] = ((index % 1000) / 100) + '0'; + buf[6] = ((index % 100) / 10) + '0'; + buf[7] = index % 10 + '0' ; + if (! SD.exists(filename)) { + // only open a new file if it doesn't exist + logFile = SD.open(buf, FILE_WRITE); + break; + } + } + + setStatusByte(SDError, 0); //SD card write OK + return index; //return number of logfile created +} + + +void cardFail(uint8_t num) +{ + Serial.print(num); //so we can tell where crd failed + Serial.println(" Card failed, or not present"); + led_Flash(100, 25); +} + +//******************************************************************************* +// End SD card routines +//******************************************************************************* + + +void setup() +{ + uint32_t i; + uint16_t j; + + Serial.begin(115200); //Setup Serial console ouput + Serial.println(); + Serial.println(); + Serial.println(F("75_Balloon_Tracker_Transmitter_SDLogger_ESP32 Starting")); + + memoryStart(Memory_Address); //setup the memory + j = readMemoryUint16(addr_ResetCount); + j++; + writeMemoryUint16(addr_ResetCount, j); + j = readMemoryUint16(addr_ResetCount); + + Serial.print(F("TXResets ")); + Serial.println(j); + + if (GPSPOWER >= 0) //if GPS needs power switching, turn it on + { + pinMode(GPSPOWER, OUTPUT); + digitalWrite(GPSPOWER, GPSONSTATE); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); //for MOSFET controlling battery volts resistor divider + } + +#ifdef QUECTELINUSE + Serial.println(F("Quectel GPS library")); +#endif + +#ifdef UBLOXINUSE + Serial.println(F("UBLOX GPS library")); +#endif + +#ifdef ClearAllMemory + clearAllMemory(); +#endif + + SPI.begin(); //initialize SPI + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + led_Flash(2, 125); + } + else + { + Serial.println(F("LoRa Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + setTrackerMode(); + + Serial.print(F("Config ")); + Serial.println(Default_config1, BIN); + + j = readMemoryUint16(addr_TXErrors); + Serial.print(F("TXErrors ")); + Serial.println(j); + + Serial.print(F("TXSequence ")); + i = readMemoryUint32(addr_SequenceNum); + Serial.println(i); + + Serial.print(F("ThisNode ")); + Serial.println(ThisNode); + + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + + Serial.println(); + printSupplyVoltage(); + printTempDS18B20(); + Serial.println(); + + j = readSupplyVoltage(); //get supply mV + TXStatus = 0; //clear all TX status bits + + sendCommand(PowerUp); //send power up command, includes supply mV and config, on tracker settings + + + Serial.println(); + Serial.println("Initializing SD card"); + + if (!SD.begin(SDCS)) + { + cardFail(1); + Serial.println(); + SDfound = false; + setStatusByte(SDError, 1); //flag SD card error + } + else + { + Serial.println("Card initialized"); + setupSDLOG(filename); //setup logfile name for writing + Serial.print(F("Write file to ")); + Serial.println(filename); + SDfound = true; + } + + + GPS_OutputOn(); + GPSTest(); + GPS_Setup(); //GPS should have had plenty of time to initialise by now + + delay(2000); + + if (GPS_CheckConfiguration()) //Check that GPS is configured for high altitude mode + { + Serial.println(); + GPS_OutputOff(); //GPS interrupts cause problems with lora device, so turn off for now + setStatusByte(GPSError, 0); + setStatusByte(GPSConfigError, 0); + + //Alert user to GPS OK, turn LED on and send a FM tone. + digitalWrite(LED1, HIGH); + Serial.println(F("GPS Config OK")); //check tone indicates navigation model 6 set + Serial.println(); + Serial.flush(); + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + LT.toneFM(1500, 500, deviation, adjustfreq, TrackerTXpower); //Transmit an FM tone, 1000hz, 3000ms + delay(1000); + digitalWrite(LED1, LOW); + } + else + { + setStatusByte(GPSConfigError, 1); + incMemoryUint16(addr_TXErrors); + Serial.println(F("GPS Error")); + Serial.println(); + setTrackerMode(); + sendCommand(NoGPS); //make sure receiver knows about GPS error + led_Flash(100, 25); //long very rapid flash for GPS error + } + + GPSstartms = millis(); + + setTrackerMode(); //so that commands indicating wait for a GPS go out + + while (!gpsWaitFix(5)) //wait for the initial GPS fix, this could take a while + { + sendCommand(NoFix); + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + } + + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + digitalWrite(LED1, HIGH); + LT.toneFM(500, 2000, deviation, adjustfreq, TrackerTXpower); + digitalWrite(LED1, LOW); + GPS_OutputOn(); + delay(2000); //GPS may be in software backup allow time for it to wakeup + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled + GPS_OutputOff(); + + + + + +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/75_Balloon_Tracker_Transmitter_SDLogger_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/75_Balloon_Tracker_Transmitter_SDLogger_ESP32/Settings.h new file mode 100644 index 0000000..2730922 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/ESP32/Tracker/75_Balloon_Tracker_Transmitter_SDLogger_ESP32/Settings.h @@ -0,0 +1,142 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 08/06/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify lora board type and pins here +//************************************************************************************************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. + +#define NSS 5 //select on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 27 //reset on LoRa device +#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 2 //On board LED, high for on +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used +#define ONE_WIRE_BUS 32 //for DS18B20 temperature sensor +#define SupplyAD 36 //pin for reading supply\battery voltage +#define BATVREADON 2 //turns on battery resistor divider, high for on +#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV +#define SDCS 13 //microSD card select + +#define RXpin 17 //pin number for GPS RX input into Arduino - TX from GPS +#define TXpin 16 //pin number for GPS TX output from Arduino- RX into GPS + +#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used +#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER +#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +#define ClearAllMemory //Clears memory of stored tracker information, counts, errors etc + +//************************************************************************************************** +// 3) LoRa modem settings +//************************************************************************************************** + +//LoRa Modem Parameters +const uint32_t Offset = 0; //offset frequency for calibration purposes + +//Tracker mode +const uint32_t TrackerFrequency = 434000000; //frequency of transmissions +const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t TrackerTXpower = 10; //LoRa TX power in dBm + +//Search mode +const uint32_t SearchFrequency = 434000000; //frequency of transmissionsconst +uint8_t SearchBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t SearchTXpower = 10; //LoRa TX power in dBm + +const uint16_t deviation = 10000; //deviation in hz for FM tones +const float adjustfreq = 0.9; //adjustment to tone frequency + +const byte TXBUFFER_SIZE = 128; //defines the maximum size of the trasnmit buffer; + + +//************************************************************************************************** +// 4) GPS Options +//************************************************************************************************** + +#define GPSBaud 9600 //GPS Baud rate + +#define HARDWARESERIALPORT Serial2 //if your using hardware serial for the GPS, define it here + +const uint16_t WaitGPSFixSeconds = 60; //when in flight the time to wait for a new GPS fix + +#define GPS_Library //use library file for UBLOX GPS +//#define GPS_Library //use library file for Quectel GPS + + +//************************************************************************************************** +// 5) FSK RTTY Settings +//************************************************************************************************** + +uint32_t FrequencyShift = 500; //hertz frequency shift for audio +uint8_t NumberofPips = 4; //number of marker pips to send +uint16_t PipDelaymS = 1000; //mS between pips when carrier is off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 1000; //ms of leadin constant shifted carrier + + +//**************************************************************************************************** +// 6) Program Default Option settings - This section determines which options are on or off by default, +// these are saved in the Default_config1 byte. These options are set in this way so that it is +// possible (in future program changes) to alter the options remotly. +//************************************************************************************************** + +uint8_t OptionOff = 0; +uint8_t OptionOn = 1; + +const char option_SearchEnable = OptionOff; //set to OptionOn to enable transmit of Search mode packet +const char option_FSKRTTYEnable = OptionOff; //set to OptionOn to enable transmit of FSKRTTY + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) + +const unsigned int Default_config1 = (option_SearchEnable_SUM + option_FSKRTTYEnable_SUM); +//const unsigned int Default_config1 = 0x05; //Phew, the default config can always be set manually........ + //0x05 would turn on transmit of search mode and FSKRTTY + + +//************************************************************************************************** +// 7) Memory settings - define the type of memory to use for non-Volatile storage. +// The ESP32 version of the HAB tracker transmitter only supports the use of FRAM here. +//************************************************************************************************** + +//#define Memory_Library +#define Memory_Library + +int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM + +//************************************************************************************************** +// 8) HAB Flight Settings +//************************************************************************************************** + +char FlightID[] = "Flight1"; //flight ID for HAB packet + +const unsigned int SleepTimesecs = 13; //sleep time in seconds after each TX loop + +const char ThisNode = '1'; //tracker number for search packet + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/40_LoRa_Transmitter_ImplicitPacket/40_LoRa_Transmitter_ImplicitPacket.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/40_LoRa_Transmitter_ImplicitPacket/40_LoRa_Transmitter_ImplicitPacket.ino new file mode 100644 index 0000000..f8a9451 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/40_LoRa_Transmitter_ImplicitPacket/40_LoRa_Transmitter_ImplicitPacket.ino @@ -0,0 +1,192 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 04/01/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is 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> Hello World 123456* BytesSent,23 CRC,DAAB TransmitTime,8mS PacketsSent,1 + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint8_t TXPacketL; +uint32_t TXPacketCount, startmS, endmS; + +uint8_t buff[] = "Hello World 1234567890"; //buffer length must be 23, and defined in constant PacketLength + + +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, must be 19 characters + 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 sent packet + Serial.print(F(" TransmitTime,")); + Serial.print(endmS - startmS); //print transmit time of packet + Serial.print(F("mS")); + Serial.print(F(" PacketsSent,")); + Serial.print(TXPacketCount); //print total of packets sent OK +} + + +void packet_is_Error() +{ + //if here there was an error transmitting packet + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setupLoRa() +{ + //this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + //This is the typical IRQ parameters set, actually excecuted in the transmit function + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done +} + + +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("40_LoRa_Transmitter_ImplicitPacket Starting")); + + SPI.begin(); + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //this function call sets up the device for LoRa using the settings from the Settings.h file + setupLoRa(); + + 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/40_LoRa_Transmitter_ImplicitPacket/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/40_LoRa_Transmitter_ImplicitPacket/Settings.h new file mode 100644 index 0000000..ce51c92 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/40_LoRa_Transmitter_ImplicitPacket/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF6; //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 = 23; //packet length is fixed + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 2000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/41_LoRa_Receiver_ImplicitPacket/41_LoRa_Receiver_ImplicitPacket.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/41_LoRa_Receiver_ImplicitPacket/41_LoRa_Receiver_ImplicitPacket.ino new file mode 100644 index 0000000..9cd43c2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/41_LoRa_Receiver_ImplicitPacket/41_LoRa_Receiver_ImplicitPacket.ino @@ -0,0 +1,258 @@ +/******************************************************************************************************* + 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 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 23 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 + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int16_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio of received packet + + +void loop() +{ + setupLoRa(); + RXPacketL = LT.receive(RXBUFFER, PacketLength, 0, NO_WAIT); //wait for a packet to arrive with 60seconds (60000mS) timeout + + while (!digitalRead(DIO0)); //wait for DIO0 to go high + + digitalWrite(LED1, HIGH); + + 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 ( LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID)) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + + 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.readPacket(RXBUFFER, PacketLength); + LT.printASCIIPacket(RXBUFFER, PacketLength); //print the packet as ASCII characters + + localCRC = LT.CRCCCITT(RXBUFFER, PacketLength, 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(PacketLength); + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + printElapsedTime(); //print elapsed time to Serial Monitor + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F(" RXTimeout")); + } + else + { + errors++; + Serial.print(F(" PacketError")); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); //print the names of the IRQ registers set + } + + delay(250); //gives a longer buzzer and LED flash for error + +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F("s")); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setupLoRa() +{ + //this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + //This is the typical IRQ parameters set, actually excecuted in the receive function + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done +} + + +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("41_LoRa_Receiver_ImplicitPacket 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)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //this function call sets up the device for LoRa using the settings from the Settings.h file + setupLoRa(); + + 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/41_LoRa_Receiver_ImplicitPacket/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/41_LoRa_Receiver_ImplicitPacket/Settings.h new file mode 100644 index 0000000..f73d7a5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Implicit/41_LoRa_Receiver_ImplicitPacket/Settings.h @@ -0,0 +1,45 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF6; //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 = 23; //packet length is fixed + +const int8_t TXpower = 2; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino new file mode 100644 index 0000000..bcd24a4 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino @@ -0,0 +1,99 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/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. + + The matching receiving program '9_LoRa_LowMemory_RX' can be used to receive and display the packet + + The contents of the packet received, and printed to serial monitor, should be; + + TR1 (buffer) - trackerID + 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 + + Memory use on an Arduino Pro Mini; + Sketch uses 4958 bytes (15%) of program storage space. + Global variables use 224 bytes (10%) of dynamic memory, leaving 1824 bytes for local variables. + + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include +#include "Settings.h" + +SX127XLT LoRa; + + +void loop() +{ + //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. + + char trackerID[] = "TR1"; + float latitude = 51.23456; + float longitude = -3.12345; + uint16_t altitude = 199; + uint8_t satellites = 8; + uint16_t voltage = 3999; + int16_t temperature = 9; + uint8_t TXPacketL = 0; + uint8_t BytesSent = 0; + + LoRa.startWriteSXBuffer(0); //start the write at SX12XX internal buffer location 0 + LoRa.writeBufferChar(trackerID, sizeof(trackerID)); //+4 bytes (3 characters plus null (0) at end) + LoRa.writeFloat(latitude); //+4 = 8 bytes + LoRa.writeFloat(longitude); //+4 = 12 bytes + LoRa.writeUint16(altitude); //+2 = 14 bytes + LoRa.writeUint8(satellites); //+1 = 15 bytes + LoRa.writeUint16(voltage); //+2 = 17 bytes + LoRa.writeInt8(temperature); //+1 = 18 bytes total to send + TXPacketL = LoRa.endWriteSXBuffer(); //closes packet write and returns the length of the packet to send + + BytesSent = LoRa.transmitSXBuffer(0, TXPacketL, 5000, TXpower, WAIT_TX); //set a TX timeout of 5000mS + + if (BytesSent == 0) //if bytessent is 0, there has been a error + { + Serial.print(F("Send Error")); + } + else + { + Serial.print(BytesSent); + Serial.print(F(" Bytes Sent")); + } + + Serial.println(); + delay(packet_delay); +} + + +void setup() +{ + Serial.begin(9600); + + SPI.begin(); + + if (!LoRa.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("Device error")); + while (1); + } + + LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + Serial.flush(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h new file mode 100644 index 0000000..3a9d0db --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h @@ -0,0 +1,30 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/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. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//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 in dBm +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino new file mode 100644 index 0000000..2fb3ab6 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino @@ -0,0 +1,168 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/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 memory buffer, the LoRa device + internal buffer is read direct for 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. + + The matching transmitter program '8_LoRa_LowMemory_TX' is used to transmit the packet. + + The contents of the packet received, and printed to serial monitor, should be; + + TR1 (buffer) - trackerID + 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 + + + + Memory use on an Arduino Pro Mini; + + Sketch uses 6290 bytes (19%) of program storage space. + Global variables use 237 bytes (11%) of dynamic memory, leaving 1811 bytes for local variables. + + + Serial monitor baud rate is set at 9600. + +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" + +SX127XLT LoRa; + + +void loop() +{ + uint8_t RXPacketL; + + RXPacketL = LoRa.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + Serial.println(); +} + + +uint8_t packet_is_OK() +{ + char receivebuffer[4]; //create receive buffer, make sure this is big enough for buffer sent !!! + float latitude; + float longitude; + uint16_t altitude; + uint8_t satellites; + uint16_t voltage; + int8_t temperature; + uint8_t RXPacketL; + static uint8_t RXpacketCount; + + //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(" ")); + + LoRa.startReadSXBuffer(0); //start buffer read at location 0 + LoRa.readBufferChar(receivebuffer); //read in the character buffer + latitude = LoRa.readFloat(); //read in the latitude + longitude = LoRa.readFloat(); //read in the longitude + altitude = LoRa.readUint16(); //read in the altitude + satellites = LoRa.readUint8(); //read in the number of satellites + voltage = LoRa.readUint16(); //read in the voltage + temperature = LoRa.readInt8(); //read in the temperature + RXPacketL = LoRa.endReadSXBuffer(); //finish packet read, get received packet length + + Serial.print(receivebuffer); //print the received character buffer + 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 ")); + printpacketDetails(); + return RXPacketL; +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LoRa.readIrqStatus(); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout")); + } + else + { + Serial.print(F("PacketError")); + printpacketDetails(); + Serial.print(F("IRQreg,")); + Serial.print(IRQStatus, HEX); + } +} + + +void printpacketDetails() +{ + int16_t PacketRSSI; //RSSI of received packet + int8_t PacketSNR; //signal to noise ratio of received packet + + PacketRSSI = LoRa.readPacketRSSI(); + PacketSNR = LoRa.readPacketSNR(); + + Serial.print(F(" RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB")); +} + + +void setup() +{ + Serial.begin(9600); + + SPI.begin(); + + if (LoRa.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("Device OK")); + } + else + { + Serial.println(F("Device error")); + while (1); + } + + Serial.flush(); + LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h new file mode 100644 index 0000000..67f7a9c --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h @@ -0,0 +1,28 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/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. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//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 in dBm +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino new file mode 100644 index 0000000..81e0489 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino @@ -0,0 +1,306 @@ +/******************************************************************************************************* + 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 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 +#include +#include "Settings.h" +#include + +#include //watchdog timer library, integral to Arduino IDE +#include //watchdog timer library, integral to Arduino IDE +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +SX127XLT 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 + + 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, DIO0, DIO1, DIO2, 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(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h new file mode 100644 index 0000000..5ef9b2e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h @@ -0,0 +1,47 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done +const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1 +const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1 +const int8_t LED1 = 8; //On board LED, logic high is on + +#define LORA_DEVICE DEVICE_SX1278 //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 +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 transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino new file mode 100644 index 0000000..a95093f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino @@ -0,0 +1,297 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 31/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 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 +#include +#include "Settings.h" +#include + + +SX127XLT LT; + +uint32_t RXpacketCount; +uint16_t errors; + +uint8_t RXPacketL; //length of received packet +uint8_t RXPacketType; //type of received packet +int16_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, DIO0, DIO1, DIO2, 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")); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/22_On_Off_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/22_On_Off_Receiver/Settings.h new file mode 100644 index 0000000..52e8f82 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/22_On_Off_Receiver/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 31/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done +const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1 +const int8_t DIO2 = -1; //DIO2 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 BUZZER = A5; //buzzer if fitted, set to -1 if not + +#define LORA_DEVICE DEVICE_SX1278 //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 + +//******* 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 + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino new file mode 100644 index 0000000..9ca8468 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino @@ -0,0 +1,229 @@ +/******************************************************************************************************* + 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 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 +#include +#include "Settings.h" +#include + +SX127XLT 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 setupLoRa() +{ + //this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + //This is the typical IRQ parameters set, actually excecuted in the transmit function + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + setupSwitches(); + + Serial.begin(115200); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + led_Flash(2, 125); + } + else + { + Serial.println(F("Device error")); + while (1) + { + led_Flash(50, 50); + } + } + + //this function call sets up the device for LoRa using the settings from the Settings.h file + setupLoRa(); + + attachInterrupts(); + + 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(F("35_Remote_Control_Servo_Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h new file mode 100644 index 0000000..cfa473d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h @@ -0,0 +1,47 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done +const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1 +const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1 +const int8_t LED1 = 8; //On board LED, logic high is on + +#define LORA_DEVICE DEVICE_SX1278 //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 +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF6; //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 uint8_t PacketLength = 5; //packet length is fixed + +const int8_t TXpower = 10; //LoRa transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino new file mode 100644 index 0000000..7b4c027 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino @@ -0,0 +1,275 @@ +/******************************************************************************************************* + 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 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 +#include +#include "Settings.h" +#include + +SX127XLT LT; + +#include +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() +{ + + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort + + while (!digitalRead(DIO0)); //wait for DIO0 to go high + + if ( LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID)) + { + packet_is_OK(); + } + else + { + 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; + int16_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 setupLoRa() +{ + //this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + //This is the typical IRQ parameters set, actually excecuted in the transmit function + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done +} + + +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, DIO0, DIO1, DIO2, 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 + } + } + + //this function call sets up the device for LoRa using the settings from the Settings.h file + setupLoRa(); + + 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(F("36_Remote_Control_Servo_Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h new file mode 100644 index 0000000..717a1bc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 02/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done +const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1 +const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1 +const int8_t LED1 = 8; //On board LED, logic high is on + +#define LORA_DEVICE DEVICE_SX1278 //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 + +//******* 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_500; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF6; //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 uint8_t PacketLength = 5; //packet length is fixed + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/86_Buffer_Transmit_Controller/86_Buffer_Transmit_Controller.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/86_Buffer_Transmit_Controller/86_Buffer_Transmit_Controller.ino new file mode 100644 index 0000000..2e7c471 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/86_Buffer_Transmit_Controller/86_Buffer_Transmit_Controller.ino @@ -0,0 +1,127 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 is a LoRa transmitter that transmits a buffer containing text to control a + remote device by sending 'LEDOn' to turn the LED on and 'LEDOff' to turn the LED off. + + Sample Serial Monitor output; + + 86_Buffer_Transmit_Controller Starting + LoRa Device found + Transmitter ready + Send Packet> LEDOn + Send Packet> LEDOff + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library + +SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for sensing RX and TX done +#define LED1 8 //pin for LED + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using +#define TXpower 10 //LoRa transmit power in dBm +#define TXtimeout 10000 //transmit timeout in mS + +uint8_t TXPacketL; + +uint8_t onpacket[] = "LEDOn"; //send this to turn LED on +uint8_t offpacket[] = "LEDOff"; //send this to turn LED off + +#include +#include + + +void loop() +{ + //************************************ + //LED on + //************************************ + + Serial.print(F("Send Packet> (")); + Serial.print(sizeof(onpacket)); + Serial.print(F("chars) ")); + + LT.printASCIIPacket(onpacket, sizeof(onpacket)); //print the buffer (the sent packet) as ASCII + + digitalWrite(LED1, HIGH); + LT.transmit(onpacket, sizeof(onpacket), TXtimeout, TXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error + + Serial.println(); + delay(5000); //have a delay between packets + + //************************************ + //LED off + //************************************ + + Serial.print(F("Send Packet> (")); + Serial.print(sizeof(offpacket)); + Serial.print(F("chars) ")); + LT.printASCIIPacket(offpacket, sizeof(offpacket)); //print the buffer (the sent packet) as ASCII + + digitalWrite(LED1, LOW); + LT.transmit(offpacket, sizeof(offpacket), TXtimeout, TXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error + + Serial.println(); + delay(5000); //have a delay between packets +} + + +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); + Serial.begin(9600); + Serial.println(); + Serial.println(F("86_Buffer_Transmit_Controller Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, 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 + } + } + + 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(); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/87_Buffer_Receive_Controller/87_Buffer_Receive_Controller.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/87_Buffer_Receive_Controller/87_Buffer_Receive_Controller.ino new file mode 100644 index 0000000..6109d69 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/RemoteControl/87_Buffer_Receive_Controller/87_Buffer_Receive_Controller.ino @@ -0,0 +1,176 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 is a LoRa receiver that listens for packets that are text based commands used + when received to turn a LED on or off. When 'LEDOn' is received the LED is turned on and its turned off + when 'LEDOff' is received. + + Sample Serial Monitor output; + + 87_Buffer_Receive_Controller Starting + + LoRa Device found + Receiver ready + 2s Received packet > LEDOn,RSSI,-65dBm,SNR,6dB,Length,5 Turn LED on + 3s Received packet > LEDOff,RSSI,-62dBm,SNR,5dB,Length,6 Turn LED off + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library + +SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define LED1 8 //pin for LED + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using +#define RXtimeout 60000 //receive timeout in mS + +char RXBUFFER[16]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int16_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet + +char onpacket[] = "LEDOn"; //send this to turn LED on +char offpacket[] = "LEDOff"; //send this to turn LED off + + +void loop() +{ + RXPacketL = LT.receive( (uint8_t*) RXBUFFER, sizeof(RXBUFFER), RXtimeout, WAIT_RX); //wait for a packet to arrive with 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(); + + if (strncmp((char*) RXBUFFER, onpacket, strlen(onpacket)) == 0) + { + Serial.print(F(" Turn LED on")); + digitalWrite(LED1, HIGH); + } + + if ( strncmp( (char*) RXBUFFER, offpacket, strlen(offpacket)) == 0) + { + Serial.print(F(" Turn LED off")); + digitalWrite(LED1, LOW); + } + + } + Serial.println(); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F("s")); +} + + +void packet_is_OK() +{ + printElapsedTime(); //print elapsed time to Serial Monitor + Serial.print(F(" Received packet > ")); + LT.printASCIIPacket((uint8_t*)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); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + printElapsedTime(); //print elapsed time to Serial Monitor + Serial.print(F(" Packet error > ")); + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F(" RXTimeout")); + } + else + { + 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(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); //print the names of the IRQ registers set + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); + Serial.begin(9600); + Serial.println(); + Serial.println(F("87_Buffer_Receive_Controller Starting")); + Serial.println(); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, 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 + } + } + + LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings + + Serial.println(F("Receiver ready")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/1_LED_Blink_STM32/1_LED_Blink_STM32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/1_LED_Blink_STM32/1_LED_Blink_STM32.ino new file mode 100644 index 0000000..c70de07 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/1_LED_Blink_STM32/1_LED_Blink_STM32.ino @@ -0,0 +1,69 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This programs is supplied as is, it is up to the user of the program to decide if the programs are + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program blinks an LED connected the pin number defined below. The 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_STM32 Starting")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/2_Register_Test_STM32/2_Register_Test_STM32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/2_Register_Test_STM32/2_Register_Test_STM32.ino new file mode 100644 index 0000000..7915fbb --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/2_Register_Test_STM32/2_Register_Test_STM32.ino @@ -0,0 +1,300 @@ +/******************************************************************************************************* + + 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 is stand alone, it is not necessary to install the SX12XX-LoRa library + to use it. + + The program checks that a SX127X LoRa device can be accessed by doing a test register write and read. + If there is no device found a message is printed on the serial monitor. The contents of the registers + from 0x00 to 0x7F are printed, there is a copy of a typical printout below. Note that the read back + changed frequency may be slightly different to the programmed frequency, there is a rounding error due + to the use of floats to calculate the frequency. + + The Arduino pin numbers that the NSS and NRESET pins on the LoRa device are connected to must be + specified in the hardware definitions section below. The LoRa device type in use, SX1272, SX1276, + SX1277, SX1278 or SX1279 must be specified also. + + Typical printout; + + 2_Register_Test Starting + SX1276-79 Selected + LoRa Device found + Device version 0x12 + + Frequency at reset 434000000 + Registers at reset + Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x00 00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A + 0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40 + 0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55 + 0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40 + 0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B + 0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78 + 0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Changed Frequency 434099968 + Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x00 00 09 1A 0B 00 52 6C 86 66 4F 09 2B 20 08 02 0A + 0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40 + 0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55 + 0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40 + 0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B + 0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78 + 0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B + 0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +const uint8_t REG_FRMSB = 0x06; //register number for setting setting and reading frequency, high byte +const uint8_t REG_FRMID = 0x07; //register number for setting setting and reading frequency, mid byte +const uint8_t REG_FRLSB = 0x08; //register number for setting setting and reading frequency, low byte +const uint8_t REG_VERSION = 0x42; //register containg version number of device + +const uint8_t DEVICE_SX1272 = 0x10; //SX1272 +const uint8_t DEVICE_SX1276 = 0x11; //SX1276 +const uint8_t DEVICE_SX1277 = 0x12; //SX1277 +const uint8_t DEVICE_SX1278 = 0x13; //SX1278 +const uint8_t DEVICE_SX1279 = 0x14; //SX1279 + +//********* Setup hardware definitions here ! ***************** + +//These are the pin definitions for one of the Tracker boards, 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 //SX127X device select +#define NRESET 9 //SX127X reset pin +#define DIO0 -1 //DIO0 pin on LoRa device, not used here so set to -1 +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //defines the type of LoRa device used, needed for correct program operation + +//**************************************************************/ + + +#include + + +void setup() +{ + Serial.begin(9600); + Serial.println(F("2_Register_Test_STM32 Starting")); + + SPI.begin(); + SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //The begin function setups the hardware pins used by device and then checks if device is found + //the DIO0, DIO1 and DIO2 pins are not used in this example so are set to -1 + //the LT.begin fuction can define the pins and device type directly in this way (for SX1278); + //LT.begin(10, 9, -1, -1, -1, DEVICE_SX1278) + + if (begin(NSS, NRESET, -1, -1, -1, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + } + else + { + Serial.println(F("No device responding")); + } + + Serial.print(F("Device version 0x")); + uint8_t deviceversion = readRegister(REG_VERSION); + if (deviceversion < 0x10) + { + Serial.print(F("0")); + } + Serial.println(deviceversion, HEX); +} + + +void loop() +{ + uint32_t frequency; + + frequency = getFreqInt(); //read the set frequency following a reset + Serial.print(F("Frequency at reset ")); + Serial.println(frequency); + + Serial.println(F("Registers at reset")); //show the all registers following a reset + printRegisters(0x00, 0x7F); + + Serial.println(); + Serial.println(); + + setRfFrequency(434100000, 0); //change the frequency at reset, in hertz + frequency = getFreqInt(); //read back the changed frequency + Serial.print(F("Changed Frequency ")); + Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ? + printRegisters(0x00, 0x7F); //show the registers after frequency change + Serial.println(); + delay(5000); + resetDevice(LORA_DEVICE); //reset the device and start again +} + + +uint8_t readRegister(uint8_t address) +{ + uint8_t regdata; + digitalWrite(NSS, LOW); //set NSS low + SPI.transfer(address & 0x7F); //mask address for read + regdata = SPI.transfer(0); //read the byte + digitalWrite(NSS, HIGH); //set NSS high + return regdata; +} + + +void writeRegister(uint8_t address, uint8_t value) +{ + digitalWrite(NSS, LOW); //set NSS low + SPI.transfer(address | 0x80); //mask address for write + SPI.transfer(value); //write the byte + digitalWrite(NSS, HIGH); //set NSS high +} + + +uint32_t getFreqInt() +{ + //get the current set LoRa device frequency, return as long integer + + uint8_t Msb, Mid, Lsb; + uint32_t uinttemp; + float floattemp; + Msb = readRegister(REG_FRMSB); + Mid = readRegister(REG_FRMID); + Lsb = readRegister(REG_FRLSB); + floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb); + floattemp = ((floattemp * 61.03515625) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +void printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of SX127x registers to serial monitor + + uint16_t Loopv1, Loopv2, RegData; + + Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F")); + Serial.println(); + + for (Loopv1 = Start; Loopv1 <= End;) + { + Serial.print(F("0x")); + if (Loopv1 < 0x10) + { + Serial.print(F("0")); + } + Serial.print((Loopv1), HEX); + Serial.print(F(" ")); + for (Loopv2 = 0; Loopv2 <= 15; Loopv2++) + { + RegData = readRegister(Loopv1); + if (RegData < 0x10) + { + Serial.print(F("0")); + } + Serial.print(RegData, HEX); + Serial.print(F(" ")); + Loopv1++; + } + Serial.println(); + } +} + + +void setRfFrequency(uint64_t freq64, int32_t offset) +{ + freq64 = freq64 + offset; + freq64 = ((uint64_t)freq64 << 19) / 32000000; + writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16)); + writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8)); + writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0)); +} + + +void resetDevice(uint8_t device) +{ + if (device == DEVICE_SX1272) + { + digitalWrite(NRESET, HIGH); + delay(2); + digitalWrite(NRESET, LOW); + delay(20); + Serial.println(F("SX1272 Selected")); + } + else + { + digitalWrite(NRESET, LOW); + delay(2); + digitalWrite(NRESET, HIGH); + delay(20); + Serial.println(F("SX1276-79 Selected")); + } +} + + +bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device) +{ + pinMode(pinNSS, OUTPUT); + digitalWrite(pinNSS, HIGH); + pinMode(pinNRESET, OUTPUT); + digitalWrite(pinNRESET, LOW); + + if (pinDIO0 >= 0) + { + pinMode( pinDIO0, INPUT); + } + + if (pinDIO1 >= 0) + { + pinMode( pinDIO1, INPUT); + } + + if (pinDIO2 >= 0) + { + pinMode( pinDIO2, INPUT); + } + + resetDevice(device); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool checkDevice() +{ + //check there is a device out there, writes a register and reads back + + uint8_t Regdata1, Regdata2; + Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting + writeRegister(REG_FRMID, (Regdata1 + 1)); + Regdata2 = readRegister(REG_FRMID); //read changed value back + writeRegister(REG_FRMID, Regdata1); //restore register to original value + + if (Regdata2 == (Regdata1 + 1)) + { + return true; + } + else + { + return false; + } +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/3_LoRa_Transmitter_STM32/3_LoRa_Transmitter_STM32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/3_LoRa_Transmitter_STM32/3_LoRa_Transmitter_STM32.ino new file mode 100644 index 0000000..bd05cd3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/3_LoRa_Transmitter_STM32/3_LoRa_Transmitter_STM32.ino @@ -0,0 +1,182 @@ +/******************************************************************************************************* + 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 is a simple 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 SX127X 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, '4_LoRa_Receive' + can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h) + must be the same for the Transmit and Receive program. Sample Serial Monitor output; + + 10dBm Packet> {packet contents*} BytesSent,23 CRC,DAAB TransmitTime,54mS PacketsSent,1 + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the SX127X device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint8_t TXPacketL; +uint32_t TXPacketCount, startmS, endmS; + +uint8_t buff[] = "Hello World 1234567890"; + +void loop() +{ + Serial.print(TXpower); //print the transmit power defined + Serial.print(F("dBm ")); + Serial.print(F("Packet> ")); + Serial.flush(); + + TXPacketL = sizeof(buff); //set TXPacketL to length of array + buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver + + LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII + + digitalWrite(LED1, HIGH); + startmS = millis(); //start transmit timer + if (LT.transmit(buff, TXPacketL, 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 sent packet + Serial.print(F(" TransmitTime,")); + Serial.print(endmS - startmS); //print transmit time of packet + Serial.print(F("mS")); + Serial.print(F(" PacketsSent,")); + Serial.print(TXPacketCount); //print total of packets sent OK +} + + +void packet_is_Error() +{ + //if here there was an error transmitting packet + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("3_LoRa_Transmitter_STM32 Starting")); + + SPI.begin(); + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //The function call list below shows the complete setup for the LoRa device using the information defined in the + //Settings.h file. + //The 'Setup LoRa device' list below can be replaced with a single function call; + //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done + //*************************************************************************************************** + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + Serial.println(); + LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/3_LoRa_Transmitter_STM32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/3_LoRa_Transmitter_STM32/Settings.h new file mode 100644 index 0000000..ac3018e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/3_LoRa_Transmitter_STM32/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/4_LoRa_Receiver_STM32/4_LoRa_Receiver_STM32.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/4_LoRa_Receiver_STM32/4_LoRa_Receiver_STM32.ino new file mode 100644 index 0000000..55b0f61 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/4_LoRa_Receiver_STM32/4_LoRa_Receiver_STM32.ino @@ -0,0 +1,247 @@ +/******************************************************************************************************* + 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 - The program listens for incoming packets using the LoRa settings in the 'Settings.h' + file. The pins to access the SX127X need to be defined in the 'Settings.h' file also. + + There is a printout of the valid packets received, the packet is assumed to be in ASCII printable text, + if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor. + The LED will flash for each packet received and the buzzer will sound, if fitted. + + Sample serial monitor output; + + 1109s Hello World 1234567890*,CRC,DAAB,RSSI,-61dBm,SNR,9dB,Length,23,Packets,1026,Errors,0,IRQreg,50 + + If there is a packet error it might look like this, which is showing a CRC error, + + 1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the SX127X device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int8_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio of received packet + + +void loop() +{ + RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout + + digitalWrite(LED1, HIGH); //something has happened + + if (BUZZER > 0) //turn buzzer on + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + PacketSNR = LT.readPacketSNR(); //read the received SNR value + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + digitalWrite(LED1, LOW); //LED off + + Serial.println(); +} + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + RXpacketCount++; + + printElapsedTime(); //print elapsed time to Serial Monitor + Serial.print(F(" ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER + Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC + Serial.print(localCRC, HEX); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(RXPacketL); + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + printElapsedTime(); //print elapsed time to Serial Monitor + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F(" RXTimeout")); + } + else + { + errors++; + Serial.print(F(" PacketError")); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); //print the names of the IRQ registers set + } + + delay(250); //gives a longer buzzer and LED flash for error + +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F("s")); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("4_LoRa_Receiver 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, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + //The function call list below shows the complete setup for the LoRa device using the information defined in the + //Settings.h file. + //The 'Setup LoRa device' list below can be replaced with a single function call; + //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device + LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions + LT.setRfFrequency(Frequency, Offset); //set the operating frequency + LT.calibrateImage(0); //run calibration after setting frequency + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters + LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX + LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters + LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34 + LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current + LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done + //*************************************************************************************************** + + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check + Serial.println(); + Serial.println(); + LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/4_LoRa_Receiver_STM32/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/4_LoRa_Receiver_STM32/Settings.h new file mode 100644 index 0000000..a152d0b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Basics/4_LoRa_Receiver_STM32/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 2; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Pictures/Arduino_IDE_for_STM32.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Pictures/Arduino_IDE_for_STM32.jpg new file mode 100644 index 0000000..278a799 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Pictures/Arduino_IDE_for_STM32.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Pictures/STM32_and_Shield.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Pictures/STM32_and_Shield.jpg new file mode 100644 index 0000000..ae306e7 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/Pictures/STM32_and_Shield.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/ReadMe.md b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/ReadMe.md new file mode 100644 index 0000000..9bd97d2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/STM32/ReadMe.md @@ -0,0 +1,38 @@ +## STM32 - SX127X Library Example Programs + +I decided to check if my SX127X library and examples would work with a STM32 board. When I require a micro controller that needs more pins or memory than a ATmega328P, my goto processor has been the ATMeg1284P. This has 128k of flash memory and 16K of RAM, so 4 times the flash and 8 times the RAM of an ATmega328P based Pro Mini. The 1284P still only runs at 8Mhz (3.3V) which can be considered slow in a modern context and more non-pinchange interrupts would be a definite advantage, so I decided to give a STM32 a go. With the STM32 there is the potential to use devices with much greater speed, flash, RAM and IO pins. + +I chose an XNucleo F103RB since that will easily take one of my Arduino shields that uses breadboard friendly modules, so it would simple and quick to test out the SX127X lora library examples. The board is pictured below; + + +![Picture 1](/pictures/STM32_and_Shield.jpg) + +The slim board at the top right of the picture is the supplied STLink programmer. + +I installed the STM32 core for Arduino; + +[https://github.com/stm32duino/Arduino/_Core/_STM32](https://github.com/stm32duino/Arduino_Core_STM32) + +Plugged in my Arduino shield, inserted the STlink programmer supplied with the board (see picture above) and connected the 'USB to USART' port to my PC so that I could monitor Serial Monitor stuff. + +I loaded the **1\_LED\_Blink\_STM32** program, then set-up the Arduino IDE as in the picture below; + +Arduino_IDE_for _STM32 + +![Picture 1](/pictures/Arduino_IDE_for_STM32.jpg) + +The blink program loaded and worked just fine. + +Next the **2\_Register\_Test\_STM32** was loaded and that worked too. + +Then the **3\_LoRa\_Transmitte\r_STM32** program was tried. I connected up my Realtek SDR and SDR#\Airspy combo and I could see lora packets being sent at 434Mhz. Hooked up another ATMega board as a receiver and it showed packets were being sent and received correctly. + +I changed the XNucleo board over to the **4\_LoRa\_Receiver\_STM32** program and that could receive lora packets OK. + +In conclusion, the SX127X example lora transmit and receive programs worked on the STM32 with no changes needed. + + + **Stuart Robinson** + + **February 2020** + \ No newline at end of file diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino new file mode 100644 index 0000000..5000077 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino @@ -0,0 +1,332 @@ +/******************************************************************************************************* + 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 - The program transmits a LoRa packet without using a processor buffer, the LoRa + devices internal buffer is filled directly with variables. + + The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There + is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end. + + Although the LoRa packet transmitted and received has its own internal CRC error checking, you could + still receive packets of the same length from another source. If this valid packet were to be used + to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet + is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet. + This CRC value is read by the receiver and used to check that the received CRC matches the supposed + sensor data in the packet. As an additional check there is some addressing information at the beginning + of the packet which is also checked for validity. Thus we can be relatively confident when reading the + received packet that its genuine and from this transmitter. The packet is built and sent in the + sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to + the packet. + + Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of + 8 seconds using the Atmel processor internal watchdog. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + Each sending sensor needs its own address and needs to know the address of the receiver its sending to. + This information is in the Settings.h file, see this section; + + ******* Setup node addressing here ! *************** + const uint8_t TXPacketType = Sensor1; //the packet type sent + const uint8_t TXDestination = 'B' //the destination address of the receiver. + const uint8_t TXSource = 1; //the source address, the address of this node. + + The TXDestination byte needs to match the RXDestination set in the receiver. The TXSource byte identifies + a particular sender node, and needs to be different for each sender. + + How often the sensor data is sent is controlled by this line in the Settings.h file; + + const uint8_t sleeps = 112; //number of 8 second sleeps, gap between transmissions + + In the above case 112 sleeps is approximatly 112 x 8 = 900seconds, 15 minutes. + + 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. + + 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 7.9uA. + + One of these transmitter programs is running on a long term test with a 150mAh battery, to see how long + the battery actually lasts, details at the link below; + + https://stuartsprojects.github.io/2020/02/20/just-how-long-can-a-sensor-battery-last.html + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include +#include "Settings.h" + +#include //watchdog timer library, integral to Arduino IDE +#include //get the library here; https://github.com/rocketscream/Low-Power + +SX127XLT LT; + +#include //get library here; https://github.com/Seeed-Studio/Grove_BME280 +BME280 bme280; //create an instance of the BME280 senosor +#include + +uint32_t TXpacketCount; +uint8_t TXPacketL; + +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t CRCvalue; //the CRC value of the packet data up to this point +uint8_t packetlength; //the packet length that was sent, checked against length received + + +void loop() +{ + TXpacketCount++; + Serial.print(TXpacketCount); //print the numbers of sends + Serial.print(F(" Sending > ")); + + readSensors(); //read the sensor values + printSensorValues(); //print the sensor values + + if (sendSensorPacket()) + { + Serial.println(F("SentOK")); + } + else + { + Serial.print(F("Send Error - IRQreg,")); + Serial.println(LT.readIrqStatus(), HEX); + } + + Serial.print(F("Sleeping zzzz")); + Serial.flush(); //make sure all serial output has gone + + //now put the sensor, LoRa device and processor to sleep + sleepBME280(); //sleep the BME280 + LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep. + sleep8seconds(sleeps); //sleep Atmel processor in units of approx 8 seconds + + //wait a bit ................ + Serial.println(F(" - Awake !!")); //the processor has woken up + Serial.println(); + normalBME280(); //BME280 sensor to normal mode +} + + +uint8_t sendSensorPacket() +{ + //The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the + //receiver uses the same variable types and sequence to read variables out of the receive buffer. + uint8_t len; + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + + LT.writeUint8(Sensor1); //this byte defines the packet type + LT.writeUint8(TXDestination); //destination address of the packet, the receivers address + LT.writeUint8(TXSource); //source address of this node + + /************************************************************************ + Highlighted section - this is where the actual sensor data is added to the packet + ************************************************************************/ + LT.writeFloat(temperature); //add the BME280 temperature + LT.writeFloat(pressure); //add the BME280 pressure + LT.writeUint16(humidity); //add the BME280 humididty + LT.writeUint16(voltage); //add the battery voltage + LT.writeUint8(statusbyte); //add the status byte + /************************************************************************/ + + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + addPacketErrorCheck(len); //add the additional CRC error checking to the packet end + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, (len + 2), 5000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void addPacketErrorCheck(uint8_t len) +{ + //calculate the CRC of packet sensor data + CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF); + + Serial.print(F("Calculated CRC value ")); + Serial.println(CRCvalue, HEX); + + LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data + LT.writeUint16(CRCvalue); //add the actual CRC value + LT.endWriteSXBuffer(); //close the packet +} + + +void readSensors() +{ + //read the sensor values into the global variables + temperature = bme280.getTemperature(); + pressure = bme280.getPressure(); + humidity = bme280.getHumidity(); + + if (BATVREADON >= 0) + { + voltage = readBatteryVoltage(); //read resistor divider across battery + } + else + { + voltage = 9999; //set a default value + } + statusbyte = 0x55; //manually set this for now, its a test +} + + +void printSensorValues() +{ + Serial.print(F("Temperature,")); + Serial.print(temperature, 1); + Serial.print(F("c,Pressure,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(" ")); + Serial.flush(); +} + + +void sleep8seconds(uint32_t sleeps) +{ + //uses the lowpower library + uint32_t index; + + for (index = 1; index <= sleeps; index++) + { + //sleep 8 seconds + LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); + } +} + + +void sleepBME280() +{ + //write this register value to BME280 to put it to sleep + writeBME280reg(BME280_REGISTER_CONTROL, B01111100); +} + + +void normalBME280() +{ + //write this register value to BME280 to put it to read mode + writeBME280reg(BME280_REGISTER_CONTROL, B01111111); +} + + +void writeBME280reg(byte reg, byte regvalue) +{ + //write a register value to the BME280 + Wire.beginTransmission((uint8_t) BME280_ADDRESS); + Wire.write((uint8_t)reg); + Wire.write((uint8_t)regvalue); + Wire.endTransmission(); +} + + +uint16_t readBatteryVoltage() +{ + //relies on 1V1 internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + byte index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + analogReference(INTERNAL); + temp = analogRead(BATTERYAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(BATTERYAD); + volts = volts + temp; + } + volts = ((volts / 5) * ADMultiplier) + DIODEMV; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + return volts; +} + + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + Serial.begin(9600); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, 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); + + if (!bme280.init()) + { + Serial.println("BME280 Device error!"); + led_Flash(100, 15); //long very fast speed flash indicates BME280 device error + } + + Serial.println(F("Transmitter ready")); + Serial.println(); + + readSensors(); //do an initial sensor read +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/17_Sensor_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/17_Sensor_Transmitter/Settings.h new file mode 100644 index 0000000..b01a732 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/17_Sensor_Transmitter/Settings.h @@ -0,0 +1,55 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +// ******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define BATVREADON 8 //when high turns on the resistor divider to measure voltage, -1 if not used +#define BATTERYAD A7 //Resitor divider for battery connected here, -1 if not used +#define ADMultiplier 10.00 //adjustment to convert AD value read into mV of battery voltage +#define DIODEMV 98 //mV voltage drop accross diode @ low idle current + + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +// ******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 14; //LoRa transmit power in dBm + +#define BME280_ADDRESS 0x76 //I2C bus address of BME280 +#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control + +const uint8_t sleeps = 112; //number of 8 second sleeps, gap between transmissions + + +// ******* Setup node addressing here ! *************** + +const uint8_t TXPacketType = Sensor1; //the packet type sent +const uint8_t TXDestination = 'B'; //the destination address of the receiver where the packet is being sent to +const uint8_t TXSource = 2; //the source address, the address of this node, where the packet came from + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino new file mode 100644 index 0000000..484b1c0 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino @@ -0,0 +1,361 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/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 - The program receives a LoRa packet without using a processor buffer, the LoRa devices + internal buffer is read direct for the received sensor data. + + The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity, + and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status + value at the end of the packet. + + When a packet is received,its printed and assuming the packet is validated, the sensor results are printed to the serial monitor + and screen. + + For the sensor data to be accepted as valid the folowing need to match; + + The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet. + The packet must start with a byte that matches the packet type sent, 'Sensor1' + The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node' + + In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid + packet is acted on and erroneous values displayed. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + With a standard Arduino Pro Mini and SSD1306 display the current consumption was 20.25mA with the + display and 16.6mA without the display. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +SX127XLT LT; + + +uint32_t RXpacketCount; //count of all packets received +uint32_t ValidPackets; //count of packets received with valid data +uint32_t RXpacketErrors; //count of all packets with errors received +bool packetisgood; + +uint8_t RXPacketL; //length of received packet +int16_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet + +uint8_t RXPacketType; +uint8_t RXDestination; +uint8_t RXSource; +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted + +//for SSD1306 +#include //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 +#define default_font u8x8_font_chroma48medium8_r + +//for SH1106 +//#include //get library here > https://github.com/olikraus/u8g2 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306 +//#define default_font u8x8_font_chroma48medium8_r + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want + } + + digitalWrite(LED1, LOW); + Serial.println(); +} + + +void packet_Received_OK() +{ + //a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from + //an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data + + uint8_t len; + uint8_t contenterrors; //keep a count of errors found in packet + + RXpacketCount++; + Serial.print(RXpacketCount); + Serial.print(F(",PacketsReceived,")); + + LT.startReadSXBuffer(0); + + RXPacketType = LT.readUint8(); //the packet type received + RXDestination = LT.readUint8(); //the destination address the packet was sent to + RXSource = LT.readUint8(); //the source address, where the packet came from + + /************************************************************************ + Highlighted section - this is where the actual sensor data is read from + the packet + ************************************************************************/ + temperature = LT.readFloat(); //the BME280 temperature value + pressure = LT.readFloat(); //the BME280 pressure value + humidity = LT.readUint16(); //the BME280 humididty value + voltage = LT.readUint16(); //the battery voltage value + statusbyte = LT.readUint8(); //a status byte, not currently used + /************************************************************************/ + + len = LT.endReadSXBuffer(); + + printreceptionDetails(); //print details of reception, RSSI etc + Serial.println(); + + contenterrors = checkPacketValid(len); //pass length of packet to check routine + + if (contenterrors == 0) + { + Serial.println(F(" Packet is good")); + ValidPackets++; + printSensorValues(); //print the sensor values + Serial.println(); + printPacketCounts(); //print count of valid packets and errors + displayscreen1(); + Serial.println(); + } + else + { + Serial.println(F(" Packet is not valid")); + RXpacketErrors++; + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +uint8_t checkPacketValid(uint8_t len) +{ + //this function checks if the packet is valid and will be displayed + + uint8_t errors = 0; + + if (RXPacketType != Sensor1) //is it a Sensor1 type packet + { + errors++; + } + + if (RXDestination != This_Node) //was the packet sent to this receiver node ? + { + errors++; + } + + if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ? + { + errors++; + } + + Serial.println(); + Serial.print(F("Error Check Count = ")); + Serial.print(errors); + return errors; +} + + +bool checkCRCvalue(uint8_t len) +{ + uint16_t CRCSensorData; + + CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data + + Serial.print(F("(CRC of Received sensor data ")); + Serial.print(CRCSensorData, HEX); + Serial.print(F(")" )); + + TXCRCvalue = ((LT.getByteSXBuffer(len + 1) << 8) + (LT.getByteSXBuffer(len))); + + Serial.print(F("(CRC transmitted ")); + Serial.print(TXCRCvalue, HEX); + Serial.print(F(")" )); + + if (TXCRCvalue != CRCSensorData) + { + Serial.print(F(" Sensor Data Not Valid")); + return false; + } + else + { + Serial.print(F(" Sensor Data is Valid")); + return true; + } + +} + + +void printSensorValues() +{ + Serial.print(F("Temp,")); + Serial.print(temperature, 1); + Serial.print(F("c,Press,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(",CRC,")); + Serial.print(TXCRCvalue, HEX); + Serial.flush(); +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void printPacketCounts() +{ + Serial.print(F("ValidPackets,")); + Serial.print(ValidPackets); + Serial.print(F(",Errors,")); + Serial.print(RXpacketErrors); +} + + +void displayscreen1() +{ + //show sensor data on display + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(F("Sensor ")); + disp.print(RXSource); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(temperature, 1); + disp.print(F("c")); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(pressure, 0); + disp.print(F("Pa")); + disp.clearLine(3); + disp.setCursor(0, 3); + disp.print(humidity); + disp.print(F("%")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(voltage); + disp.print(F("mV")); + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("ValidPkts ")); + disp.print(ValidPackets); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXpacketErrors++; + IRQStatus = LT.readIrqStatus(); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + Serial.println(); + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + + + + +void 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); + + disp.setCursor(0, 0); + disp.print(F("Check LoRa")); + disp.setCursor(0, 1); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + disp.print(F("LoRa OK")); + led_Flash(2, 125); + } + else + { + disp.print(F("Device error")); + Serial.println(F("Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/18_Sensor_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/18_Sensor_Receiver/Settings.h new file mode 100644 index 0000000..5414cdc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/18_Sensor_Receiver/Settings.h @@ -0,0 +1,45 @@ +/******************************************************************************************************* + 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 definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//*************** Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 2; //LoRa TX power + +#define packet_delay 1000 //mS delay between packets + +//******* Setup node addressing here ! *************** + +#define This_Node 'B' //this identifies this node, needs to match TXDestination on senders + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/39_LoRa_SX127x_Temperature_Read/39_LoRa_SX127x_Temperature_Read.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/39_LoRa_SX127x_Temperature_Read/39_LoRa_SX127x_Temperature_Read.ino new file mode 100644 index 0000000..812cb92 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sensor/39_LoRa_SX127x_Temperature_Read/39_LoRa_SX127x_Temperature_Read.ino @@ -0,0 +1,103 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ +/******************************************************************************************************* + Program Operation - This program reads the internal temperature sensor in the SX127X range of devices. + The temeprature sensor needs calibrating, so run a test, check what the error is (could be +\- 10C or + more) and calculate the value for the temperature_compensate constant. This constant will be different + for each individual device. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +//These are the pin definitions for one of the Tracker boards, be sure to change them to match +//your own setup. + +#define NSS 10 //SX127X device select +#define NRESET 9 //SX127X reset pin +#define LED1 8 //for on board LED, put high for on + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +#include +#include //load the appropriate library + +SX127XLT LT; + +const int8_t temperature_compensate = 0; //value, degrees centigrade, to add to read temperature for calibration. Can be negative + //this compensate value will be different for each LoRa device instance, so best to + //label and record values for each device + + +void loop() +{ + int8_t temperature_register; + LT.resetDevice(); + + temperature_register = LT.getDeviceTemperature(); + + Serial.print(F("Temperature Register Raw ")); + Serial.println(temperature_register); + Serial.print(F("Temperature Compensated ")); + Serial.print(temperature_register + temperature_compensate); + Serial.println(F("c")); + Serial.println(); + delay(2000); +} + + +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("39_LoRa_SX127x_Temperature_Read Starting")); + + + SPI.begin(); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, -1, -1, -1, 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 + } + } + + Serial.println(F("Temperature Sensor Ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/59_Play_Star_Wars_Tune.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/59_Play_Star_Wars_Tune.ino new file mode 100644 index 0000000..48661f2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/59_Play_Star_Wars_Tune.ino @@ -0,0 +1,175 @@ +/******************************************************************************************************* + 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 - 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. + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the settings file, frequencies etc +#include "pitches.h" //lookup file for notes + +SX127XLT 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("PlayTune> ")); + Serial.println(); + + playpart1(); + + playpart2(); + + LT.toneFM(NOTE_F4, 250, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 375, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_E5, 650, deviation, adjustfreq, TXpower); + + delay(500); + + playpart2(); + + LT.toneFM(NOTE_F4, 250, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 375, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 375, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower); + + LT.setMode(MODE_STDBY_RC); //turns off carrier + + Serial.println(); + + delay(2000); //have a delay between packets +} + + +void playpart1() +{ + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower); + + delay(500); + + LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F5, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower); + + delay(500); +} + + +void playpart2() +{ + LT.toneFM(NOTE_A5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 300, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A4, 150, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_A5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_GS5, 325, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_G5, 175, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_FS5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_FS5, 250, deviation, adjustfreq, TXpower); + + delay(500); + + LT.toneFM(NOTE_AS4, 250, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_DS5, 500, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_F5, 325, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_CS5, 175, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_AS4, 125, deviation, adjustfreq, TXpower); + LT.toneFM(NOTE_C5, 250, deviation, adjustfreq, TXpower); + + delay(500); +} + + +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("59_Play_Star_Wars_Tune Starting")); + + SPI.begin(); + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.setupDirect(Frequency, Offset); + Serial.print(F("Tone Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/Settings.h new file mode 100644 index 0000000..5fbdee8 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/Settings.h @@ -0,0 +1,32 @@ +/******************************************************************************************************* + 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 are not used by this particular sketch so they are set to -1 and not connected. + +#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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup Direct Modem Parameters Here ! *************** + +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes +const uint16_t deviation = 10000; //deviation in hz, 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 + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/pitches.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/pitches.h new file mode 100644 index 0000000..2f733c7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Silly/59_Play_Star_Wars_Tune/pitches.h @@ -0,0 +1,94 @@ +//File from https://www.arduino.cc/en/Tutorial/toneMelody +//This note table was originally written by Brett Hagman, on whose work the Arduino tone() command was based. + +#define NOTE_B0 31 +#define NOTE_C1 33 +#define NOTE_CS1 35 +#define NOTE_D1 37 +#define NOTE_DS1 39 +#define NOTE_E1 41 +#define NOTE_F1 44 +#define NOTE_FS1 46 +#define NOTE_G1 49 +#define NOTE_GS1 52 +#define NOTE_A1 55 +#define NOTE_AS1 58 +#define NOTE_B1 62 +#define NOTE_C2 65 +#define NOTE_CS2 69 +#define NOTE_D2 73 +#define NOTE_DS2 78 +#define NOTE_E2 82 +#define NOTE_F2 87 +#define NOTE_FS2 93 +#define NOTE_G2 98 +#define NOTE_GS2 104 +#define NOTE_A2 110 +#define NOTE_AS2 117 +#define NOTE_B2 123 +#define NOTE_C3 131 +#define NOTE_CS3 139 +#define NOTE_D3 147 +#define NOTE_DS3 156 +#define NOTE_E3 165 +#define NOTE_F3 175 +#define NOTE_FS3 185 +#define NOTE_G3 196 +#define NOTE_GS3 208 +#define NOTE_A3 220 +#define NOTE_AS3 233 +#define NOTE_B3 247 +#define NOTE_C4 262 +#define NOTE_CS4 277 +#define NOTE_D4 294 +#define NOTE_DS4 311 +#define NOTE_E4 330 +#define NOTE_F4 349 +#define NOTE_FS4 370 +#define NOTE_G4 392 +#define NOTE_GS4 415 +#define NOTE_A4 440 +#define NOTE_AS4 466 +#define NOTE_B4 494 +#define NOTE_C5 523 +#define NOTE_CS5 554 +#define NOTE_D5 587 +#define NOTE_DS5 622 +#define NOTE_E5 659 +#define NOTE_F5 698 +#define NOTE_FS5 740 +#define NOTE_G5 784 +#define NOTE_GS5 831 +#define NOTE_A5 880 +#define NOTE_AS5 932 +#define NOTE_B5 988 +#define NOTE_C6 1047 +#define NOTE_CS6 1109 +#define NOTE_D6 1175 +#define NOTE_DS6 1245 +#define NOTE_E6 1319 +#define NOTE_F6 1397 +#define NOTE_FS6 1480 +#define NOTE_G6 1568 +#define NOTE_GS6 1661 +#define NOTE_A6 1760 +#define NOTE_AS6 1865 +#define NOTE_B6 1976 +#define NOTE_C7 2093 +#define NOTE_CS7 2217 +#define NOTE_D7 2349 +#define NOTE_DS7 2489 +#define NOTE_E7 2637 +#define NOTE_F7 2794 +#define NOTE_FS7 2960 +#define NOTE_G7 3136 +#define NOTE_GS7 3322 +#define NOTE_A7 3520 +#define NOTE_AS7 3729 +#define NOTE_B7 3951 +#define NOTE_C8 4186 +#define NOTE_CS8 4435 +#define NOTE_D8 4699 +#define NOTE_DS8 4978 + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino new file mode 100644 index 0000000..b9c286d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino @@ -0,0 +1,242 @@ +/******************************************************************************************************* + 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 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. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //watchdog timer library, integral to Arduino IDE +#include +#include //get the library here; https://github.com/rocketscream/Low-Power + +#include +#include "Settings.h" + +SX127XLT LT; + +bool SendOK; +int8_t TestPower; +uint8_t TXPacketL; + + +void loop() +{ + digitalWrite(LED1, HIGH); + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket1> ")); + Serial.flush(); + + if (Send_Test_Packet1()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); + + LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep. + Serial.println(F("Sleeping zzzzz....")); + Serial.println(); + Serial.flush(); + digitalWrite(LED1, LOW); + + sleep1second(15); //goto sleep for 15 seconds + + Serial.println(F("Awake !")); + Serial.flush(); + digitalWrite(LED1, HIGH); + LT.wake(); + + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket2> ")); + Serial.flush(); + + if (Send_Test_Packet2()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); +} + + +void sleep1second(uint32_t sleeps) +{ + //uses the lowpower library + uint32_t index; + + for (index = 1; index <= sleeps; index++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep in 1 second steps + } +} + + +void packet_is_OK() +{ + Serial.print(F(" ")); + Serial.print(TXPacketL); + Serial.print(F(" Bytes SentOK")); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error +} + + +bool Send_Test_Packet1() +{ + uint8_t bufffersize; + + uint8_t buff[] = "Before Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +bool Send_Test_Packet2() +{ + uint8_t bufffersize; + + uint8_t buff[] = "After Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("5_LoRa_TX_Sleep_Timed_Wakeup_Atmel Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.print(F("Transmitter ready - TXBUFFER_SIZE ")); + Serial.println(TXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h new file mode 100644 index 0000000..cdc4325 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define TXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/62_LoRa_Wake_on_RX_Atmel.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/62_LoRa_Wake_on_RX_Atmel.ino new file mode 100644 index 0000000..ad6fe6a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/62_LoRa_Wake_on_RX_Atmel.ino @@ -0,0 +1,224 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 19/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 - 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 setup to recieve 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 13.07mA. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include +#include +#include "Settings.h" + +#include +#include +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +#include + +SX127XLT LT; + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create a buffer for the received packet + +uint8_t RXPacketL; //stores length of packet received +int16_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, NO_WAIT); //setup LoRa device for receive with no timeout + + Serial.println(F("Waiting for RX - Sleeping")); + Serial.flush(); + + attachInterrupt(digitalPinToInterrupt(DIO0), wakeUp, HIGH); + + atmelSleepPermanent(); //sleep the processor + + detachInterrupt(digitalPinToInterrupt(DIO0)); + + //something has happened ? + Serial.println(F("Awake")); + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + + digitalWrite(BUZZER, LOW); + } + Serial.println(); +} + + +void wakeUp() +{ + //handler for the interrupt +} + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); + RXpacketCount++; + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + Serial.print(F("Packet> ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); + Serial.print(F(" 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); + Serial.println(); + led_Flash(2, 125); //LED flash for approx 10 seconds +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.println(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(); + Serial.println(); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("62_LoRa_Wake_on_RX_Atmel Starting")); + + if (BUZZER > 0) + { + pinMode(BUZZER, OUTPUT); + digitalWrite(BUZZER, HIGH); + delay(50); + digitalWrite(BUZZER, LOW); + } + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, 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.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/Settings.h new file mode 100644 index 0000000..cd4bf39 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/62_LoRa_Wake_on_RX_Atmel/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 19/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. +*******************************************************************************************************/ + +//******* 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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define BUZZER -1 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size +const uint16_t packetCRCcheck = 0x3F83; //CRC to check RX packet for +const uint8_t packetCRClengthcheck = 23; //packet length to check for + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/6_LoRa_RX_and_Sleep_Atmel.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/6_LoRa_RX_and_Sleep_Atmel.ino new file mode 100644 index 0000000..37a4f8a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/6_LoRa_RX_and_Sleep_Atmel.ino @@ -0,0 +1,247 @@ +/******************************************************************************************************* + 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 - 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 setup to recieve 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. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +#include +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +SX127XLT LT; + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create a buffer for the received packet + +uint8_t RXPacketL; //stores length of packet received +int16_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio of received packet + + +void loop() +{ + LT.fillSXBuffer(0, 13, '#'); //make sure the first part of FIFO is cleared, so we can tell its a fresh packet + + RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 0, NO_WAIT); //setup LoRa device for receive and continue + + //receive is setup + + Serial.println(F("Going to sleep zzzz")); + Serial.println(); + Serial.flush(); //make sure all serial has gone, it can wake up processor + + sleep_permanent(); //put processor to sleep, with LoRa device listening, should + //wakeup when DIO0 goes high + + Serial.println(F("Awake !!!!")); + digitalWrite(LED1, HIGH); //something has happened ? + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + + digitalWrite(BUZZER, LOW); + } + + Serial.println(); +} + + +void sleep_permanent() +{ + LT.clearIrqStatus(IRQ_RADIO_ALL); //ensure the DIO0 low is cleared, otherwise there could be an immediate wakeup + attachPCINT(digitalPinToPCINT(DIO0), wakeUp, HIGH); //This is a hardware interrupt, the LoRa device is set for DIOo goes high on RXdone + ADCSRA = 0; //disable ADC + set_sleep_mode (SLEEP_MODE_PWR_DOWN); + noInterrupts (); //timed sequence follows + sleep_enable(); + + 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(); + + detachPCINT(digitalPinToPCINT(DIO0)); +} + + +void wakeUp() +{ + //handler for the interrupt +} + + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); + RXpacketCount++; + + RXPacketL = LT.readPacket(RXBUFFER, RXBUFFER_SIZE); //now read in the received packet to the RX buffer + + Serial.print(F("Packet> ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); + Serial.print(F(" 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(); //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); + LT.printIrqStatus(); + } +} + + +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("6_LoRa_RX_and_Sleep_Atmel Starting")); + Serial.println(); + + if (BUZZER > 0) + { + pinMode(BUZZER, OUTPUT); + digitalWrite(BUZZER, HIGH); + delay(50); + digitalWrite(BUZZER, LOW); + } + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, 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(); + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/Settings.h new file mode 100644 index 0000000..d2ce90e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/6_LoRa_RX_and_Sleep_Atmel/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define BUZZER 4 //pin for buzzer, on when logic high + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel.ino new file mode 100644 index 0000000..8560939 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel.ino @@ -0,0 +1,260 @@ +/******************************************************************************************************* + 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 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 an bare bones ATmega328P board, the curent in sleep mode was 2.4uA. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include + +#include +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +#include +#include "Settings.h" + +SX127XLT LT; + +uint8_t TXPacketL; + + +void loop() +{ + digitalWrite(LED1, HIGH); + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket1> ")); + Serial.flush(); + + if (Send_Test_Packet1()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); + + LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep. + Serial.println(F("Sleeping zzzzz....")); + Serial.println(); + Serial.flush(); + digitalWrite(LED1, LOW); + + sleep_permanent(); //goto sleep till woken up by switch press + + Serial.println(F("Awake !")); + Serial.flush(); + digitalWrite(LED1, HIGH); + LT.wake(); + + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket2> ")); + Serial.flush(); + + if (Send_Test_Packet2()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); +} + + +void sleep_permanent() +{ + attachPCINT(digitalPinToPCINT(SWITCH1), wakeUp, LOW); //This is a hardware interrupt + + 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(); + + detachPCINT(digitalPinToPCINT(SWITCH1)); +} + + +void wakeUp() +{ + //handler for the interrupt +} + + +void packet_is_OK() +{ + Serial.print(F(" ")); + Serial.print(TXPacketL); + Serial.print(F(" Bytes SentOK")); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error +} + + +bool Send_Test_Packet1() +{ + uint8_t bufffersize; + + uint8_t buff[] = "Before Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +bool Send_Test_Packet2() +{ + uint8_t bufffersize; + + uint8_t buff[] = "After Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + pinMode(SWITCH1, INPUT_PULLUP); //setup switch pin, 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("7_LoRa_TX_Sleep_Switch_Wakeup_Atmel Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, 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.print(F("Transmitter ready - TXBUFFER_SIZE ")); + Serial.println(TXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel/Settings.h new file mode 100644 index 0000000..b358b97 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/7_LoRa_TX_Sleep_Switch_Wakeup_Atmel/Settings.h @@ -0,0 +1,43 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER may not be in used by this sketch so they do not need to be +//connected and should be included and be set to -1. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 8 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1 +#define SWITCH1 2 //switch pin, used to wake processor up + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto + +const int8_t TXpower = 2; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define TXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/Atmel Watchdog Sleep Time.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/Atmel Watchdog Sleep Time.jpg new file mode 100644 index 0000000..04ec92d Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/Atmel Watchdog Sleep Time.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/Bare_Bones_Arduino_ATMega328.pdf b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/Bare_Bones_Arduino_ATMega328.pdf new file mode 100644 index 0000000..57851e2 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/Sleep/Bare_Bones_Arduino_ATMega328.pdf differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino new file mode 100644 index 0000000..71b4a4c --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino @@ -0,0 +1,419 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 28/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 an example of a basic GPS tracker. The program reads the GPS, + waits for an updated fix and transmits location and altitude, number of satellites in view, the HDOP + value, the fix time of the GPS and the battery voltage. This transmitter can be also be used to + investigate GPS performance. At startup there should be a couple of seconds of recognisable text from + the GPS printed to the serial monitor. If you see garbage or funny characters its likley the GPS baud + rate is wrong. If the transmitter is turned on from cold, the receiver will pick up the cold fix time, + which is an indication of GPS performance. The GPS will be powered on for around 4 seconds before the + timing of the fix starts. Outside with a good view of the sky most GPSs should produce a fix in around + 45 seconds. The number of satellites and HDOP are good indications to how well a GPS is working. + + The program writes direct to the LoRa devices internal buffer, no memory buffer is used. + + The LoRa settings are configured in the Settings.h file. + + The program has the option of using a pin to control the power to the GPS (GPSPOWER), if the GPS module + or board being used has this feature. To not use this feature set the define for GPSPOWER in the + Settings.h file to '#define GPSPOWER -1'. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic + levels. + + 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 115200. +*******************************************************************************************************/ + +#define Program_Version "V1.2" +#define authorname "Stuart Robinson" + +#include +#include + +#include "Settings.h" +#include + +SX127XLT LT; + +#include //get library here > http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USESOFTSERIALGPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#endif + +#ifdef USEHARDWARESERIALGPS +#define GPSserial HARDWARESERIALPORT +#endif + + +uint8_t TXStatus = 0; //used to store current status flag bits of Tracker transmitter (TX) +uint8_t TXPacketL; //length of LoRa packet (TX) +float TXLat; //Latitude from GPS on Tracker transmitter (TX) +float TXLon; //Longitude from GPS on Tracker transmitter (TX) +float TXAlt; //Altitude from GPS on Tracker transmitter (TX) +uint8_t TXSats; //number of GPS satellites seen (TX) +uint32_t TXHdop; //HDOP from GPS on Tracker transmitter (TX) +uint16_t TXVolts; //Volts (battery) level on Tracker transmitter (TX) +uint32_t TXGPSFixTime; //GPS fix time in hot fix mode of GPS on Tracker transmitter (TX) +uint32_t TXPacketCount, TXErrorsCount; //keep count of OK packets and send errors + + +void loop() +{ + + if (gpsWaitFix(WaitGPSFixSeconds)) + { + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); + Serial.println(); + Serial.print(F("Waiting ")); + Serial.print(Sleepsecs); + Serial.println(F("s")); + delay(Sleepsecs * 1000); //this sleep is used to set overall transmission cycle time + } + else + { + send_Command(NoFix); //send notification of no GPS fix. + } +} + + +bool gpsWaitFix(uint32_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + uint32_t startmS, waitmS, GPSonTime; + bool GPSfix = false; + float tempfloat; + uint8_t GPSchar; + + GPSonTime = millis(); + GPSserial.begin(9600); //start GPSserial + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.println(F("s")); + + 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.date.isUpdated()) + { + GPSfix = true; + Serial.println(); + Serial.print(F("Have GPS Fix ")); + TXGPSFixTime = millis() - GPSonTime; + Serial.print(TXGPSFixTime); + Serial.println(F("mS")); + + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = gps.altitude.meters(); + TXSats = gps.satellites.value(); + TXHdop = gps.hdop.value(); + tempfloat = ( (float) TXHdop / 100); + + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempfloat, 2); + Serial.println(); + + break; //exit while loop reading GPS + } + } + + //if here then there has either been a fix or no fix and a timeout + + if (GPSfix) + { + setStatusByte(GPSFix, 1); //set status bit to flag a GPS fix + } + else + { + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(); + Serial.println(F("Timeout - No GPSFix")); + Serial.println(); + GPSfix = false; + } + + GPSserial.end(); //serial RX interrupts interfere with SPI, so stop GPSserial + return GPSfix; +} + + +void sendLocation(float Lat, float Lon, float Alt, uint32_t Hdop, uint32_t fixtime) +{ + uint8_t len; + uint16_t IRQStatus; + + Serial.print(F("Send Location")); + + TXVolts = readSupplyVoltage(); //get the latest supply\battery volts + + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationPacket); //identify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeFloat(Alt); //add altitude + LT.writeUint8(TXSats); //add number of satellites + LT.writeUint32(Hdop); //add hdop + LT.writeUint8(TXStatus); //add tracker status + LT.writeUint32(fixtime); //add GPS fix time in mS + LT.writeUint16(TXVolts); //add tracker supply volts + LT.writeUint32(millis()); //add uptime in mS + len = LT.endWriteSXBuffer(); //close buffer write + + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); + + if (TXPacketL) + { + TXPacketCount++; + Serial.println(F(" - Done ")); + Serial.print(F("SentOK,")); + Serial.print(TXPacketCount); + Serial.print(F(",Errors,")); + Serial.println(TXErrorsCount); + } + else + { + //if here there was an error transmitting packet + TXErrorsCount++; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + Serial.println(); + } +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void send_Command(char cmd) +{ + bool SendOK; + uint8_t len; + + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + + LT.startWriteSXBuffer(0); + LT.writeUint8(cmd); //packet addressing used indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent to + LT.writeUint8(ThisNode); //where is packet from + LT.writeUint16(TXVolts); + len = LT.endWriteSXBuffer(); + + digitalWrite(LED1, HIGH); + SendOK = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); //timeout set at 10 seconds + digitalWrite(LED1, LOW); + + if (SendOK) + { + Serial.println(F(" - Done")); + } + else + { + Serial.println(F(" - Error")); + } +} + + +uint16_t readSupplyVoltage() +{ + //relies on 1V internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t voltage = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + analogReference(INTERNAL); + temp = analogRead(SupplyAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(SupplyAD); + voltage = voltage + temp; + } + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + + voltage = ((voltage / 5) * ADMultiplier) + DIODEMV; + return voltage; +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void GPSTest() +{ + uint32_t startmS; + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < 2000) //allows for millis() overflow + { + if (GPSserial.available() > 0) + { + Serial.write(GPSserial.read()); + } + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +void setup() +{ + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + GPSON(); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(115200); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("23_GPS_Tracker_Transmitter Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + + TXVolts = readSupplyVoltage(); + + Serial.print(F("Supply ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + + send_Command(PowerUp); //send power up command, includes supply mV + + Serial.println(F("Startup GPS check")); + GPSserial.begin(9600); + GPSTest(); + Serial.println(); + Serial.println(); + + Serial.println(F("Wait for first GPS fix")); + gpsWaitFix(WaitFirstGPSFixSeconds); + + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); +} diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h new file mode 100644 index 0000000..7bff166 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h @@ -0,0 +1,65 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done + +#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 + +#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 //On board LED, high for on +#define SupplyAD A7 //pin for reading supply\battery voltage +#define BATVREADON 8 //turns on battery resistor divider, high for on, -1 if not used + +const float ADMultiplier = 10.0; //multiplier for supply volts calculation +#define DIODEMV 98 //mV voltage drop accross diode at approx 8mA + + +#define LORA_DEVICE DEVICE_SX1278 //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_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa TX power + +#define ThisNode 'T' //a character that identifies this tracker + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define USESOFTSERIALGPS //if your using software serial for the GPS, enable this define +//#define USEHARDWARESERIALGPS //if your using hardware serial for the GPS, enable this define +//#define HARDWARESERIALPORT Serial2 //if your using hardware serial for the GPS, define the port here + + +#define GPSBaud 9600 //GPS Baud rate + +#define WaitGPSFixSeconds 30 //time in seconds to wait for a new GPS fix +#define WaitFirstGPSFixSeconds 120 //time to seconds to wait for the first GPS fix at startup +#define Sleepsecs 15 //seconds between transmissions, this delay is used to set overall transmission cycle time + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino new file mode 100644 index 0000000..b892edd --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino @@ -0,0 +1,323 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 28/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 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. + + Serial monitor baud rate is set at 115200. +*******************************************************************************************************/ + +#define Program_Version "V1.2" + +#include +#include + +SX127XLT LT; + +#include "Settings.h" +#include + + +uint32_t RXpacketCount; //count of received packets + +uint8_t RXPacketL; //length of received packet +int16_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //A status byte +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint8_t TXSats; //number of sattelites in use +uint32_t TXupTimemS; //up time of TX in mS + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort + + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + + Serial.println(); +} + + +void readPacketAddressing() +{ + //the transmitter is using packet addressing, so read in the details + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + float tempHdop; + + RXpacketCount++; + Serial.print(F("Packet OK > ")); + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from FIFO, not used + LT.readUint8(); //read byte from FIFO, not used + LT.readUint8(); //read byte from FIFO, not used + TXVolts = LT.readUint16(); + LT.endReadSXBuffer(); + Serial.print(F("Tracker transmitter powerup - battery ")); + Serial.print(TXVolts); + Serial.print(F("mV")); + } + + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readFloat(); + TXSats = LT.readUint8(); + TXHdop = LT.readUint32(); + TXStatus = LT.readUint8(); + TXGPSFixTime = LT.readUint32(); + TXVolts = LT.readUint16(); + TXupTimemS = LT.readUint32(); + RXPacketL = LT.endReadSXBuffer(); + + tempHdop = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F("m,")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempHdop, 2); + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS/1000)); + Serial.print(F("s,")); + printpacketDetails(); + return; + } + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + tempHdop = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + printpacketDetails(); + return; + } + + if (PacketType == NoFix) + { + Serial.print(F("No Tracker GPS fix ")); + printpacketDetails(); + return; + } + +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("PacketError,RSSI")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + 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(115200); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("24_GPS_Tracker_Receiver Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + Serial.println(F("BUZZER Enabled")); + } + else + { + Serial.println(F("BUZZER Not Enabled")); + } + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, 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(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h new file mode 100644 index 0000000..8f20a16 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h @@ -0,0 +1,35 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 22/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. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done + +#define LED1 8 //On board LED, high for on +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used + +#define DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino new file mode 100644 index 0000000..c85ec22 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino @@ -0,0 +1,634 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 28/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 an example of a functional GPS tracker receiver using lora. +It is capable of picking up the trackers location packets from many kilometres away with only basic antennas. + +The program receives the location packets from the remote tracker transmitter and writes them on an OLED +display and also prints the information to the Arduino IDE serial monitor. The program can read a locally +attached GPS and when that has a fix, will display the distance and direction to the remote tracker. + +The program writes direct to the lora devices internal buffer, no memory buffer is used. The lora settings +are configured in the Settings.h file. + +The receiver recognises two types of tracker packet, the one from the matching program '23_GPS_Tracker_Transmitter' +(LocationPacket, 27 bytes) which causes these fields to be printed to the serial monitor; + +Latitude, Longitude, Altitude, Satellites, HDOP, TrackerStatusByte, GPS Fixtime, Battery mV, Distance, Direction, +Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, PacketLength, IRQRegister. + +This is a long packet which at the long range LoRa settings takes just over 3 seconds to transmit. + +The receiver also recognises a much shorter location only packet (LocationBinaryPacket, 11 bytes) and when +received this is printed to the serial monitor; + +Latitude, Longitude, Altitude, TrackerStatusByte, Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, +PacketLength, IRQRegister. + +Most of the tracker information (for both types of packet) is shown on the OLED display. If there has been a +tracker transmitter GPS fix the number\identifier of that tracker is shown on row 0 right of screen and if there +is a recent local (receiver) GPS fix an 'R' is displayed row 1 right of screen. + +When the tracker transmitter starts up or is reset its sends a power up message containing the battery voltage +which is shown on the OLED and printer to the serial monitor. + +The program has the option of using a pin to control the power to the GPS, if the GPS module being used has this +feature. To use the option change the define in Settings.h; + +'#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE defines to +the appropriate logic levels. + +The program by default uses software serial to read the GPS, you can use hardware serial by commenting out this +line in the Settings.h file; + +#define USE_SOFTSERIAL_GPS + +And then defining the hardware serial port you are using, which defaults to Serial1. + +Serial monitor baud rate is set at 115200. +*******************************************************************************************************/ + + +#define Program_Version "V1.2" + +#include +#include +SX127XLT LT; + +#include "Settings.h" +#include + +#include //https://github.com/olikraus/u8g2 +//U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 + + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USESOFTSERIALGPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#endif + +#ifdef USEHARDWARESERIALGPS +#define GPSserial HARDWARESERIALPORT +#endif + + +uint32_t RXpacketCount; //count of received packets +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet +int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //status byte from tracker transmitter +uint8_t TXSats; //number of sattelites in use +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +float RXLat; //latitude +float RXLon; //longitude +float RXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint16_t RXVolts; //supply\battery voltage +float TXdistance; //calculated distance to tracker +uint16_t TXdirection; //calculated direction to tracker +uint16_t RXerrors; +uint32_t TXupTimemS; //up time of TX in mS + +uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix + +bool TXLocation = false; //set to true when at least one tracker location packet has been received +bool RXGPSfix = false; //set to true if the local GPS has a recent fix + +uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); //returns 0 if packet error of some sort + + while (!digitalRead(DIO0)) + { + readGPS(); //If the DIO pin is low, no packet arrived, so read the GPS + } + + //something has happened in receiver + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readRXPacketL(); + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + Serial.println(); +} + + +void readGPS() +{ + if (GPSserial.available() > 0) + { + gps.encode(GPSserial.read()); + } + + if ( (uint32_t) (millis() - LastRXGPSfixCheck) > NoRXGPSfixms) + { + RXGPSfix = false; + LastRXGPSfixCheck = millis(); + dispscreen1(); + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated()) + { + RXGPSfix = true; + RXLat = gps.location.lat(); + RXLon = gps.location.lng(); + RXAlt = gps.altitude.meters(); + printRXLocation(); + LastRXGPSfixCheck = millis(); + + if ( FixCount == 1) //update screen when FIX count counts down from DisplayRate to 1 + { + FixCount = DisplayRate; + dispscreen1(); + } + FixCount--; + } +} + + +bool readTXStatus(byte bitnum) +{ + return bitRead(TXStatus, bitnum); +} + + +void printRXLocation() +{ + Serial.print(F("LocalGPS ")); + Serial.print(RXLat, 5); + Serial.print(F(",")); + Serial.print(RXLon, 5); + Serial.print(F(",")); + Serial.print(RXAlt, 1); + Serial.println(); +} + + +void readPacketAddressing() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + //uint16_t IRQStatus; + float tempfloat; + + RXpacketCount++; + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + TXVolts = LT.readUint16(); //read tracker transmitter voltage + LT.endReadSXBuffer(); + Serial.print(F("Tracker Powerup - Battery ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + dispscreen2(); + } + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + TXLocation = true; + LT.startReadSXBuffer(0); //start the read of received packet + PacketType = LT.readUint8(); //read in the PacketType + Destination = LT.readUint8(); //read in the Packet destination address + Source = LT.readUint8(); //read in the Packet source address + TXLat = LT.readFloat(); //read in the tracker latitude + TXLon = LT.readFloat(); //read in the tracker longitude + TXAlt = LT.readFloat(); //read in the tracker altitude + TXSats = LT.readUint8(); //read in the satellites in use by tracker GPS + TXHdop = LT.readUint32(); //read in the HDOP of tracker GPS + TXStatus = LT.readUint8(); //read in the tracker status byte + TXGPSFixTime = LT.readUint32(); //read in the last fix time of tracker GPS + TXVolts = LT.readUint16(); //read in the tracker supply\battery volts + TXupTimemS = LT.readUint32(); //read in the TX uptime in mS + RXPacketL = LT.endReadSXBuffer(); //end the read of received packet + + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + + tempfloat = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + Serial.print(tempfloat, 2); + + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS/1000)); + Serial.print(F("s,")); + + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); //and show the packet detail it on screen + return; + } + + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + TXLocation = true; + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); + return; + } +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + RXerrors++; + Serial.print(F("PacketError,RSSI")); + + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void dispscreen1() +{ + //show received packet data on display + float tempfloat; + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(TXLat, 5); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(TXLon, 5); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(TXAlt,0); + disp.print(F("m")); + disp.clearLine(3); + disp.setCursor(0, 3); + + disp.print(F("RSSI ")); + disp.print(PacketRSSI); + disp.print(F("dBm")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(F("SNR ")); + + if (PacketSNR > 0) + { + disp.print(F("+")); + } + + if (PacketSNR == 0) + { + disp.print(F(" ")); + } + + if (PacketSNR < 0) + { + disp.print(F("-")); + } + + disp.print(PacketSNR); + disp.print(F("dB")); + + if (PacketType == LocationPacket) + { + disp.clearLine(5); + disp.setCursor(0, 5); + tempfloat = ((float) TXVolts / 1000); + disp.print(F("Batt ")); + disp.print(tempfloat, 2); + disp.print(F("v")); + } + + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); + + disp.clearLine(7); + + if (RXGPSfix) + { + disp.setCursor(15, 1); + disp.print(F("R")); + } + else + { + disp.setCursor(15, 1); + disp.print(F(" ")); + disp.setCursor(0, 7); + disp.print(F("No Local Fix")); + } + + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(TXdistance, 0); + disp.print(F("m ")); + disp.print(TXdirection); + disp.print(F("d")); + } + + if (readTXStatus(GPSFix)) + { + disp.setCursor(15, 0); + disp.write(Source); + } + +} + + +void dispscreen2() +{ + //show tracker powerup data on display + float tempfloat; + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Tracker Powerup")); + disp.setCursor(0, 1); + disp.print(F("Battery ")); + tempfloat = ((float) TXVolts / 1000); + disp.print(tempfloat, 2); + disp.print(F("v")); +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void GPSTest() +{ + uint32_t startmS; + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < 2000) //allows for millis() overflow + { + if (GPSserial.available() > 0) + { + Serial.write(GPSserial.read()); + } + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +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(115200); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("25_GPS_Tracker_Receiver_With_Display_and_GPS Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + } + + SPI.begin(); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + Serial.print(F("Checking LoRa device - ")); //Initialize LoRa + disp.setCursor(0, 0); + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("Receiver ready")); + disp.print(F("Receiver ready")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No LoRa device responding")); + disp.print(F("No LoRa device")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + Serial.println(); + Serial.println(F("Startup GPS check")); + + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + } + + GPSON(); + GPSserial.begin(GPSBaud); + GPSTest(); + + Serial.println(); + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h new file mode 100644 index 0000000..c393b14 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h @@ -0,0 +1,59 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be +//connected and should be set to -1. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define LED1 8 //On board LED, high for on +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used + +#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 4 //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 + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 434000000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define USESOFTSERIALGPS //if your using software serial for the GPS, enable this define +//#define USEHARDWARESERIALGPS //if your using hardware serial for the GPS, enable this define +//#define HARDWARESERIALPORT Serial2 //if your using hardware serial for the GPS, define the port here + +#define GPSBaud 9600 //GPS Baud rate + +#define NoRXGPSfixms 15000 //max number of mS to allow before no local GPS fix flagged +#define DisplayRate 7 //when working OK the GPS will get a new fix every second or so + //this rate defines how often the display should be updated + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino new file mode 100644 index 0000000..60f8fff --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino @@ -0,0 +1,173 @@ +/******************************************************************************************************* + 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 will receive a lora packet and relay (re-transmit) it. The receiving + and transmitting can use different frequencies and lora settings, although in this example they are + the same. The receiving and transmitting settings are in the 'Settings.h' file. If the relay is located + in an advantageous position, for instance on top of a tall tree, building or in an radio controlled model + then the range at which trackers or nodes on the ground can be received is considerably increased. + In these circumstances the relay may listen at a long range setting using SF12 for example and then + re-transmit back to the ground at SF7. + + For an example of the use of such a program see this report; + + https://stuartsprojects.github.io/2016/08/15/how-to-search-500-square-kilometres-in-10-minutes.html + + Serial monitor baud rate is set at 9600. + +*******************************************************************************************************/ + + +#include +#include +#include "Settings.h" + +SX127XLT LT; + +uint8_t RXPacketL, TXPacketL; +int8_t PacketRSSI, PacketSNR; +uint16_t RXPacketErrors; + + +void loop() +{ + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation); + + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + if (BUZZER > 0) //turn buzzer on + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + PacketSNR = LT.readPacketSNR(); //read the received SNR value + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + Serial.println(); +} + + +void packet_is_OK() +{ + //a packet has been received, so change to relay settings and transmit buffer + + Serial.print(F("PacketOK ")); + printreceptionDetails(); + delay(packet_delay / 2); + digitalWrite(LED1, LOW); + delay(packet_delay / 2); + + Serial.print(F(" Retransmit")); + LT.setupLoRa(RelayFrequency, RelayOffset, RelaySpreadingFactor, RelayBandwidth, RelayCodeRate, RelayOptimisation); + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, RXPacketL, 10000, TXpower, WAIT_TX); + Serial.print(F(" - Done")); + digitalWrite(LED1, LOW); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXPacketErrors++; + IRQStatus = LT.readIrqStatus(); + + led_Flash(5, 50); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + } +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void led_Flash(uint16_t flashdelay, uint16_t flashes) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + + delay(flashdelay); + digitalWrite(LED1, HIGH); + delay(flashdelay); + digitalWrite(LED1, LOW); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + Serial.begin(9600); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, 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.print(F("ListenSettings,")); + LT.printModemSettings(); + Serial.println(); + LT.setupLoRa(RelayFrequency, RelayOffset, RelaySpreadingFactor, RelayBandwidth, RelayCodeRate, RelayOptimisation); + Serial.print(F("RelaySettings,")); + LT.printModemSettings(); + Serial.println(); + Serial.println(F("Relay Ready")); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/38_lora_Relay/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/38_lora_Relay/Settings.h new file mode 100644 index 0000000..7f60a2f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/38_lora_Relay/Settings.h @@ -0,0 +1,51 @@ +/******************************************************************************************************* + 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. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, 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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 +#define LED1 8 //On board LED, high for on +#define BUZZER -1 //normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa receiving 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 + +//LoRa relay (re-transmitting) parameters +const uint32_t RelayFrequency = 434000000; //frequency of transmissions +const uint32_t RelayOffset = 0; //offset frequency for calibration purposes + +const uint8_t RelayBandwidth = LORA_BW_125; //LoRa bandwidth +const uint8_t RelaySpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t RelayCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t RelayOptimisation = LDRO_AUTO; //low data rate optimisation setting + + +const int8_t TXpower = 10; //LoRa TX power in dBm + +#define packet_delay 500 //mS delay before received packet transmitted + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/67_Balloon_Tracker_Transmitter/67_Balloon_Tracker_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/67_Balloon_Tracker_Transmitter/67_Balloon_Tracker_Transmitter.ino new file mode 100644 index 0000000..4db6767 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/67_Balloon_Tracker_Transmitter/67_Balloon_Tracker_Transmitter.ino @@ -0,0 +1,807 @@ +/****************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 28/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 tracker intended for use as a high altitude balloon (HAB) tracker. The + program sends out a standard format payload with LoRa that is compatible with the HABHUB online tracking + system. + + The HAB payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,Status,Errors,TXGPSfixms,Checksum + Field 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + + The LoRa and frequency settings can be changed in the Settings.h file. There is the option of sending + out a much shorter Search mode binary location only payload. This is intended for ground based searching + and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker + mode used by the HAB payload. There is also the option of sending the HAB payload in FSK RTTY format, + see the Settings.h file for all the options. FSK RTTY gets sent at the same frequency as the Tracker mode + HAB packet. The LT.transmitFSKRTTY() function sends at 1 start bit, 7 data bits, no parity and 2 stop bits. + For full control of the FSK RTTY setting you can use the following alternative function; + + LT.transmitFSKRTTY(chartosend, databits, stopbits, parity, baudPerioduS, pin) + + There is a matching Balloon Tracker Receiver program which writes received data to the Serial monitor as well + as a small OLED display. + + In the Settings.h file you can set the configuration for either a Ublox GPS or a Quectel L70\L80. The GPSs + are configured for high altitude balloon mode. + + It is strongly recommended that a FRAM option is fitted for this transmitter. The sequence, resets and error + nembers are stred in non-volatile memory. This defaults to EEPROM which has a limited endurance of only + 100,000 writes, so in theory the limt is reached after the transmission of 100,000 hab packets. The use of + a FRAM will extend the life of the tracker to circa 100,000,000,000,000 transmissions. + + Changes: + 240420 - Change to work with Easy Pro Mini style modules + 300420 - Improve error detection for UBLOX GPS library + + ToDo: + + Serial monitor baud rate is set at 115200 +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include + +#include //include the appropriate library + +SX127XLT LT; //create a library class instance called LT + +#include "Settings.h" +#include "ProgramLT_Definitions.h" + +//************************************************************************************************** +// HAB tracker data - these are the variables transmitted in payload +//************************************************************************************************** +uint32_t TXSequence; //sequence number of payload +uint8_t TXHours; //Hours +uint8_t TXMinutes; //Minutes +uint8_t TXSeconds; //Seconds +float TXLat; //latitude from GPS +float TXLon; //longitude from GPS +uint16_t TXAlt; //altitude from GPS +uint8_t TXSatellites; //satellites used by GPS +uint16_t TXVolts; //measured tracker supply volts +int8_t TXTemperature; //measured temperature +uint16_t TXResets; //number of tracker resets +uint8_t TXStatus = 0; //used to store current status flag bits +uint16_t TXErrors; //number of tracker Errors +uint32_t TXGPSfixms; //fix time of GPS +//************************************************************************************************** + +uint8_t TXPacketL; //length of LoRa packet sent +uint8_t TXBUFFER[TXBUFFER_SIZE]; //buffer for packet to send + +#include Memory_Library + +#include + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USESOFTSERIALGPS +//#include //https://github.com/SlashDevin/NeoSWSerial +//NeoSWSerial GPSserial(RXpin, TXpin); //The NeoSWSerial library is an option to use and is more relaible + //at GPS init than software serial +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#endif + +#ifdef USEHARDWARESERIALGPS +#define GPSserial HARDWARESERIALPORT +#endif + +#ifdef USEI2CGPS +#include +#endif + + +#include GPS_Library //include previously defined GPS Library + +#include //get library here > https://github.com/PaulStoffregen/OneWire +OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library +#include //get library here > https://github.com/milesburton/Arduino-TXTemperature-Control-Library +DallasTemperature sensor(&oneWire); //create instance of dallas library + +uint32_t GPSstartms; //start time waiting for GPS to get a fix + + +void loop() +{ + Serial.println(F("Start Loop")); + + GPSstartms = millis(); + + if (!gpsWaitFix(WaitGPSFixSeconds)) + { + GPS_OutputOff(); + sendCommand(NoFix); //report a GPS fix error + delay(1000); //give receiver enough time to report NoFix + } + Serial.println(); + + do_Transmissions(); //do the transmissions + + Serial.println(F("Sleep")); + LT.setSleep(CONFIGURATION_RETENTION); //put LoRa device to sleep, preserve lora register settings + Serial.flush(); //make sure no serial output pending before goint to sleep + + delay(SleepTimesecs * 1000); + + Serial.println(F("Wake")); + LT.wake(); //wake the LoRa device from sleep +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + uint32_t startTimemS; + uint8_t index; + + incMemoryUint32(addr_SequenceNum); //increment Sequence number + + if (readConfigByte(SearchEnable)) + { + setSearchMode(); + TXPacketL = buildLocationOnly(TXLat, TXLon, TXAlt, TXStatus); //put location data in SX12xx buffer + Serial.print(F("Search packet > ")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F(",")); + Serial.print(TXStatus); + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmitSXBuffer(0, TXPacketL, 10000, SearchTXpower, WAIT_TX); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + } + + delay(1000); //gap between transmissions + + setTrackerMode(); + + TXPacketL = buildHABPacket(); + Serial.print(F("HAB Packet > ")); + printBuffer(TXBUFFER, (TXPacketL + 1)); //print the buffer (the packet to send) as ASCII + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmit(TXBUFFER, (TXPacketL + 1), 10000, TrackerTXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error + digitalWrite(LED1, LOW); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + + delay(1000); //gap between transmissions + + if (readConfigByte(FSKRTTYEnable)) //FSKRTTY is sent last, so that receiver has time to use AFSK upload + { + LT.setupDirect(TrackerFrequency, Offset); + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + startTimemS = millis() - LeadinmS; + + Serial.print(F("FSK RTTY > $$$")); + Serial.flush(); + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + + for (index = 0; index <= (TXPacketL - 1); index++) //its TXPacketL-1 since we dont want to send the null at the end + { + LT.transmitFSKRTTY(TXBUFFER[index], BaudPerioduS, LED1); + Serial.write(TXBUFFER[index]); + } + + LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed + LT.endFSKRTTY(); //stop transmitting carrier + digitalWrite(LED1, LOW); //LED off + printTXtime(startTimemS, millis()); + TXPacketL += 4; //add the two $ at beginning and CR/LF at end + reportCompletion(); + Serial.println(); + } +} + + +void printTXtime(uint32_t startmS, uint32_t endmS) +{ + Serial.print(F(" ")); + Serial.print(endmS - startmS); + Serial.print(F("mS")); +} + + +void reportCompletion() +{ + Serial.print(F(" ")); + if (TXPacketL == 0) + { + Serial.println(); + reporttransmitError(); + } + else + { + Serial.print(TXPacketL); + Serial.print(F("bytes")); + setStatusByte(LORAError, 0); + } +} + + +void printBuffer(uint8_t *buffer, uint8_t size) +{ + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } +} + + +uint8_t buildHABPacket() +{ + //build the HAB tracker payload + uint16_t index, j, CRC; + uint8_t Count, len; + char LatArray[12], LonArray[12]; + + TXSequence = readMemoryUint32(addr_SequenceNum); //Sequence number is kept in non-volatile memory so it survives TXResets + TXResets = readMemoryUint16(addr_ResetCount); //reset count is kept in non-volatile memory so it survives TXResets + TXVolts = readSupplyVoltage(); + Serial.print(F("TXVolts ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + TXTemperature = (int8_t) readTempDS18B20(); + TXErrors = readMemoryUint16(addr_TXErrors); + + dtostrf(TXLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TXLon, 7, 5, LonArray); //converts float to character array + + len = sizeof(TXBUFFER); + memset(TXBUFFER, 0, len); //clear array to 0s + Count = snprintf((char*) TXBUFFER, + TXBUFFER_SIZE, + "$%s,%lu,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%d,%d,%d,%lu", + FlightID, + TXSequence, + TXHours, + TXMinutes, + TXSeconds, + LatArray, + LonArray, + TXAlt, + TXSatellites, + TXVolts, + TXTemperature, + TXResets, + TXStatus, + TXErrors, + TXGPSfixms + ); + + CRC = 0xffff; //start value for CRC16 + + for (index = 1; index < Count; index++) //element 1 is first character after $ at start (for LoRa) + { + CRC ^= (((uint16_t)TXBUFFER[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + TXBUFFER[Count++] = '*'; + TXBUFFER[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + TXBUFFER[Count++] = Hex((CRC >> 8) & 15); + TXBUFFER[Count++] = Hex((CRC >> 4) & 15); + TXBUFFER[Count] = Hex(CRC & 15); + return Count; +} + + +char Hex(uint8_t lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + +uint8_t buildLocationOnly(float Lat, float Lon, uint16_t Alt, uint8_t stat) +{ + uint8_t len; + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationBinaryPacket); //identify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeInt16(Alt); //add altitude + LT.writeUint8(stat); //add tracker status + len = LT.endWriteSXBuffer(); //close buffer write + return len; +} + + +void reporttransmitError() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F("TXError,")); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + incMemoryUint16(addr_TXErrors); //increase the error count + setStatusByte(LORAError, 1); +} + + +void incMemoryUint32(uint32_t addr) +{ + uint32_t val = readMemoryUint32(addr); + val++; + writeMemoryUint32(addr, val); +} + + +void incMemoryUint16(uint32_t addr) +{ + uint16_t val = readMemoryUint16(addr); + val++; + writeMemoryUint16(addr, val); +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +uint8_t readConfigByte(uint8_t bitnum) +{ + return bitRead(Default_config1, bitnum); +} + + +void setTrackerMode() +{ + Serial.println(F("setTrackerMode")); + LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation); +} + + +void setSearchMode() +{ + Serial.println(F("setSearchMode")); + LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation); +} + + +uint8_t sendCommand(char cmd) +{ + uint8_t len; + TXVolts = readSupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + LT.writeUint8(cmd); //this byte defines the packet type + LT.writeUint8(Broadcast); //destination address of the packet, the receivers address + LT.writeUint8(ThisNode); //source address of this node + LT.writeUint16(TXVolts); //add the battery voltage + LT.writeUint8(TXStatus); //add the status byte + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, len, 5000, TrackerTXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void clearAllMemory() +{ + //clears the whole of non-volatile + Serial.println(F("Clear Memory")); + fillMemory(addr_StartMemory, addr_EndMemory, 0); +} + + +float readTempDS18B20() +{ + float DS18B20TXTemperature; + sensor.requestTemperatures(); + DS18B20TXTemperature = sensor.getTempCByIndex(0); + return DS18B20TXTemperature; +} + + +void printTempDS18B20() +{ + float DS18B20TXTemperature; + DS18B20TXTemperature = readTempDS18B20(); + Serial.print(F("Temperature ")); + Serial.print(DS18B20TXTemperature, 1); + Serial.println(F("c")); +} + + +void printSupplyVoltage() +{ + //get and display supply volts on terminal or monitor + Serial.print(F("Volts ")); + Serial.print(readSupplyVoltage()); + Serial.println(F("mV")); +} + + +uint16_t readSupplyVoltage() +{ + //relies on internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit + } + + analogReference(INTERNAL); + temp = analogRead(SupplyAD); + + for (index = 0; index <= 9; index++) //sample AD 10 times + { + temp = analogRead(SupplyAD); + volts = volts + temp; + delay(10); + } + volts = ( (float) (volts / 10) * ADMultiplier); + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn MOSFET connection resitor divider in circuit + } + + return volts; +} + + +//*********************************************************** +// Start GPS Functions +//*********************************************************** + +void GPSTest() +{ + uint8_t GPSchar; + uint32_t startmS; + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < 2000) //allows for millis() overflow + { + GPSchar = GPS_GetByte(); + if (GPSchar != 0xFF) + { + Serial.write(GPSchar); + } + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +bool gpsWaitFix(uint16_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + + uint32_t startmS, waitmS; + uint8_t GPSchar; + + Serial.flush(); + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.println(F("s ")); + Serial.flush(); + + GPS_OutputOn(); + + waitmS = waitSecs * 1000; + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < waitmS) //allows for millis() overflow + { + + do + { + GPSchar = GPS_GetByte(); + if (GPSchar != 0xFF) + { + gps.encode(GPSchar); + Serial.write(GPSchar); + } + } + while (GPSchar != 0xFF); + + if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated()) + { + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = (uint16_t) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TXAlt > 60000) + { + TXAlt = 0; + } + + TXHours = gps.time.hour(), + TXMinutes = gps.time.minute(), + TXSeconds = gps.time.second(), + TXSatellites = gps.satellites.value(); + + setStatusByte(GPSFix, 1); + + TXGPSfixms = millis() - GPSstartms; + + Serial.flush(); + Serial.print(F("Have GPS Fix ")); + Serial.print(TXGPSfixms); + Serial.print(F("mS")); + Serial.println(); + GPSprintTime(); + GPSprintDate(); + Serial.flush(); + + return true; + } + + } + + //if here then there has been no fix and a timeout + GPS_OutputOff(); + setStatusByte(GPSFix, 0); //set status bit to flag no fix + incMemoryUint16(addr_TXErrors); + Serial.println(F("Error No GPS Fix")); + return false; +} + +void GPSprintTime() +{ + uint8_t hours, mins, secs; + hours = gps.time.hour(); + mins = gps.time.minute(); + secs = gps.time.second(); + + 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.println(secs); +} + + +void GPSprintDate() +{ + Serial.print(F("Date ")); + Serial.print(gps.date.day()); + Serial.print(F("/")); + Serial.print(gps.date.month()); + Serial.print(F("/")); + Serial.println(gps.date.year()); +} + +//*********************************************************** +// End GPS Functions +//*********************************************************** + + +void setup() +{ + uint32_t i; + uint16_t j; + + Serial.begin(115200); //Setup Serial console ouput + Serial.println(); + Serial.println(); + Serial.println(F("67_HAB_Balloon_Tracker_Transmitter Starting")); + + memoryStart(Memory_Address); //setup the memory + j = readMemoryUint16(addr_ResetCount); + j++; + writeMemoryUint16(addr_ResetCount, j); + j = readMemoryUint16(addr_ResetCount); + + Serial.print(F("TXResets ")); + Serial.println(j); + + if (GPSPOWER >= 0) //if GPS needs power switching, turn it on + { + pinMode(GPSPOWER, OUTPUT); + digitalWrite(GPSPOWER, GPSONSTATE); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); //for MOSFET controlling battery volts resistor divider + } + +#ifdef QUECTELINUSE + Serial.println(F("Quectel GPS library")); +#endif + +#ifdef UBLOXINUSE + Serial.println(F("UBLOX GPS library")); +#endif + +#ifdef ClearAllMemory + clearAllMemory(); +#endif + + SPI.begin(); //initialize SPI + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + led_Flash(2, 125); + } + else + { + Serial.println(F("LoRa Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + setTrackerMode(); + + Serial.print(F("Config ")); + Serial.println(Default_config1, BIN); + + j = readMemoryUint16(addr_TXErrors); + Serial.print(F("TXErrors ")); + Serial.println(j); + + Serial.print(F("TXSequence ")); + i = readMemoryUint32(addr_SequenceNum); + Serial.println(i); + + Serial.print(F("ThisNode ")); + Serial.println(ThisNode); + + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + + Serial.println(); + printSupplyVoltage(); + printTempDS18B20(); + Serial.println(); + + TXStatus = 0; //clear all TX status bits + + sendCommand(PowerUp); //send power up command, includes supply mV and config, on tracker settings + + GPS_OutputOn(); + Serial.println(); + Serial.println(F("GPS output test")); + Serial.flush(); + GPSTest(); //copy GPS output to serial monitor as a test + GPS_Setup(); //GPS should have had plenty of time to initialise by now + GPS_SetBalloonMode(); + + delay(2000); + + if (GPS_CheckBalloonMode()) //Check that GPS is configured for high altitude balloon mode + { + Serial.println(); + GPS_OutputOff(); //GPS interrupts cause problems with lora device, so turn off for now + setStatusByte(GPSError, 0); + setStatusByte(GPSConfigError, 0); + + //Alert user to GPS OK, turn LED on and send a FM tone + digitalWrite(LED1, HIGH); + Serial.println(F("GPS Config OK")); //check tone indicates navigation model 6 set + Serial.println(); + Serial.flush(); + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + LT.toneFM(1500, 500, deviation, adjustfreq, TrackerTXpower); //Transmit an FM tone, 1000hz, 3000ms + delay(1000); + digitalWrite(LED1, LOW); + } + else + { + setStatusByte(GPSConfigError, 1); + incMemoryUint16(addr_TXErrors); + Serial.println(F("GPS Error")); + Serial.println(); + setTrackerMode(); + sendCommand(NoGPS); //make sure receiver knows about GPS error + led_Flash(100, 25); //long very rapid flash for GPS error + } + + GPSstartms = millis(); + + setTrackerMode(); //so that commands indicating wait for a GPS go out + + while (!gpsWaitFix(5)) //wait for the initial GPS fix, this could take a while + { + sendCommand(NoFix); + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + } + + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + digitalWrite(LED1, HIGH); + LT.toneFM(500, 2000, deviation, adjustfreq, TrackerTXpower); + digitalWrite(LED1, LOW); + GPS_OutputOn(); + delay(2000); //GPS may be in software backup allow time for it to wakeup + GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled + GPS_OutputOff(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/67_Balloon_Tracker_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/67_Balloon_Tracker_Transmitter/Settings.h new file mode 100644 index 0000000..52c6bfc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/67_Balloon_Tracker_Transmitter/Settings.h @@ -0,0 +1,143 @@ + /******************************************************************************************************* + 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. +*******************************************************************************************************/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify lora board type and pins here +//************************************************************************************************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define LED1 8 //On board LED, high for on +#define BATVREADON 8 //Pin that turns on the resistor divider to read battery volts +#define ONE_WIRE_BUS 4 //for DS18B20 temperature sensor +#define ADMultiplier 5.25 //adjustment to convert into mV of battery voltage. for 100K\10K divider +#define SupplyAD A0 //Resistor divider for battery connected here + +#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 powers GPS on\off, 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 + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +//#define ClearAllMemory //Clears memory of stored tracker information, counts, errors etc + +//************************************************************************************************** +// 3) LoRa modem settings +//************************************************************************************************** + +//LoRa Modem Parameters +const uint32_t Offset = 0; //offset frequency for calibration purposes + +//Tracker mode +const uint32_t TrackerFrequency = 434000000; //frequency of transmissions +const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t TrackerTXpower = 10; //LoRa TX power in dBm + +//Search mode +const uint32_t SearchFrequency = 434000000; //frequency of transmissionsconst +uint8_t SearchBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t SearchTXpower = 10; //LoRa TX power in dBm + +const uint16_t deviation = 10000; //deviation in hz for FM tones +const float adjustfreq = 0.9; //adjustment to tone frequency + +const uint8_t TXBUFFER_SIZE = 128; //defines the maximum size of the trasnmit buffer; + + +//************************************************************************************************** +// 4) GPS Options +//************************************************************************************************** + +#define GPSBaud 9600 //GPS Baud rate + +//#define USEI2CGPS //enable this define if your using a Ublox over the I2C interface +//#define GPS_Library //and define this library file for the UBLOX GPS over I2C + +#define USESOFTSERIALGPS //if your using software serial for the GPS, enable this define + +//#define USEHARDWARESERIALGPS //if your using hardware serial for the GPS, enable this define +#define HARDWARESERIALPORT Serial1 //if your using hardware serial for the GPS, define the port here + +//#define GPS_Library //use library file for UBLOX GPS +#define GPS_Library //use library file for Quectel GPS + +const uint16_t WaitGPSFixSeconds = 60; //when in flight the time to wait for a new GPS fix + +//************************************************************************************************** +// 5) FSK RTTY Settings +//************************************************************************************************** + +uint32_t FrequencyShift = 500; //hertz frequency shift, approx, sent at nearest 61.03515625hz step +uint8_t NumberofPips = 4; //number of marker pips to send +uint16_t PipDelaymS = 1000; //mS between pips when carrier is off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 1000; //ms of leadin constant shifted carrier + + +//**************************************************************************************************** +// 6) Program Default Option settings - This section determines which options are on or off by default, +// these are saved in the Default_config1 byte. These options are set in this way so that it is +// possible (in future program changes) to alter the options remotly. +//************************************************************************************************** + +uint8_t OptionOff = 0; +uint8_t OptionOn = 1; + +const char option_SearchEnable = OptionOn; //set to OptionOn to enable transmit of Search mode packet +const char option_FSKRTTYEnable = OptionOn; //set to OptionOn to enable transmit of FSKRTTY + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) + +const uint16_t Default_config1 = (option_SearchEnable_SUM + option_FSKRTTYEnable_SUM); +//const uint16_t Default_config1 = 0x05; //Phew, the default config can always be set manually........ + //0x05 would turn on transmit of search mode and FSKRTTY + + +//************************************************************************************************** +// 7) Memory settings - define the type of memory to use for non-Volatile storage. +// Default is internal ATmega device EEPROM but EEPROM has a limited write endurance of 'only' +// 100,000 writes. Since the non-Volatile memory selected is written to at each transmission loop +// and error, its highly recommended to use one of the FRAM options, these have an endurance of +// 100,000,000,000,000 writes. +//************************************************************************************************** + +#define Memory_Library +//#define Memory_Library +//#define Memory_Library + +int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM + +//************************************************************************************************** +// 8) HAB Flight Settings +//************************************************************************************************** + +char FlightID[] = "Flight1"; //flight ID for HAB packet + +const uint16_t SleepTimesecs = 13; //sleep time in seconds after each TX loop + +const char ThisNode = '1'; //tracker number for search packet + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/68_Balloon_Tracker_Receiver.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/68_Balloon_Tracker_Receiver.ino new file mode 100644 index 0000000..45ed8cd --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/68_Balloon_Tracker_Receiver.ino @@ -0,0 +1,1048 @@ +/******************************************************************************************************* + 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 is a LoRa tracker receiver intended to be used with the matching high altitude + balloon (HAB) tracker program '67_Balloon_Tracker_Transmitter'. The program receives a standard format + payload with LoRa that is compatible with the HABHUB online tracking system. + + The HAB payload sent by the tracker transmitter is assumed to be formatted like this; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,status,errors,Checksum + Field 0 1 2 3 4 5 6 7 8 9 10 11 12 + + The LoRa and frequency settings can be changed in the Settings.h file. There is the option of the transmitter + sending out a much shorter Search mode binary location only payload. This is intended for ground based searching + and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker + mode used by the HAB payload. To switch between standard tracker mode press the switch that is defined in the + Settings.h file. This receiver cannot receive the transmitted FSK RTTY payload. + + There is the option to enable an audio FSK RTTY uplaod into FLDIGI from where it can be sent to the HABHUB + online tracking system. + + The program will drive a SSD1306 or SH1106 OLED display for portable use. + + Not that the distance and direction to the tracker is only displayed when there has been at least one location + fix from the remote tracker and the locally attached GPS has a fix. + + Serial monitor baud rate is set at 9600. + + ToDo: + +*******************************************************************************************************/ + + +#define Program_Version "V1.2" + +#include +#include +SX127XLT LT; + +#include "Settings.h" +#include + +#include //https://github.com/olikraus/u8g2 +//U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 +#define DEFAULTFONT u8x8_font_chroma48medium8_r //font for U8X8 Library + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USESOFTSERIALGPS +//#include //https://github.com/SlashDevin/NeoSWSerial +//NeoSWSerial GPSserial(RXpin, TXpin); //The NeoSWSerial library is an option to use and is more relaible + //at GPS init than software serial +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#endif + +#ifdef USEHARDWARESERIALGPS +#define GPSserial HARDWARESERIALPORT +#endif + +#ifdef UPLOADHABPACKET +#include //this library supports Arduinos without tone functions +#endif + +//************************************************************************************************** +// HAB tracker data - these are the variables transmitted in payload +//************************************************************************************************** +uint32_t TXSequence; //sequence number of payload +uint8_t TXHours; //Hours +uint8_t TXMinutes; //Minutes +uint8_t TXSeconds; //Seconds +float TXLat; //latitude from GPS +float TXLon; //longitude from GPS +uint16_t TXAlt; //altitude from GPS +uint8_t TXSatellites; //satellites used by GPS +uint16_t TXVolts; //measured tracker supply volts +int8_t TXTemperature; //measured temperature +uint16_t TXResets; //number of tracker resets +uint8_t TXStatus; //used to store current status flag bits +uint16_t TXErrors; //number of tracker Errors +//************************************************************************************************** + +float RXLat; //latitude of RX +float RXLon; //longitude of RX +float RXAlt; //altitude of RX + +uint32_t RXpacketCount; //count of received packets +uint8_t RXPacketL; //length of received packet +int16_t PacketRSSI; //signal strength (RSSI) dBm of received packet +int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet +uint16_t RXerrors; //count of packets received with errors +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +float TXdistance; //calculated distance to tracker +uint16_t TXdirection; //calculated direction to tracker +uint16_t RXVolts; //supply\battery voltage of this receiver +uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix +bool TXLocation = false; //set to true when at least one tracker location packet has been received +bool RXGPSfix = false; //set to true if the local GPS has a recent fix + +uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into +char FlightID[16]; //buffer for flight ID +uint8_t FlightIDlen; //length of received flight ID + +uint8_t modeNumber = 1; //mode receiver is in default to 1. (1 = Tracker, 2 = Search) + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); + + GPSserial.begin(GPSBaud); //startup GPS input + + while (!digitalRead(DIO0)) + { + readGPS(); //If the DIO pin is low, no packet has arrived, so read the GPS + + if (!digitalRead(SWITCH1)) + { + checkModeSwitch(); + break; + } + } + + if (digitalRead(DIO0)) + { + //something has happened in receiver + GPSserial.end(); //stop GPS input to use SPI reliably + digitalWrite(LED1, HIGH); + + RXPacketL = LT.readRXPacketL(); + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + Serial.println(); + printElapsedTime(); //print elapsed time to Serial Monitor + + if (LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID)) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + + digitalWrite(LED1, LOW); + + Serial.println(); + } +} + + +void readGPS() +{ + + if (GPSserial.available() > 0) + { + gps.encode(GPSserial.read()); + } + + if ( (uint32_t) (millis() - LastRXGPSfixCheck) > NoRXGPSfixms) + { + RXGPSfix = false; + LastRXGPSfixCheck = millis(); + if (TXLocation) //only display location screen if we have had an update + { + displayscreen1(); //shows the received location data and packet reception on display + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + } + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated()) + { + RXGPSfix = true; + RXLat = gps.location.lat(); + RXLon = gps.location.lng(); + RXAlt = gps.altitude.meters(); + LastRXGPSfixCheck = millis(); + displayscreen4(); //put RX and TX GPS fix status on display + + if (FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1 + { + FixCount = DisplayRate; + if (TXLocation) //only display location screen if we have had an update + { + doDistanceDirectionCalc(); + displayscreen1(); //shows the received location data and packet reception on display + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + displayscreen5(); //put distance and direction on display + printDistanceDirection(); + } + } + FixCount--; + } +} + + +void checkModeSwitch() +{ + digitalWrite(LED1, LOW); + Serial.println(); + Serial.print(F("Listening in ")); + + modeNumber++; + + if (modeNumber == 3) + { + modeNumber = 1; + } + + if (modeNumber == 1) + { + setTrackerMode(); + Serial.println(F("Tracker Mode")); + } + + + if (modeNumber == 2) + { + setSearchMode(); + Serial.println(F("Search Mode")); + } + + displayscreen3(); //show receive mode on display + + LT.printModemSettings(); + Serial.println(); + Serial.println(); + delay(1500); //do a bit of switch de-bounce +} + + +bool readTXStatus(uint8_t bitnum) +{ + return bitRead(TXStatus, bitnum); +} + + +void readPacketAddressing() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + uint16_t includedCRC, actualCRC; + + RXpacketCount++; + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + read_Command(); + Serial.print(F("TrackerPowerup,Battery,")); + Serial.print(TXVolts); + Serial.print(F("mV")); + displayscreen2(); + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + displayscreen7(); //display received packet count + return; + } + + if (PacketType == HABPacket) + { + includedCRC = calcIncludedCRC(); + actualCRC = LT.CRCCCITTSX(1, RXPacketL - 6, 0xFFFF); + + if (actualCRC != includedCRC) + { + Serial.print(F("PayloadCRCError")); + Serial.print(F(",includedCRC,")); + Serial.print(includedCRC, HEX); + Serial.print(F(",actualCRC,")); + Serial.print(actualCRC, HEX); + Serial.print(F(",")); + LT.printSXBufferASCII(0, (RXPacketL - 1)); + printpacketDetails(); + displayscreen7(); //display received packet count + return; + } + + extractHABdata(0); + + TXLocation = true; + LT.printSXBufferASCII(0, (RXPacketL - 1)); + + TXdistance = 0; + TXdirection = 0; + + if (RXGPSfix) + { + doDistanceDirectionCalc(); + } + + printpacketDetails(); + Serial.println(); + + displayscreen1(); //shows the received location data and packet reception on display + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + displayscreen5(); //put distance and direction on display + printDistanceDirection(); + +#ifdef UPLOADHABPACKET + if (actualCRC == includedCRC) + { + Serial.println(); + uploadHABpacket(); + } +#endif + + return; + } + + if ((PacketType == LocationBinaryPacket) && (Destination == '*') && (RXPacketL == 14)) + { + //packet from tracker transmitter has been received, now read from the SX12XX FIFO in the correct order. + TXLocation = true; + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F("m,")); + Serial.println(TXStatus); + + TXdistance = 0; + TXdirection = 0; + + if (RXGPSfix) + { + doDistanceDirectionCalc(); + } + + displayscreen1(); //shows the received location data and packet reception on display + displayscreen5(); //put distance and direction on display + displayscreen7(); //display received packet count + printDistanceDirection(); + return; + } + + if (PacketType == NoFix) + { + read_Command(); + Serial.write(Source); + Serial.print(F(",NoTrackerGPSFix")); + Serial.write(7); //send a BELL to serial terminal + delay(250); + Serial.write(7); + displayscreen6(); //send a note about no tracker GPS fix to screen + displayscreen7(); //display received packet count + return; + } + + if (PacketType == NoGPS) + { + Serial.write(Source); + read_Command(); + Serial.print(F(",GPSError")); + return; + } + + Serial.print(F("PacketNotRecognised")); + printpacketDetails(); + printmorepacketDetails(); +} + +#ifdef UPLOADHABPACKET +void uploadHABpacket() +{ + uint8_t index; + uint8_t chartosend; + + Serial.print(F("Dl-Fldigi Upload $")); + Serial.flush(); + + startAFSKRTTY(AUDIOOUT, CHECK, LOWCYCLES, LOWPERIODUS, HIGHCYCLES, HIGHPERIODUS, ADJUSTUS, leadinmS); + sendAFSKRTTY(13); + sendAFSKRTTY(10); + sendAFSKRTTY('$'); + + for (index = 0; index <= (RXPacketL - 1); index++) + { + chartosend = LT.getByteSXBuffer(index); + sendAFSKRTTY(chartosend); + Serial.write(chartosend); + Serial.flush(); + } + + sendAFSKRTTY(13); + sendAFSKRTTY(10); + Serial.println(); + endAFSKRTTY(AUDIOOUT, CHECK, leadoutmS); +} +#endif + + +uint16_t calcIncludedCRC() +{ + uint8_t high, midhigh, midlow, low; + uint16_t crc; + high = LT.getByteSXBuffer(RXPacketL - 4); + midhigh = LT.getByteSXBuffer(RXPacketL - 3); + midlow = LT.getByteSXBuffer(RXPacketL - 2); + low = LT.getByteSXBuffer(RXPacketL - 1); + + high = convertASCIIbyte(high); + midhigh = convertASCIIbyte(midhigh); + midlow = convertASCIIbyte(midlow); + low = convertASCIIbyte(low); + + crc = (high * 4096) + (midhigh * 256) + (midlow * 16) + low; + return (uint16_t) crc; +} + + +uint8_t convertASCIIbyte(uint8_t val) +{ + if (val > 0x40) + { + val = (val - 0x41) + 10; + return val; + } + else + { + val = (val - 0x30); + return val; + } +} + + +void read_Command() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXVolts = LT.readUint16(); //read tracker transmitter voltage + LT.endReadSXBuffer(); +} + + +void printDistanceDirection() +{ + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + Serial.print(F("Distance,")); + Serial.print(TXdistance, 0); + Serial.print(F("m,Direction,")); + Serial.print(TXdirection); + Serial.println(F("d")); + } +} + + +void doDistanceDirectionCalc() +{ + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); +} + + +void printpacketDetails() +{ + int32_t hertzerror; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,FreqErr,")); + hertzerror = LT.getFrequencyErrorHz(); + Serial.print(hertzerror); + Serial.print(F("hz,PacketErrs,")); + Serial.print(RXerrors); + Serial.print(F(",PacketsOK,")); + Serial.print(RXpacketCount); +} + + +void printmorepacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + RXerrors++; + Serial.print(F(",PacketError,RSSI")); + + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); +} + + +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 extractHABdata(uint8_t startaddr) +{ + //extracts data from received HAB packets where first fields are lat,lon,alt + //all varialbles are extracted, not all are used. + + uint8_t ptr = startaddr; //pointer to current location in SXbuffer + uint8_t buffData; + + //Skip leading $ + do + { + buffData = LT.getByteSXBuffer(ptr++); + } + while ( buffData == '$'); + + ptr--; //so ptr is at location of first non $ + + FlightIDlen = extractBuffer(FlightID, sizeof(FlightID), ptr); //extract flight ID + + ptr = nextComma(ptr); //step to next comma in SX buffer + TXSequence = extractUint(ptr); //extract sequence + + ptr = nextComma(ptr); + TXHours = (uint32_t) extractUint(ptr); + + ptr = nextComma(ptr); + TXMinutes = (uint32_t) extractUint(ptr); + + ptr = nextComma(ptr); + TXSeconds = (uint32_t) extractUint(ptr); + + //ptr = nextComma(ptr); + ptr = nextComma(ptr); + TXLat = extractFloat(ptr); + + ptr = nextComma(ptr); + TXLon = extractFloat(ptr); + + ptr = nextComma(ptr); + TXAlt = extractUint(ptr); + + ptr = nextComma(ptr); + TXSatellites = extractUint(ptr); + + ptr = nextComma(ptr); + TXVolts = extractUint(ptr); + + ptr = nextComma(ptr); + TXTemperature = extractUint(ptr); + + ptr = nextComma(ptr); + TXResets = extractUint(ptr); + + ptr = nextComma(ptr); + TXStatus = extractUint(ptr); + + ptr = nextComma(ptr); + TXErrors = extractUint(ptr); +} + + +void printHABdata() +{ + printBuffer(FlightID, FlightIDlen); + Serial.print(F(",")); + Serial.print(TXSequence); + Serial.print(F(",")); + + Serial.print(TXHours); + Serial.print(F(",")); + Serial.print(TXMinutes); + Serial.print(F(",")); + Serial.print(TXSeconds); + Serial.print(F(",")); + + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F(",")); + Serial.print(TXSatellites); + Serial.print(F(",")); + Serial.print(TXVolts); + Serial.print(F(",")); + Serial.print(TXTemperature); + Serial.print(F(",")); + Serial.print(TXResets); + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXErrors); +} + + +uint8_t extractBuffer(char *mybuffer, size_t bufferSize, uint8_t startptr) +{ + //extracts a character buffer in ASCII format from lora device RX buffer, returns the length of the buffer to , char + uint16_t index; + + memset(mybuffer, 0, bufferSize); //clear array to 0s + + bufferSize--; //last index location is one less than buffer size + + for (index = 0; index <= bufferSize; index++) + { + mybuffer[index] = LT.getByteSXBuffer(startptr++); + if ((mybuffer[index] == ',') || (mybuffer[index] == '*')) + { + break; + } + } + mybuffer[index] = 0; //it was a , so clear it + return index++; //buffer length is one more than index location +} + + +void printBuffer(char *buff, uint8_t len) +{ + //send buffer to serial terminal + uint8_t index; + + for (index = 0; index < len; index++) + { + Serial.write(buff[index]); + } + +} + + +uint8_t nextComma(uint8_t localpointer) +{ + //skips through HAB packet (in SX device buffer) to next comma + uint8_t bufferdata; + do + { + bufferdata = LT.getByteSXBuffer(localpointer++); + } + while ((bufferdata != ',') && (bufferdata != ':') && (localpointer < RXPacketL)); + return localpointer; //note returns start of next field +} + + +uint8_t nextColon(uint8_t localpointer) +{ + //skips through HAB packet (in SX device buffer) to next colon + uint8_t bufferdata; + do + { + bufferdata = LT.getByteSXBuffer(localpointer++); + } + while ((bufferdata != ':') && (localpointer < RXPacketL)); + return localpointer; +} + + +int32_t extractUint(uint16_t localpointer) +{ + //extracts an unsigned int in ASCII format from buffer + + char temp[16]; + uint8_t tempptr = 0; + uint8_t buffdata; + uint32_t tempint; + do + { + buffdata = LT.getByteSXBuffer(localpointer++);; + temp[tempptr++] = buffdata; + } + while ((buffdata != ',') && (buffdata != '*') && (localpointer < 256) ); + temp[tempptr] = 0; //terminator for string + tempint = (int32_t) atof(temp); + return tempint; +} + + +float extractFloat(uint16_t localpointer) +{ + //extracts a float in ASCII format from buffer + char temp[16]; + uint8_t tempptr = 0; + uint8_t buffdata; + float tempfloat; + do + { + buffdata = LT.getByteSXBuffer(localpointer++);; + temp[tempptr++] = buffdata; + } + while ((buffdata != ',') && (buffdata != '*') && (localpointer < 256) ); + temp[tempptr] = 0; //terminator for string + tempfloat = (float)atof(temp); + return tempfloat; +} + + +void setTrackerMode() +{ + LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation); +} + + +void setSearchMode() +{ + LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation); +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F(",")); +} + + +void GPSPowerOn(int8_t pin, uint8_t state) +{ + if (pin >= 0) + { + digitalWrite(pin, state); + } +} + +//************************************************************************ +// Display screen functions +//************************************************************************ + +void displayscreen1() +{ + //shows the received location data and packet reception on display + uint8_t index; + + disp.clearLine(0); + disp.setCursor(0, 0); + + if (PacketType == HABPacket) + { + for (index = 0; index < FlightIDlen; index++) + { + disp.write(FlightID[index]); + } + } + + if (PacketType == LocationBinaryPacket) + { + disp.print(Source); + } + + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(F("Lat ")); + disp.print(TXLat, 5); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(F("Lon ")); + disp.print(TXLon, 5); + disp.clearLine(3); + disp.setCursor(0, 3); + disp.print(F("Alt ")); + disp.print(TXAlt); + disp.print(F("m")); + + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(F("RSSI ")); + disp.print(PacketRSSI); + disp.print(F("dBm")); + disp.clearLine(5); + disp.setCursor(0, 5); + disp.print(F("SNR ")); + + if (PacketSNR > 0) + { + disp.print(F("+")); + } + + if (PacketSNR == 0) + { + disp.print(F(" ")); + } + + if (PacketSNR < 0) + { + disp.print(F("-")); + } + + disp.print(PacketSNR); + disp.print(F("dB")); + + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); +} + + +void displayscreen2() +{ + //show tracker transmitter powerup data on display + float tempfloat; + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("TXPowerup")); + disp.setCursor(0, 1); + disp.print(F("Battery,")); + tempfloat = ((float) TXVolts / 1000); + disp.print(tempfloat, 2); + disp.print(F("v")); +} + + +void displayscreen3() +{ + //show receive mode on display + disp.setCursor(14, 0); + + if (modeNumber == TrackerMode) + { + disp.print(F("TR")); + return; + } + + if (modeNumber == SearchMode) + { + disp.print(F("SE")); + return; + } + + disp.print(modeNumber); +} + + +void displayscreen4() +{ + //put RX and TX GPS fix status on display + + disp.setCursor(14, 1); + + if (RXGPSfix) + { + disp.print(F("RG")); + } + else + { + disp.setCursor(14, 1); + disp.print(F("R?")); + } + + disp.setCursor(14, 2); + + if (readTXStatus(GPSFix)) + { + disp.print(F("TG")); + } + else + { + disp.print(F("T?")); + } +} + + +void displayscreen5() +{ + //put distance and direction on display + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("D&D ")); + disp.print(TXdistance, 0); + disp.print(F("m ")); + disp.print(TXdirection); + disp.print(F("d")); + } +} + + +void displayscreen6() +{ + //no GPS fix + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("No GPS Fix")); +} + + +void displayscreen7() +{ + //display received packet count + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); +} + + +void GPSTest() +{ + uint32_t startmS; + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < 2000) //allows for millis() overflow + { + if (GPSserial.available() > 0) + { + Serial.write(GPSserial.read()); + } + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +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(SWITCH1, INPUT_PULLUP); //setup pin as switch input + + if (CHECK <= 0) + { + pinMode(CHECK, OUTPUT); + } + + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, 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("68_Balloon_Tracker_Receiver Starting")); + + SPI.begin(); + + disp.begin(); + disp.setFont(DEFAULTFONT); + + Serial.print(F("Checking LoRa device - ")); + disp.setCursor(0, 0); + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) //Initialize LoRa device + { + Serial.println(F("Receiver ready")); + disp.print(F("Ready")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No LoRa device responding")); + disp.print(F("No LoRa device")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + GPSPowerOn(GPSPOWER, GPSONSTATE); + GPSserial.begin(GPSBaud); + + Serial.println(); + + Serial.println(F("Startup GPS check")); + GPSTest(); + Serial.println(F("Done")); + Serial.println(); + Serial.flush(); + + GPSserial.end(); //software serial interferes with SPI for LoRa device + + setTrackerMode(); + displayscreen3(); //show receive mode on display + displayscreen4(); //put RX and TX GPS fix status on display + + LT.printModemSettings(); + Serial.println(); + Serial.println(F("Listening in Tracker mode")); + Serial.println(); + Serial.write(7); //send a BELL to serial terminal + TXStatus = 4; //set default flag of no TX GPS fix +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/AFSKRTTY2_DL-Fldigi_Settings.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/AFSKRTTY2_DL-Fldigi_Settings.jpg new file mode 100644 index 0000000..b428c9d Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/AFSKRTTY2_DL-Fldigi_Settings.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/Settings.h new file mode 100644 index 0000000..67e1a4a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/68_Balloon_Tracker_Receiver/Settings.h @@ -0,0 +1,103 @@ +/******************************************************************************************************* + 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. +*******************************************************************************************************/ + + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify lora board type and pins here +//************************************************************************************************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define LED1 8 //On board LED, high for on +#define SWITCH1 2 //if pin shorted to ground, switch is active + +#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 + +#define AUDIOOUT 6 //pin used to output Audio tones for HAB packet upload +#define CHECK 8 //this pin is toggled inside the AFSKRTTY library, high for logic 1, low for logic 0, so it can be used to check the timing. + +#define LORA_DEVICE DEVICE_SX1278 //this is the LoRa device we are using + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + + + +//************************************************************************************************** +// 3) LoRa modem settings +//************************************************************************************************** + +const uint32_t Offset = 0; //offset frequency for calibration purposes + +//Tracker mode +const uint32_t TrackerFrequency = 434000000; //frequency of transmissions +const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t TrackerTXpower = 10; //LoRa TX power in dBm +const uint8_t TrackerMode = 1; //used for receiver to tell whatmode it is in + +//Search mode +const uint32_t SearchFrequency = 434000000; //frequency of transmissions +const uint8_t SearchBandwidth = LORA_BW_062;; //LoRa bandwidth +const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t SearchTXpower = 10; //LoRa TX power in dBm +const uint8_t SearchMode = 2; //used for receiver to tell whatmode it is in + +const uint8_t RXBUFFER_SIZE = 128; //RX buffer size + +//************************************************************************************************** +// 4) GPS Options +//************************************************************************************************** + +const uint16_t GPSBaud = 9600; //GPS Baud rate + +#define USESOFTSERIALGPS //if your using software serial for the GPS, enable this define +//#define USEHARDWARESERIALGPS //if your using hardware serial for the GPS, enable this define +#define HARDWARESERIALPORT Serial1 //if using hardware serial enable this define for hardware serial port + +const uint16_t WaitGPSFixSeconds = 30; //time to wait for a new GPS fix + +const uint16_t NoRXGPSfixms = 15000; //max number of mS to allow before no local fix flagged +const uint8_t DisplayRate = 7; //when working OK the GPS will get a new fix every second or so +//this rate defines how often the display should be updated + + +//************************************************************************************************** +// 6) AFSK RTTY Settings - For PC upload into Dl-Fldigi in HAB mode. +// Sent at 200baud, 7 bit, no parity, 2 stop bits. +// Shift circa 360hz, low tone 1000hz, high tone 1400hz (measured on an Arduino Due) +// See screenshot 'AFSKRTTY2_DL-Fldigi_Settings.jpg' in this folder for the settings used +// +//************************************************************************************************** + +#define UPLOADHABPACKET //comment in define to output HAB packet as AFSKRTTY for PC upload + +const uint16_t leadinmS = 2000; //number of ms for AFSK constant lead in tone +const uint16_t leadoutmS = 0; //number of ms for AFSK constant lead out tone + + +const uint16_t LOWPERIODUS = 1000; //actual period in uS of to give a 200baud +const uint8_t LOWCYCLES = 5; //cycles of low frequency tone for 200baud +const uint16_t HIGHPERIODUS = 714; //actual high period in uS to give a 200baud +const uint8_t HIGHCYCLES = 7; //cycles of high frequency tone for 200baud +const int8_t ADJUSTUS = 0; //uS to subtract from tone generation loop to match frequency + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/69_Balloon_Tracker_Transmitter_GenericGPS/69_Balloon_Tracker_Transmitter_GenericGPS.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/69_Balloon_Tracker_Transmitter_GenericGPS/69_Balloon_Tracker_Transmitter_GenericGPS.ino new file mode 100644 index 0000000..b86094b --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/69_Balloon_Tracker_Transmitter_GenericGPS/69_Balloon_Tracker_Transmitter_GenericGPS.ino @@ -0,0 +1,786 @@ +/****************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 28/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 tracker intended for use as a high altitude balloon (HAB) tracker. The + program sends out a standard format payload with LoRa that is compatible with the HABHUB online tracking + system. + + The HAB payload is constructed thus; + + PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,Status,Errors,TXGPSfixms,Checksum + Field 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + + The LoRa and frequency settings can be changed in the Settings.h file. There is the option of sending + out a much shorter Search mode binary location only payload. This is intended for ground based searching + and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker + mode used by the HAB payload. There is also the option of sending the HAB payload in FSK RTTY format, + see the Settings.h file for all the options. FSK RTTY gets sent at the same frequency as the Tracker mode + HAB packet. The LT.transmitFSKRTTY() function sends at 1 start bit, 7 data bits, no parity and 2 stop bits. + For full control of the FSK RTTY setting you can use the following alternative function; + + LT.transmitFSKRTTY(chartosend, databits, stopbits, parity, baudPerioduS, pin) + + There is a matching Balloon Tracker Receiver program which writes received data to the Serial monitor as well + as a small OLED display. + + In the Settings.h file you can set the configuration for either a Ublox GPS or a Quectel L70\L80. The GPSs + are configured for high altitude balloon mode. + + It is strongly recommended that a FRAM option is fitted for this transmitter. The sequence, resets and error + nembers are stred in non-volatile memory. This defaults to EEPROM which has a limited endurance of only + 100,000 writes, so in theory the limt is reached after the transmission of 100,000 hab packets. The use of + a FRAM will extend the life of the tracker to circa 100,000,000,000,000 transmissions. + + Changes: + 240420 - Change to work with Easy Pro Mini style modules + 300420 - Improve error detection for UBLOX GPS library + + ToDo: + + Serial monitor baud rate is set at 115200 +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include + +#include //include the appropriate library + +SX127XLT LT; //create a library class instance called LT + +#include "Settings.h" +#include "ProgramLT_Definitions.h" + +//************************************************************************************************** +// HAB tracker data - these are the variables transmitted in payload +//************************************************************************************************** +uint32_t TXSequence; //sequence number of payload +uint8_t TXHours; //Hours +uint8_t TXMinutes; //Minutes +uint8_t TXSeconds; //Seconds +float TXLat; //latitude from GPS +float TXLon; //longitude from GPS +uint16_t TXAlt; //altitude from GPS +uint8_t TXSatellites; //satellites used by GPS +uint16_t TXVolts; //measured tracker supply volts +int8_t TXTemperature; //measured temperature +uint16_t TXResets; //number of tracker resets +uint8_t TXStatus = 0; //used to store current status flag bits +uint16_t TXErrors; //number of tracker Errors +uint32_t TXGPSfixms; //fix time of GPS +//************************************************************************************************** + +uint8_t TXPacketL; //length of LoRa packet sent +uint8_t TXBUFFER[TXBUFFER_SIZE]; //buffer for packet to send + +#include Memory_Library + +#include + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USESOFTSERIALGPS +//#include //https://github.com/SlashDevin/NeoSWSerial +//NeoSWSerial GPSserial(RXpin, TXpin); //The NeoSWSerial library is an option to use and is more relaible +//at GPS init than software serial +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#endif + +#ifdef USEHARDWARESERIALGPS +#define GPSserial HARDWARESERIALPORT +#endif + +#ifdef USEI2CGPS +#include +#endif + +#include //get library here > https://github.com/PaulStoffregen/OneWire +OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library +#include //get library here > https://github.com/milesburton/Arduino-TXTemperature-Control-Library +DallasTemperature sensor(&oneWire); //create instance of dallas library + +uint32_t GPSstartms; //start time waiting for GPS to get a fix + + +void loop() +{ + Serial.println(F("Start Loop")); + + GPSstartms = millis(); + + if (!gpsWaitFix(WaitGPSFixSeconds)) + { + GPSOutputOff(); + sendCommand(NoFix); //report a GPS fix error + delay(1000); //give receiver enough time to report NoFix + } + Serial.println(); + + do_Transmissions(); //do the transmissions + + Serial.println(F("Sleep")); + LT.setSleep(CONFIGURATION_RETENTION); //put LoRa device to sleep, preserve lora register settings + Serial.flush(); //make sure no serial output pending before goint to sleep + + delay(SleepTimesecs * 1000); + + Serial.println(F("Wake")); + LT.wake(); //wake the LoRa device from sleep +} + + +void do_Transmissions() +{ + //this is where all the transmisions get sent + uint32_t startTimemS; + uint8_t index; + + incMemoryUint32(addr_SequenceNum); //increment Sequence number + + if (readConfigByte(SearchEnable)) + { + setSearchMode(); + TXPacketL = buildLocationOnly(TXLat, TXLon, TXAlt, TXStatus); //put location data in SX12xx buffer + Serial.print(F("Search packet > ")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt); + Serial.print(F(",")); + Serial.print(TXStatus); + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmitSXBuffer(0, TXPacketL, 10000, SearchTXpower, WAIT_TX); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + } + + delay(1000); //gap between transmissions + + setTrackerMode(); + + TXPacketL = buildHABPacket(); + Serial.print(F("HAB Packet > ")); + printBuffer(TXBUFFER, (TXPacketL + 1)); //print the buffer (the packet to send) as ASCII + digitalWrite(LED1, HIGH); + startTimemS = millis(); + TXPacketL = LT.transmit(TXBUFFER, (TXPacketL + 1), 10000, TrackerTXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error + digitalWrite(LED1, LOW); + printTXtime(startTimemS, millis()); + reportCompletion(); + Serial.println(); + + delay(1000); //gap between transmissions + + if (readConfigByte(FSKRTTYEnable)) //FSKRTTY is sent last, so that receiver has time to use AFSK upload + { + LT.setupDirect(TrackerFrequency, Offset); + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + startTimemS = millis() - LeadinmS; + + Serial.print(F("FSK RTTY > $$$")); + Serial.flush(); + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync + + for (index = 0; index <= (TXPacketL - 1); index++) //its TXPacketL-1 since we dont want to send the null at the end + { + LT.transmitFSKRTTY(TXBUFFER[index], BaudPerioduS, LED1); + Serial.write(TXBUFFER[index]); + } + + LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed + LT.endFSKRTTY(); //stop transmitting carrier + digitalWrite(LED1, LOW); //LED off + printTXtime(startTimemS, millis()); + TXPacketL += 4; //add the two $ at beginning and CR/LF at end + reportCompletion(); + Serial.println(); + } +} + + +void printTXtime(uint32_t startmS, uint32_t endmS) +{ + Serial.print(F(" ")); + Serial.print(endmS - startmS); + Serial.print(F("mS")); +} + + +void reportCompletion() +{ + Serial.print(F(" ")); + if (TXPacketL == 0) + { + Serial.println(); + reporttransmitError(); + } + else + { + Serial.print(TXPacketL); + Serial.print(F("bytes")); + setStatusByte(LORAError, 0); + } +} + + +void printBuffer(uint8_t *buffer, uint8_t size) +{ + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } +} + + +uint8_t buildHABPacket() +{ + //build the HAB tracker payload + uint16_t index, j, CRC; + uint8_t Count, len; + char LatArray[12], LonArray[12]; + + TXSequence = readMemoryUint32(addr_SequenceNum); //Sequence number is kept in non-volatile memory so it survives TXResets + TXResets = readMemoryUint16(addr_ResetCount); //reset count is kept in non-volatile memory so it survives TXResets + TXVolts = readSupplyVoltage(); + Serial.print(F("TXVolts ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + TXTemperature = (int8_t) readTempDS18B20(); + TXErrors = readMemoryUint16(addr_TXErrors); + + dtostrf(TXLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER); + dtostrf(TXLon, 7, 5, LonArray); //converts float to character array + + len = sizeof(TXBUFFER); + memset(TXBUFFER, 0, len); //clear array to 0s + Count = snprintf((char*) TXBUFFER, + TXBUFFER_SIZE, + "$%s,%lu,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%d,%d,%d,%lu", + FlightID, + TXSequence, + TXHours, + TXMinutes, + TXSeconds, + LatArray, + LonArray, + TXAlt, + TXSatellites, + TXVolts, + TXTemperature, + TXResets, + TXStatus, + TXErrors, + TXGPSfixms + ); + + CRC = 0xffff; //start value for CRC16 + + for (index = 1; index < Count; index++) //element 1 is first character after $ at start (for LoRa) + { + CRC ^= (((uint16_t)TXBUFFER[index]) << 8); + for (j = 0; j < 8; j++) + { + if (CRC & 0x8000) + CRC = (CRC << 1) ^ 0x1021; + else + CRC <<= 1; + } + } + + TXBUFFER[Count++] = '*'; + TXBUFFER[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end + TXBUFFER[Count++] = Hex((CRC >> 8) & 15); + TXBUFFER[Count++] = Hex((CRC >> 4) & 15); + TXBUFFER[Count] = Hex(CRC & 15); + return Count; +} + + +char Hex(uint8_t lchar) +{ + //used in CRC calculation in buildHABPacket + char Table[] = "0123456789ABCDEF"; + return Table[lchar]; +} + + +uint8_t buildLocationOnly(float Lat, float Lon, uint16_t Alt, uint8_t stat) +{ + uint8_t len; + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationBinaryPacket); //identify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeInt16(Alt); //add altitude + LT.writeUint8(stat); //add tracker status + len = LT.endWriteSXBuffer(); //close buffer write + return len; +} + + +void reporttransmitError() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F("TXError,")); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + incMemoryUint16(addr_TXErrors); //increase the error count + setStatusByte(LORAError, 1); +} + + +void incMemoryUint32(uint32_t addr) +{ + uint32_t val = readMemoryUint32(addr); + val++; + writeMemoryUint32(addr, val); +} + + +void incMemoryUint16(uint32_t addr) +{ + uint16_t val = readMemoryUint16(addr); + val++; + writeMemoryUint16(addr, val); +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +uint8_t readConfigByte(uint8_t bitnum) +{ + return bitRead(Default_config1, bitnum); +} + + +void setTrackerMode() +{ + Serial.println(F("setTrackerMode")); + LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation); +} + + +void setSearchMode() +{ + Serial.println(F("setSearchMode")); + LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation); +} + + +uint8_t sendCommand(char cmd) +{ + uint8_t len; + TXVolts = readSupplyVoltage(); + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + Serial.println(); + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + LT.writeUint8(cmd); //this byte defines the packet type + LT.writeUint8(Broadcast); //destination address of the packet, the receivers address + LT.writeUint8(ThisNode); //source address of this node + LT.writeUint16(TXVolts); //add the battery voltage + LT.writeUint8(TXStatus); //add the status byte + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, len, 5000, TrackerTXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void clearAllMemory() +{ + //clears the whole of non-volatile + Serial.println(F("Clear Memory")); + fillMemory(addr_StartMemory, addr_EndMemory, 0); +} + + +float readTempDS18B20() +{ + float DS18B20TXTemperature; + sensor.requestTemperatures(); + DS18B20TXTemperature = sensor.getTempCByIndex(0); + return DS18B20TXTemperature; +} + + +void printTempDS18B20() +{ + float DS18B20TXTemperature; + DS18B20TXTemperature = readTempDS18B20(); + Serial.print(F("Temperature ")); + Serial.print(DS18B20TXTemperature, 1); + Serial.println(F("c")); +} + + +void printSupplyVoltage() +{ + //get and display supply volts on terminal or monitor + Serial.print(F("Volts ")); + Serial.print(readSupplyVoltage()); + Serial.println(F("mV")); +} + + +uint16_t readSupplyVoltage() +{ + //relies on internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit + } + + analogReference(INTERNAL); + temp = analogRead(SupplyAD); + + for (index = 0; index <= 9; index++) //sample AD 10 times + { + temp = analogRead(SupplyAD); + volts = volts + temp; + delay(10); + } + volts = ( (float) (volts / 10) * ADMultiplier); + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn MOSFET connection resitor divider in circuit + } + + return volts; +} + + +//*********************************************************** +// Start GPS Functions +//*********************************************************** + +void GPSTest() +{ + uint8_t GPSchar; + uint32_t startmS; + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < 2000) //allows for millis() overflow + { + if (GPSserial.available() > 0) + { + GPSchar = GPSserial.read(); + Serial.write(GPSchar); + } + } + Serial.println(); + Serial.println(); + Serial.flush(); +} + + +bool gpsWaitFix(uint16_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + + uint32_t startmS, waitmS; + uint8_t GPSchar; + + Serial.flush(); + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.println(F("s ")); + Serial.flush(); + + GPSOutputOn(); + + waitmS = waitSecs * 1000; + 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()) + { + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = (uint16_t) gps.altitude.meters(); + + //Altitude is used as an unsigned integer, so that the binary payload is as short as possible. + //However gps.altitude.meters(); can return a negative value which converts to + //65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero + + if (TXAlt > 60000) + { + TXAlt = 0; + } + + TXHours = gps.time.hour(), + TXMinutes = gps.time.minute(), + TXSeconds = gps.time.second(), + TXSatellites = gps.satellites.value(); + + setStatusByte(GPSFix, 1); + + TXGPSfixms = millis() - GPSstartms; + + Serial.flush(); + Serial.println(); + Serial.print(F("Have GPS Fix ")); + Serial.print(TXGPSfixms); + Serial.print(F("mS")); + Serial.println(); + GPSprintTime(); + GPSprintDate(); + Serial.flush(); + + return true; + } + + } + + //if here then there has been no fix and a timeout + GPSOutputOff(); + setStatusByte(GPSFix, 0); //set status bit to flag no fix + incMemoryUint16(addr_TXErrors); + Serial.println(F("Error No GPS Fix")); + return false; +} + +void GPSprintTime() +{ + uint8_t hours, mins, secs; + hours = gps.time.hour(); + mins = gps.time.minute(); + secs = gps.time.second(); + + 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.println(secs); +} + + +void GPSprintDate() +{ + Serial.print(F("Date ")); + Serial.print(gps.date.day()); + Serial.print(F("/")); + Serial.print(gps.date.month()); + Serial.print(F("/")); + Serial.println(gps.date.year()); +} + +void GPSOutputOn() +{ + GPSserial.begin(GPSBaud); + while (GPSserial.available()) GPSserial.read(); //make sure input buffer is empty +} + + +void GPSOutputOff() +{ + //turns off serial output from GPS + GPSserial.end(); +} + + + + +//*********************************************************** +// End GPS Functions +//*********************************************************** + + +void setup() +{ + uint32_t i; + uint16_t j; + + Serial.begin(115200); //Setup Serial console ouput + Serial.println(); + Serial.println(); + Serial.println(F("67_HAB_Balloon_Tracker_Transmitter Starting")); + + memoryStart(Memory_Address); //setup the memory + j = readMemoryUint16(addr_ResetCount); + j++; + writeMemoryUint16(addr_ResetCount, j); + j = readMemoryUint16(addr_ResetCount); + + Serial.print(F("TXResets ")); + Serial.println(j); + + if (GPSPOWER >= 0) //if GPS needs power switching, turn it on + { + pinMode(GPSPOWER, OUTPUT); + digitalWrite(GPSPOWER, GPSONSTATE); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); //for MOSFET controlling battery volts resistor divider + } + +#ifdef QUECTELINUSE + Serial.println(F("Quectel GPS library")); +#endif + +#ifdef UBLOXINUSE + Serial.println(F("UBLOX GPS library")); +#endif + +#ifdef ClearAllMemory + clearAllMemory(); +#endif + + SPI.begin(); //initialize SPI + + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + led_Flash(2, 125); + } + else + { + Serial.println(F("LoRa Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + setTrackerMode(); + + Serial.print(F("Config ")); + Serial.println(Default_config1, BIN); + + j = readMemoryUint16(addr_TXErrors); + Serial.print(F("TXErrors ")); + Serial.println(j); + + Serial.print(F("TXSequence ")); + i = readMemoryUint32(addr_SequenceNum); + Serial.println(i); + + Serial.print(F("ThisNode ")); + Serial.println(ThisNode); + + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + + Serial.println(); + printSupplyVoltage(); + printTempDS18B20(); + Serial.println(); + + TXStatus = 0; //clear all TX status bits + + sendCommand(PowerUp); //send power up command, includes supply mV and config, on tracker settings + + GPSOutputOn(); + Serial.println(); + Serial.println(F("GPS output test")); + Serial.flush(); + GPSTest(); //copy GPS output to serial monitor as a test + + delay(2000); + + GPSstartms = millis(); + + setTrackerMode(); //so that commands indicating wait for a GPS go out + + while (!gpsWaitFix(5)) //wait for the initial GPS fix, this could take a while + { + sendCommand(NoFix); + led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix + } + + LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones + digitalWrite(LED1, HIGH); + LT.toneFM(500, 2000, deviation, adjustfreq, TrackerTXpower); + digitalWrite(LED1, LOW); + GPSOutputOn(); + delay(2000); //GPS may be in software backup allow time for it to wakeup + GPSOutputOff(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/69_Balloon_Tracker_Transmitter_GenericGPS/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/69_Balloon_Tracker_Transmitter_GenericGPS/Settings.h new file mode 100644 index 0000000..328190c --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/69_Balloon_Tracker_Transmitter_GenericGPS/Settings.h @@ -0,0 +1,137 @@ + /******************************************************************************************************* + 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. +*******************************************************************************************************/ + +//************************************************************************************************** +// 1) Hardware related definitions and options - specify lora board type and pins here +//************************************************************************************************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitions to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done +#define LED1 8 //On board LED, high for on +#define BATVREADON 8 //Pin that turns on the resistor divider to read battery volts +#define ONE_WIRE_BUS 4 //for DS18B20 temperature sensor +#define ADMultiplier 5.25 //adjustment to convert into mV of battery voltage. for 100K\10K divider +#define SupplyAD A0 //Resistor divider for battery connected here + +#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 powers GPS on\off, 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 + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//************************************************************************************************** +// 2) Program Options +//************************************************************************************************** + +//#define ClearAllMemory //Clears memory of stored tracker information, counts, errors etc + +//************************************************************************************************** +// 3) LoRa modem settings +//************************************************************************************************** + +//LoRa Modem Parameters +const uint32_t Offset = 0; //offset frequency for calibration purposes + +//Tracker mode +const uint32_t TrackerFrequency = 434000000; //frequency of transmissions +const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t TrackerTXpower = 10; //LoRa TX power in dBm + +//Search mode +const uint32_t SearchFrequency = 434000000; //frequency of transmissionsconst +uint8_t SearchBandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate +const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting +const int8_t SearchTXpower = 10; //LoRa TX power in dBm + +const uint16_t deviation = 10000; //deviation in hz for FM tones +const float adjustfreq = 0.9; //adjustment to tone frequency + +const uint8_t TXBUFFER_SIZE = 128; //defines the maximum size of the trasnmit buffer; + + +//************************************************************************************************** +// 4) GPS Options - Settings for a generic GPS, no attempt is made to put the GPS into balloon mode +//************************************************************************************************** + +#define GPSBaud 9600 //GPS Baud rate + +#define USESOFTSERIALGPS //if your using software serial for the GPS, enable this define + +//#define USEHARDWARESERIALGPS //if your using hardware serial for the GPS, enable this define +#define HARDWARESERIALPORT Serial1 //if your using hardware serial for the GPS, define the port here + +const uint16_t WaitGPSFixSeconds = 60; //when in flight the time to wait for a new GPS fix + +//************************************************************************************************** +// 5) FSK RTTY Settings +//************************************************************************************************** + +uint32_t FrequencyShift = 500; //hertz frequency shift, approx, sent at nearest 61.03515625hz step +uint8_t NumberofPips = 4; //number of marker pips to send +uint16_t PipDelaymS = 1000; //mS between pips when carrier is off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 1000; //ms of leadin constant shifted carrier + + +//**************************************************************************************************** +// 6) Program Default Option settings - This section determines which options are on or off by default, +// these are saved in the Default_config1 byte. These options are set in this way so that it is +// possible (in future program changes) to alter the options remotly. +//************************************************************************************************** + +uint8_t OptionOff = 0; +uint8_t OptionOn = 1; + +const char option_SearchEnable = OptionOn; //set to OptionOn to enable transmit of Search mode packet +const char option_FSKRTTYEnable = OptionOn; //set to OptionOn to enable transmit of FSKRTTY + +#define option_SearchEnable_SUM (option_SearchEnable*1) +#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4) + +const uint16_t Default_config1 = (option_SearchEnable_SUM + option_FSKRTTYEnable_SUM); +//const uint16_t Default_config1 = 0x05; //Phew, the default config can always be set manually........ + //0x05 would turn on transmit of search mode and FSKRTTY + + +//************************************************************************************************** +// 7) Memory settings - define the type of memory to use for non-Volatile storage. +// Default is internal ATmega device EEPROM but EEPROM has a limited write endurance of 'only' +// 100,000 writes. Since the non-Volatile memory selected is written to at each transmission loop +// and error, its highly recommended to use one of the FRAM options, these have an endurance of +// 100,000,000,000,000 writes. +//************************************************************************************************** + +#define Memory_Library +//#define Memory_Library +//#define Memory_Library + +int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM + +//************************************************************************************************** +// 8) HAB Flight Settings +//************************************************************************************************** + +char FlightID[] = "Flight1"; //flight ID for HAB packet + +const uint16_t SleepTimesecs = 13; //sleep time in seconds after each TX loop + +const char ThisNode = '1'; //tracker number for search packet + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/70_AFSKRTTY_Upload_Test/70_AFSKRTTY_Upload_Test.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/70_AFSKRTTY_Upload_Test/70_AFSKRTTY_Upload_Test.ino new file mode 100644 index 0000000..422c8d8 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/70_AFSKRTTY_Upload_Test/70_AFSKRTTY_Upload_Test.ino @@ -0,0 +1,98 @@ +/******************************************************************************************************* + 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 test program has been written to check that the hardware for sending AFSK RTTY on + been connected correctly. AFSKRTTY can be used to upload packets received from a high altitude balloon + tracker as LoRa into DL-FLDIGI running on a PC and from there uploaded to an Internet connected tracking + system. + + The AFSK RTTY library has been tested and will work on an Arduion Pro Mini 8Mhz, Arduino DUE and ESP32 + when used with this startup command; + + startAFSKRTTY(AUDIOOUTpin, CHECKpin, 5, 1000, 7, 714, 0, 1000); + + This outputs AFSKRTTY at 200baud, 7 databits, 1 startbit, 2 stopbits, no parity, low tone 1000hz, hightone 1400hz. + + The audio comes out of the pin passed via AUDIOOUTpin and the bit timing can be checked by looking at + the CHECKpin on a scope or analyser. + + A low pass filter consiting of a deries 47K resistor and parallel 470nF capacitor was used to reduce the output + for feeding into a PC soundcard. + + A screenshot of the FLDIGI settings used is in the folder containing this program; 'AFSKRTTY2_DL-Fldigi_Settings.jpg' + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#include //AFSK RTTY library for microcontrollers without the tone() function + +//Choose whichever test pattern takes your fancy +//uint8_t testBuffer[] = "0123456789* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"; +//uint8_t testBuffer[] = "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"; +uint8_t testBuffer[] = "$$$$MyFlight1,2213,14:54:37,51.48230,-3.18136,15,6,3680,23,66,3,0*2935"; + + + +const uint16_t leadinmS = 1000; //number of ms for AFSK constant lead in tone +const uint16_t leadoutmS = 0; //number of ms for AFSK constant lead out tone + + +const uint16_t LOWPERIODUS = 1000; //actual period in uS of to give a 200baud +const uint8_t LOWCYCLES = 5; //cycles of low frequency tone for 200baud +const uint16_t HIGHPERIODUS = 714; //actual high period in uS to give a 200baud +const uint8_t HIGHCYCLES = 7; //cycles of high frequency tone for 200baud +const int8_t ADJUSTUS = 0; //uS to subtract from tone generation loop to match frequency + +const int8_t AUDIOOUT = 6; //pin used to output Audio tones +const int8_t CHECK = 8; //this pin is toggled inside the AFSKRTTY library, high for logic 1, low for logic 0, so it can be used to check the timing. + + +void loop() +{ + uint8_t index; + uint8_t chartosend; + uint8_t len = sizeof(testBuffer) - 1; //must NOT send null at end of buffer + + Serial.print(F("Sending AFSK RTTY ")); + Serial.flush(); + + startAFSKRTTY(AUDIOOUT, CHECK, LOWCYCLES, LOWPERIODUS, HIGHCYCLES, HIGHPERIODUS, ADJUSTUS, leadinmS); + + sendAFSKRTTY(13); + sendAFSKRTTY(10); + + for (index = 0; index < len; index++) + { + chartosend = testBuffer[index]; + sendAFSKRTTY(chartosend); + Serial.write(chartosend); + } + + sendAFSKRTTY(13); + sendAFSKRTTY(10); + + endAFSKRTTY(AUDIOOUT, CHECK, leadoutmS); + + digitalWrite(CHECK, LOW); + Serial.println(); + delay(1000); +} + + +void setup() +{ + pinMode(CHECK, OUTPUT); //setup pin as output for indicator LED + + Serial.begin(9600); + Serial.println(); + Serial.println(F("70_AFSKRTTY_Upload_Test")); + Serial.println(); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/70_AFSKRTTY_Upload_Test/AFSKRTTY2_DL-Fldigi_Settings.jpg.jpg b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/70_AFSKRTTY_Upload_Test/AFSKRTTY2_DL-Fldigi_Settings.jpg.jpg new file mode 100644 index 0000000..b428c9d Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/70_AFSKRTTY_Upload_Test/AFSKRTTY2_DL-Fldigi_Settings.jpg.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/71_FSKRTTY_Transmitter_Test/71_FSKRTTY_Transmitter_Test.ino b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/71_FSKRTTY_Transmitter_Test/71_FSKRTTY_Transmitter_Test.ino new file mode 100644 index 0000000..e0df1a6 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/71_FSKRTTY_Transmitter_Test/71_FSKRTTY_Transmitter_Test.ino @@ -0,0 +1,183 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 23/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 test program for using the LoRa device to transmit upper side band FSK + RTTY. With the LoRa device in FSK direct mode, the frequency of the generated carrier is shifted up + or down at the correct baud rate depending on whether a logic 0 or 1 is being sent. + + The desired shift in frequency is defined in the Settings.h file as 'FrequencyShift'. When the program + starts the actual frequency shift will be calculated according to the discrete frequency steps the + LoRa device can be set to. This example uses the library function for sending FSKRTTY that is fixed at + 7 databits, 1 stop bit and no parity bit. If you want to vary these settings see the example; + '78_FSKRTTY_Transmitter_Test_Configurable.ino' + + Before the actual data transmission starts you can send a series of marker pips which are short bursts + of up shifted carrier which will be heard as beeps in a correctly tuned receiver. These pips can aid + in setting the receiver decode frequemcy to match the transmission. on some LoRa devices, such as the SX127x + series there can be considerable temperature induced frequency drift. This drift can be caused by outside + temperature changes or the RF device self heating when transmit is turned on. The duration of the pips, + the gaps between them and the period of leadin carrier before the data starts can all be set. To send no + pips just set the number to 0. + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include //the lora device is SPI based +#include //include the appropriate SX12XX library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX127XLT LT; //create a library class instance called LT + +//Choose whichever test pattern takes your fancy +//uint8_t testBuffer[] = "0123456789* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"; //This string is sent as AFSK RTTY, 7 bit, 2 Stop bit, no parity, 300 baud. + +//uint8_t testBuffer[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789"; +//uint8_t testBuffer[] = "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"; +uint8_t testBuffer[] = "$$$$MyFlight1,2213,14:54:37,51.48230,-3.18136,15,6,3680,23,66,3,0*2935"; + +uint8_t freqShiftRegs[3]; //to hold returned registers that set frequency + + +void loop() +{ + uint8_t index; + + printRegisterSetup(FrequencyShift); + Serial.println(); + + LT.setupDirect(Frequency, Offset); + LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS); + + Serial.print(F("Start RTTY micros() = ")); + Serial.println(micros()); + Serial.print(F("Seconds to overflow ")); + Serial.println(((0xFFFFFFFF - micros()) / 1E6),0); + + LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed + + for (index = 0; index < (sizeof(testBuffer)-1); index++) + { + LT.transmitFSKRTTY(testBuffer[index], BaudPerioduS, LED1); + Serial.write(testBuffer[index]); + } + LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return + LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed + + Serial.println(); + Serial.print(F("END RTTY micros() = ")); + Serial.println(micros()); + digitalWrite(LED1, LOW); + Serial.println(); + Serial.println(); + + LT.setMode(MODE_STDBY_RC); + + delay(2000); +} + + +void printRegisterSetup(uint32_t shift) +{ + + uint32_t nonShiftedFreq, ShiftedFreq; + uint32_t freqShift; + float exactfreqShift; + + LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set + LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values + nonShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2]; + Serial.print(F("NoShift Registers 0x")); + Serial.println(nonShiftedFreq, HEX); + + LT.setRfFrequency((Frequency + shift), Offset); //set shifted frequecy + LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values + ShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2]; + Serial.print(F("Shifted Registers 0x")); + Serial.println(ShiftedFreq, HEX); + + freqShift = ShiftedFreq - nonShiftedFreq; + exactfreqShift = freqShift * FREQ_STEP; + Serial.print(F("FSKRTTY register shift ")); + Serial.println(freqShift,HEX); + Serial.print(F("FSKRTTY frequency shift ")); + Serial.print(exactfreqShift, 8); + Serial.println(F("hZ")); + + LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set +} + + +void printRegisterBuffer() +{ +Serial.print(freqShiftRegs[0],HEX); +Serial.print(F(" ")); +Serial.print(freqShiftRegs[1],HEX); +Serial.print(F(" ")); +Serial.print(freqShiftRegs[2],HEX); +Serial.println(); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("71_FSKRTTY_Transmitter_Test")); + + SPI.begin(); + + //SPI beginTranscation is normally part of library routines, but if it is disabled in library + //a single instance is needed here, so uncomment the program line below + //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); + + //setup hardware pins used by device, then check if device is found + if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); //two further quick LED flashes to indicate device found + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed LED flash indicates device error + } + } + + LT.setupDirect(Frequency, Offset); + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/71_FSKRTTY_Transmitter_Test/Settings.h b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/71_FSKRTTY_Transmitter_Test/Settings.h new file mode 100644 index 0000000..2ceaa7f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX127x_examples/Tracker/71_FSKRTTY_Transmitter_Test/Settings.h @@ -0,0 +1,45 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 23/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. +*******************************************************************************************************/ + +//******* 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 are not used by this particular sketch so they are set to -1 and not connected. + +#define NSS 10 //select pin on LoRa device +#define NRESET 9 //reset pin on LoRa device +#define LED1 4 //on board LED, high for on +#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using + + +//******* Setup Direct Modem Parameters Here ! *************** + +const uint32_t Frequency = 434000000; //frequency of transmissions in hertz +const uint32_t Offset = 0; //offset frequency for calibration purposes +const uint16_t deviation = 10000; //deviation, total frequency shift low to high +const float adjustfreq = 0.9; //adjustment to tone frequency + +const int8_t TXpower = 10; //LoRa transmit power in dBm + + +//******* Setup FSKRTTY Settings here ! *************** + +uint32_t FrequencyShift = 500; //hertz frequency shift, approx, sent at nearest 61.03515625hz step +uint8_t NumberofPips = 2; //number of marker pips to send +uint16_t PipDelaymS = 500; //mS between pips, carrier off +uint16_t PipPeriodmS = 100; //mS length of pip +uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud +uint16_t LeadinmS = 2000; //ms of leadin, shifted carrier +uint8_t DataBits = 7; //number of databits, normally 7 or 8 +uint8_t StopBits = 2; //number of stopbits, normally 1 or 2 +uint8_t Parity = ParityNone; //parity on data bits, ParityNone, ParityOdd, ParityEven, ParityZero, ParityOne + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/103_LoRa_Transmitter_Detailed_Setup.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/103_LoRa_Transmitter_Detailed_Setup.ino new file mode 100644 index 0000000..2671efb --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/103_LoRa_Transmitter_Detailed_Setup.ino @@ -0,0 +1,182 @@ +/******************************************************************************************************* + 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 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.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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, 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); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_LORA); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); + //*************************************************************************************************** + + + 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 0x900 to 0x9FF + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/Settings.h new file mode 100644 index 0000000..c73ec3e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/103_LoRa_Transmitter_Detailed_Setup/Settings.h @@ -0,0 +1,42 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/104_LoRa_Receiver_Detailed_Setup.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/104_LoRa_Receiver_Detailed_Setup.ino new file mode 100644 index 0000000..5adadb8 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/104_LoRa_Receiver_Detailed_Setup.ino @@ -0,0 +1,247 @@ +/******************************************************************************************************* + 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 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.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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, 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); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_LORA); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); + //*************************************************************************************************** + + + 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 0x900 to 0x9FF + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/Settings.h new file mode 100644 index 0000000..3f4205d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/104_LoRa_Receiver_Detailed_Setup/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + 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 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 SX128X devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX128X devices, set to -1 if not used +#define LED1 8 //on board LED, high for on +#define BUZZER -1 //pin for buzzer, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino new file mode 100644 index 0000000..3592352 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/14_LoRa_Structure_TX/14_LoRa_Structure_TX.ino @@ -0,0 +1,145 @@ +/******************************************************************************************************* + 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 - 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 +#include +#include "Settings.h" + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/14_LoRa_Structure_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/14_LoRa_Structure_TX/Settings.h new file mode 100644 index 0000000..6e4d27d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/14_LoRa_Structure_TX/Settings.h @@ -0,0 +1,39 @@ +/******************************************************************************************************* + 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. +*******************************************************************************************************/ + +//******* 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +#define TXpower 10 //power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino new file mode 100644 index 0000000..7e68538 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/15_LoRa_Structure_RX/15_LoRa_Structure_RX.ino @@ -0,0 +1,194 @@ +/******************************************************************************************************* + 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 - 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 +#include +#include "Settings.h" + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.print(F("Receiver ready")); + Serial.println(); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/15_LoRa_Structure_RX/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/15_LoRa_Structure_RX/Settings.h new file mode 100644 index 0000000..77ba17c --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/15_LoRa_Structure_RX/Settings.h @@ -0,0 +1,38 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +#define TXpower 10 //power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/1_LED_Blink/1_LED_Blink.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/1_LED_Blink/1_LED_Blink.ino new file mode 100644 index 0000000..2865c0a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/1_LED_Blink/1_LED_Blink.ino @@ -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")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/2_Register_Test/2_Register_Test.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/2_Register_Test/2_Register_Test.ino new file mode 100644 index 0000000..90cb393 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/2_Register_Test/2_Register_Test.ino @@ -0,0 +1,375 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 11/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 SX128X LoRa devices. + + The program checks that a SX128X 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, SX1280 or SX1281 + 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 + 0x900 80 0C 7B 02 20 FA C0 00 00 80 00 00 00 00 00 FF + 0x910 FF FF 00 00 00 19 00 00 00 19 87 65 43 21 7F FF + 0x920 FF FF FF 0C 70 37 0A 50 D0 80 00 C0 5F D2 8F 0A + 0x930 00 C0 00 00 00 24 00 21 28 B0 30 09 1A 59 70 08 + 0x940 58 0B 32 0A 14 24 6A 96 00 18 00 00 00 00 00 00 + 0x950 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x960 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF + 0x970 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 04 + 0x980 00 0B 18 70 00 00 00 4C 00 F0 64 00 00 00 00 00 + 0x990 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x9A0 00 08 EC B8 9D 8A E6 66 06 00 00 00 00 00 00 00 + 0x9B0 00 08 EC B8 9D 8A E6 66 06 00 00 00 00 00 00 00 + 0x9C0 00 16 00 3F E8 01 FF FF FF FF 5E 4D 25 10 55 55 + 0x9D0 55 55 55 55 55 55 55 55 55 55 55 55 55 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 2495996672hz + Change Frequency to 2445000000hz + Frequency now 2444999936hz + + Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x900 80 0C 7B 02 20 FA BC 13 C1 80 00 00 00 00 00 61 + +Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +const uint16_t REG_RFFrequency23_16 = 0x906; +const uint16_t REG_RFFrequency15_8 = 0x907; +const uint16_t REG_RFFrequency7_0 = 0x908; +const uint8_t RADIO_WRITE_REGISTER = 0x18; +const uint8_t RADIO_READ_REGISTER = 0x19; +const uint8_t RADIO_SET_RFFREQUENCY = 0x86; //commnad to change frequency +const uint8_t RADIO_SET_PACKETTYPE = 0x8A; //commnad to set packet mode +const float FREQ_STEP = 198.364; +const uint8_t PACKET_TYPE_LORA = 0x01; + +//********* 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 //SX128X device select +#define NRESET 9 //SX128X reset pin +#define RFBUSY 7 //SX128X busy pin +#define LED1 8 //for on board LED, put high for on + +//**************************************************************/ + + +#include + +uint8_t saveddevice; + + +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 pins are not used in this example so are set to -1 + + if (begin(NSS, NRESET, RFBUSY, -1, -1, -1, 0)) + { + Serial.println(F("LoRa Device found")); + } + else + { + Serial.println(F("No device responding")); + } +} + + +void loop() +{ + uint32_t frequency; + resetDevice(); //reset the device + Serial.println(F("Registers at reset")); //show the all registers following a reset + printRegisters(0x0900, 0x09FF); + Serial.println(); + Serial.println(); + + frequency = getFreqInt(); //read the set frequency following a reset + Serial.print(F(" Frequency at reset ")); + Serial.print(frequency); + Serial.println(F("hz")); + + Serial.print(F("Change Frequency to 2445000000hz")); + setPacketType(PACKET_TYPE_LORA); //this is needed to ensure frequency change is reflected in register print + setRfFrequency(2445000000, 0); //change the frequency to 2445000000hertz + + frequency = getFreqInt(); //read back the changed frequency + Serial.println(); + Serial.print(F(" Frequency now ")); + Serial.print(frequency); //print the changed frequency, did the write work (allow for rounding errors) ? + Serial.println(F("hz")); + Serial.println(); + printRegisters(0x0900, 0x090F); //show the registers after frequency change + 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, return as long integer + uint8_t Msb, Mid, Lsb; + uint32_t uinttemp; + float floattemp; + Msb = readRegister(REG_RFFrequency23_16); + Mid = readRegister(REG_RFFrequency15_8); + Lsb = readRegister(REG_RFFrequency7_0); + floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb); + floattemp = ((floattemp * FREQ_STEP) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +void printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of SX128x 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) +{ + frequency = frequency + offset; + uint8_t buffer[3]; + uint32_t freqtemp = 0; + freqtemp = ( uint32_t )( (float) frequency / (float) FREQ_STEP); + buffer[0] = ( uint8_t )( ( freqtemp >> 16 ) & 0xFF ); + buffer[1] = ( uint8_t )( ( freqtemp >> 8 ) & 0xFF ); + buffer[2] = ( uint8_t )( freqtemp & 0xFF ); + writeCommand(RADIO_SET_RFFREQUENCY, buffer, 3); + writeCommand(RADIO_SET_RFFREQUENCY, buffer, 3); +} + + +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() +{ + 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, uint8_t device) +{ + saveddevice = device; + + pinMode(pinNSS, OUTPUT); + digitalWrite(pinNSS, HIGH); + pinMode(pinNRESET, OUTPUT); + digitalWrite(pinNRESET, HIGH); + pinMode(pinRFBUSY, INPUT); + + if (pinDIO1 >= 0) + { + pinMode( pinDIO1, INPUT); + } + + if (pinDIO2 >= 0) + { + pinMode(pinDIO2, INPUT); + } + + if (pinDIO3 >= 0) + { + pinMode(pinDIO3, INPUT); + } + + resetDevice(); + + 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(0x0908); //low byte of frequency setting + writeRegister(0x0908, (Regdata1 + 1)); + Regdata2 = readRegister(0x0908); //read changed value back + writeRegister(0x0908, 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]); + //Serial.println(buffer[index], HEX); + } + digitalWrite(NSS, HIGH); + + checkBusy(); +} + +void setPacketType(uint8_t packettype) +{ + writeCommand(RADIO_SET_PACKETTYPE, &packettype, 1); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino new file mode 100644 index 0000000..1183b43 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/3_LoRa_Transmitter/3_LoRa_Transmitter.ino @@ -0,0 +1,183 @@ +/******************************************************************************************************* + 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 is a simple 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 Serial Monitor, together with the transmit + power used, the packet length and the CRC of the packet. The matching receive program, '4_LoRa_Receive' + can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h) + must be the same for the Transmit and Receive program. Sample Serial Monitor output; + + 10dBm Packet> {packet contents*} BytesSent,23 CRC,DAAB TransmitTime,54mS PacketsSent,1 + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the SX128X device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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, timeout 10 seconds + { + endmS = millis(); //packet sent, note end time + TXPacketCount++; + packet_is_OK(); + } + else + { + packet_is_Error(); //transmit packet returned 0, there was an error + } + + digitalWrite(LED1, LOW); + Serial.println(); + delay(packet_delay); //have a delay between packets +} + + +void packet_is_OK() +{ + //if here packet has been sent OK + uint16_t localCRC; + + Serial.print(F(" BytesSent,")); + Serial.print(TXPacketL); //print transmitted packet length + localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF); + Serial.print(F(" CRC,")); + Serial.print(localCRC, HEX); //print CRC of sent packet + Serial.print(F(" TransmitTime,")); + Serial.print(endmS - startmS); //print transmit time of packet + Serial.print(F("mS")); + Serial.print(F(" PacketsSent,")); + Serial.print(TXPacketCount); //print total of packets sent OK +} + + +void packet_is_Error() +{ + //if here there was an error transmitting packet + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("3_LoRa_Transmitter 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, 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); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_LORA); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); + LT.setHighSensitivity(); + //LT.setLowPowerRX(); + //*************************************************************************************************** + + 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 + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/3_LoRa_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/3_LoRa_Transmitter/Settings.h new file mode 100644 index 0000000..8409182 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/3_LoRa_Transmitter/Settings.h @@ -0,0 +1,38 @@ +/******************************************************************************************************* + 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 set to -1. + +#define NSS 10 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino new file mode 100644 index 0000000..38148cb --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/4_LoRa_Receiver/4_LoRa_Receiver.ino @@ -0,0 +1,247 @@ +/******************************************************************************************************* + 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 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 Hello World 1234567890*,CRC,DAAB,RSSI,-61dBm,SNR,9dB,Length,23,Packets,1026,Errors,0,IRQreg,50 + + If there is a packet error it might look like this, which is showing a CRC error, + + 1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT LT; //create a library class instance called LT + +uint32_t RXpacketCount; +uint32_t errors; + +uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into + +uint8_t RXPacketL; //stores length of packet received +int8_t PacketRSSI; //stores RSSI of received packet +int8_t PacketSNR; //stores signal to noise ratio of received packet + + +void loop() +{ + RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout + + digitalWrite(LED1, HIGH); //something has happened + + if (BUZZER > 0) //turn buzzer on + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + PacketSNR = LT.readPacketSNR(); //read the received SNR value + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + digitalWrite(LED1, LOW); //LED off + + Serial.println(); +} + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + RXpacketCount++; + + printElapsedTime(); //print elapsed time to Serial Monitor + Serial.print(F(" ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER + Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC + Serial.print(localCRC, HEX); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(RXPacketL); + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + printElapsedTime(); //print elapsed time to Serial Monitor + + if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout + { + Serial.print(F(" RXTimeout")); + } + else + { + errors++; + Serial.print(F(" PacketError")); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); //print the names of the IRQ registers set + } + + delay(250); //gives a longer buzzer and LED flash for error + +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F("s")); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("4_LoRa_Receiver 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, 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); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_LORA); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); + LT.setHighSensitivity(); + //LT.setLowPowerRX(); + //*************************************************************************************************** + + + 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 + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/4_LoRa_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/4_LoRa_Receiver/Settings.h new file mode 100644 index 0000000..defe33f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/4_LoRa_Receiver/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //pin for BUZZER, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/52_FLRC_Transmitter/52_FLRC_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/52_FLRC_Transmitter/52_FLRC_Transmitter.ino new file mode 100644 index 0000000..bb534d9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/52_FLRC_Transmitter/52_FLRC_Transmitter.ino @@ -0,0 +1,180 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 09/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a test 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 + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the SX128X device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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, timeout 10 seconds + { + endmS = millis(); //packet sent, note end time + TXPacketCount++; + packet_is_OK(); + } + else + { + packet_is_Error(); //transmit packet returned 0, there was an error + } + + digitalWrite(LED1, LOW); + Serial.println(); + delay(packet_delay); //have a delay between packets +} + + +void packet_is_OK() +{ + //if here packet has been sent OK + uint16_t localCRC; + + Serial.print(F(" BytesSent,")); + Serial.print(TXPacketL); //print transmitted packet length + localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF); + Serial.print(F(" CRC,")); + Serial.print(localCRC, HEX); //print CRC of sent packet + Serial.print(F(" TransmitTime,")); + Serial.print(endmS - startmS); //print transmit time of packet + Serial.print(F("mS")); + Serial.print(F(" PacketsSent,")); + Serial.print(TXPacketCount); //print total of packets sent OK +} + + +void packet_is_Error() +{ + //if here there was an error transmitting packet + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + 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("52_FLRC_Transmitter 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, 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. + + //*************************************************************************************************** + //Setup FLRC + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_FLRC); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(BandwidthBitRate, CodingRate, BT); + LT.setPacketParams(PREAMBLE_LENGTH_32_BITS, FLRC_SYNC_WORD_LEN_P32S, RADIO_RX_MATCH_SYNCWORD_1, RADIO_PACKET_VARIABLE_LENGTH, 127, RADIO_CRC_3_BYTES, RADIO_WHITENING_OFF); + 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.setSyncWord1(Sample_Syncword); + //*************************************************************************************************** + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured modem 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 + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/52_FLRC_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/52_FLRC_Transmitter/Settings.h new file mode 100644 index 0000000..28822db --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/52_FLRC_Transmitter/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//FLRC Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t BandwidthBitRate = FLRC_BR_1_300_BW_1_2; //FLRC bandwidth and bit rate, 1.3Mbs +const uint8_t CodingRate = FLRC_CR_1_2; //FLRC coding rate +const uint8_t BT = RADIO_MOD_SHAPING_BT_1_0; //FLRC BT +const uint32_t Sample_Syncword = 0x01234567; //FLRC uses syncword + + +const int8_t TXpower = 0; //power for transmissions in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/53_FLRC_Receiver/53_FLRC_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/53_FLRC_Receiver/53_FLRC_Receiver.ino new file mode 100644 index 0000000..272d100 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/53_FLRC_Receiver/53_FLRC_Receiver.ino @@ -0,0 +1,240 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 09/02/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +/******************************************************************************************************* + Program Operation - This is a test 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 + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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 + + +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 + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + digitalWrite(LED1, LOW); //LED off + + Serial.println(); +} + + +void packet_is_OK() +{ + uint16_t IRQStatus, localCRC; + + IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register + + RXpacketCount++; + + printElapsedTime(); //print elapsed time to Serial Monitor + Serial.print(F(" ")); + LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters + + localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER + Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC + Serial.print(localCRC, HEX); + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("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("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",Packets,")); + Serial.print(RXpacketCount); + Serial.print(F(",Errors,")); + Serial.print(errors); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); //print the names of the IRQ registers set + } + + delay(250); //gives a longer buzzer and LED flash for error + +} + + +void printElapsedTime() +{ + float seconds; + seconds = millis() / 1000; + Serial.print(seconds, 0); + Serial.print(F("s")); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + 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("53_FLRC_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 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, 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. + + //*************************************************************************************************** + //Setup FLRC + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_FLRC); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(BandwidthBitRate, CodingRate, BT); + LT.setPacketParams(PREAMBLE_LENGTH_32_BITS, FLRC_SYNC_WORD_LEN_P32S, RADIO_RX_MATCH_SYNCWORD_1, RADIO_PACKET_VARIABLE_LENGTH, 127, RADIO_CRC_3_BYTES, RADIO_WHITENING_OFF); + 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.setSyncWord1(Sample_Syncword); + //*************************************************************************************************** + + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured modem 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 + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/53_FLRC_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/53_FLRC_Receiver/Settings.h new file mode 100644 index 0000000..bf67dc2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Basics/53_FLRC_Receiver/Settings.h @@ -0,0 +1,42 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//FLRC Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t BandwidthBitRate = FLRC_BR_1_300_BW_1_2; //FLRC bandwidth and bit rate, 1.3Mbs +const uint8_t CodingRate = FLRC_CR_1_2; //FLRC coding rate +const uint8_t BT = RADIO_MOD_SHAPING_BT_1_0; //FLRC BT +const uint32_t Sample_Syncword = 0x01234567; //FLRC uses syncword + +const int8_t TXpower = 0; //power for transmissions in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino new file mode 100644 index 0000000..fed73c0 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/10_LoRa_Link_Test_Transmitter.ino @@ -0,0 +1,266 @@ +/******************************************************************************************************* + 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 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 +#include +#include +#include "Settings.h" + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + 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 + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h new file mode 100644 index 0000000..9a23e28 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/10_LoRa_Link_Test_Transmitter/Settings.h @@ -0,0 +1,47 @@ +/******************************************************************************************************* + 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. + +#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 //SX128X 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 RX_EN -1 //pin for RX enable, used on some SX128X devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX128X devices, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +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, maximum +12dBm +const int8_t end_power = -18; //and ends at this power, minimum -18dBm +const uint8_t ThisNode = 'T'; //this identifies the node in transmissions + + +#define packet_delay 250 //mS delay between packets +#define mode_delaymS 2000 //mS delay after sending start test sequence + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino new file mode 100644 index 0000000..885b024 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/11_LoRa_Packet_Logger_Receiver.ino @@ -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 +#include +#include "Settings.h" +#include //get the library here; https://github.com/PaulStoffregen/Time +time_t recordtime; //used to record the current time, preventing displayed rollover on printing + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(); + LT.printModemSettings(); + Serial.println(); + LT.printOperatingSettings(); + Serial.println(); + Serial.println(); + printtime(); + Serial.print(F(" Receiver ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h new file mode 100644 index 0000000..05daf7f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/11_LoRa_Packet_Logger_Receiver/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + 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 DIO2, +//DIO3, 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //pin for buzzer, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino new file mode 100644 index 0000000..ea72ff3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/16_LoRa_RX_Frequency_Error_Check.ino @@ -0,0 +1,183 @@ +/******************************************************************************************************* + 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'. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h new file mode 100644 index 0000000..ae41040 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/16_LoRa_RX_Frequency_Error_Check/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + 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 DIO2, +//DIO3, 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino new file mode 100644 index 0000000..a33632a --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/20_LoRa_Link_Test_Receiver.ino @@ -0,0 +1,317 @@ +/******************************************************************************************************* + 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 - 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.0" + +#include //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc +#include + +SX128XLT 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[32]; //buffer where counts of received packets are stored, -18dbm to +12dBm +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+18]); + Test1Count[lTXpower+18] = 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 = 30; index >= 0; index--) + { + Serial.print(index-18); + Serial.print(F("dBm,")); + j = Test1Count[index]; + Serial.print(j); + Serial.print(F(" ")); + } + Serial.println(); + + Serial.print(F("CSV")); + for (index = 30; 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h new file mode 100644 index 0000000..3f23d16 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/20_LoRa_Link_Test_Receiver/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + 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. + + +#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 //SX128X 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 RX_EN -1 //pin for RX enable, used on some SX128X devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX128X devices, set to -1 if not used +#define BUZZER -1 //pin for buzzer, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino new file mode 100644 index 0000000..0196fd7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/33_LoRa_RSSI_Checker_With_Display.ino @@ -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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT LT; //create a library class instance called LT + +#include //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, DIO2, DIO3, RX_EN, TX_EN, 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); + + 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 + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h new file mode 100644 index 0000000..013c247 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/33_LoRa_RSSI_Checker_With_Display/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + 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 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //pin for BUZZER, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + +#define RXBUFFER_SIZE 32 //RX buffer size + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino new file mode 100644 index 0000000..db1b7a1 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/42_LoRa_Data_Throughput_Test_Transmitter.ino @@ -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; + + SX1280,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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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); + + 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(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h new file mode 100644 index 0000000..1ea3ea8 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter/Settings.h @@ -0,0 +1,42 @@ +/******************************************************************************************************* + 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 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes + +#define Bandwidth LORA_BW_1600 //LoRa bandwidth +#define SpreadingFactor LORA_SF5 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +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 = 16; //length of packet to send +const bool waitforACK = false; //set to true to have transmit wait for ack before continuing + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter_FLRC/42_LoRa_Data_Throughput_Test_Transmitter_FLRC.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter_FLRC/42_LoRa_Data_Throughput_Test_Transmitter_FLRC.ino new file mode 100644 index 0000000..cfa2942 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter_FLRC/42_LoRa_Data_Throughput_Test_Transmitter_FLRC.ino @@ -0,0 +1,294 @@ +/******************************************************************************************************* + 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; + + SX1280,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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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_FLRC 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 + } + } + + //*************************************************************************************************** + //Setup FLRC + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_FLRC); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(BandwidthBitRate, CodingRate, BT); + LT.setPacketParams(PREAMBLE_LENGTH_32_BITS, FLRC_SYNC_WORD_LEN_P32S, RADIO_RX_MATCH_SYNCWORD_1, RADIO_PACKET_VARIABLE_LENGTH, 127, RADIO_CRC_3_BYTES, RADIO_WHITENING_OFF); + 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.setSyncWord1(Sample_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(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter_FLRC/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter_FLRC/Settings.h new file mode 100644 index 0000000..d9bd38e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Diagnostic_and_Test/42_LoRa_Data_Throughput_Test_Transmitter_FLRC/Settings.h @@ -0,0 +1,42 @@ +/******************************************************************************************************* + 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 //DIO0 pin on LoRa device, used for RX and TX done + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes + +const uint8_t BandwidthBitRate = FLRC_BR_1_300_BW_1_2; //FLRC bandwidth and bit rate, 1.3Mbs +const uint8_t CodingRate = FLRC_CR_1_2; //FLRC coding rate +const uint8_t BT = RADIO_MOD_SHAPING_BT_1_0; //FLRC BT +const uint32_t Sample_Syncword = 0x01234567; //FLRC uses syncword +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 = 16; //length of packet to send +const bool waitforACK = false; //set to true to have transmit wait for ack before continuing + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/103_LoRa_Transmitter_Detailed_Setup_ESP32.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/103_LoRa_Transmitter_Detailed_Setup_ESP32.ino new file mode 100644 index 0000000..da118b2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/103_LoRa_Transmitter_Detailed_Setup_ESP32.ino @@ -0,0 +1,183 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_LORA); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); + //*************************************************************************************************** + + + 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 0x900 to 0x9FF + Serial.println(); + Serial.println(); + + Serial.print(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/Settings.h new file mode 100644 index 0000000..64e0f06 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/103_LoRa_Transmitter_Detailed_Setup_ESP32/Settings.h @@ -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 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 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 SX128X devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX128X devices, 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_SX1280 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + +const int8_t TXpower = 10; //LoRa transmit power in dBm + +const uint16_t packet_delay = 1000; //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/104_LoRa_Receiver_Detailed_Setup_ESP32.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/104_LoRa_Receiver_Detailed_Setup_ESP32.ino new file mode 100644 index 0000000..49b2924 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/104_LoRa_Receiver_Detailed_Setup_ESP32.ino @@ -0,0 +1,247 @@ +/******************************************************************************************************* + 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 //the lora device is SPI based so load the SPI library +#include //include the appropriate library +#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + //*************************************************************************************************** + //Setup LoRa device + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setRegulatorMode(USE_LDO); + LT.setPacketType(PACKET_TYPE_LORA); + LT.setRfFrequency(Frequency, Offset); + LT.setBufferBaseAddress(0, 0); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); + //*************************************************************************************************** + + + 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 0x900 to 0x9FF + Serial.println(); + Serial.println(); + + Serial.print(F("Receiver ready - RXBUFFER_SIZE ")); + Serial.println(RXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/Settings.h new file mode 100644 index 0000000..fed557e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Basics/104_LoRa_Receiver_Detailed_Setup_ESP32/Settings.h @@ -0,0 +1,51 @@ +/******************************************************************************************************* + 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 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 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 SX128X devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX128X devices, 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_SX1280 //we need to define the device we are using + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + +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 + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg new file mode 100644 index 0000000..19b2873 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Pictures/ESP32_Bare_Bones_Schematic.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg new file mode 100644 index 0000000..ff18459 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/Pictures/ESP32_Micro_Node.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/ReadMe.md b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/ReadMe.md new file mode 100644 index 0000000..f33e6f5 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/ESP32/ReadMe.md @@ -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. + +
+ +**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 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 + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino new file mode 100644 index 0000000..750455d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/8_LoRa_LowMemory_TX/8_LoRa_LowMemory_TX.ino @@ -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 +#include +#include "Settings.h" + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("Transmitter ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h new file mode 100644 index 0000000..8b628ea --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/8_LoRa_LowMemory_TX/Settings.h @@ -0,0 +1,38 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +#define TXpower 10 //power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino new file mode 100644 index 0000000..cc6e2ed --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/9_LoRa_LowMemory_RX/9_LoRa_LowMemory_RX.ino @@ -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 +#include +#include "Settings.h" + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h new file mode 100644 index 0000000..fce77b6 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/LowMemory/9_LoRa_LowMemory_RX/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //connect a buzzer here if wanted + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +#define TXpower 10 //power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets + +#define RXBUFFER_SIZE 255 //RX buffer size, not used in this program + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/Calibration_Values.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/Calibration_Values.jpg new file mode 100644 index 0000000..ca0893a Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/Calibration_Values.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/IMG_2531_Reduced.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/IMG_2531_Reduced.jpg new file mode 100644 index 0000000..e445c9f Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/IMG_2531_Reduced.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/SX128XLT_Ranging_100m.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/SX128XLT_Ranging_100m.jpg new file mode 100644 index 0000000..7ad7063 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/SX128XLT_Ranging_100m.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/SX128X_Ranging_Calibration_Values.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/SX128X_Ranging_Calibration_Values.jpg new file mode 100644 index 0000000..d6dc2d9 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Pictures/SX128X_Ranging_Calibration_Values.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/54_Ranging_Master/54_Ranging_Master.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/54_Ranging_Master/54_Ranging_Master.ino new file mode 100644 index 0000000..fbc09ed --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/54_Ranging_Master/54_Ranging_Master.ino @@ -0,0 +1,212 @@ +/***************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 16/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. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include +#include +#include "Settings.h" + +SX128XLT LT; + + +#ifdef ENABLEOLED +#include //https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 +#endif + + + +uint16_t rangeing_errors, rangeings_valid, rangeing_results; +uint16_t IrqStatus; +uint32_t endwaitmS, startrangingmS, range_result_sum, range_result_average; +float distance, distance_sum, distance_average; +bool ranging_error; +int32_t range_result; + + +void loop() +{ + uint8_t index; + distance_sum = 0; + range_result_sum = 0; + rangeing_results = 0; //count of valid results in each loop + + for (index = 1; index <= rangeingcount; index++) + { + + startrangingmS = millis(); + + LT.transmitRanging(RangingAddress, TXtimeoutmS, RangingTXPower, WAIT_TX); + + IrqStatus = LT.readIrqStatus(); + + if (IrqStatus & IRQ_RANGING_MASTER_RESULT_VALID) + { + rangeing_results++; + rangeings_valid++; + digitalWrite(LED1, HIGH); + Serial.print(F("Valid")); + range_result = LT.getRangingResultRegValue(RANGING_RESULT_RAW); + Serial.print(F(",Register,")); + Serial.print(range_result); + + if (range_result > 800000) + { + range_result = 0; + } + range_result_sum = range_result_sum + range_result; + + distance = LT.getRangingDistance(RANGING_RESULT_RAW, range_result, distance_adjustment); + distance_sum = distance_sum + distance; + + Serial.print(F(",Distance,")); + Serial.print(distance, 1); + digitalWrite(LED1, LOW); + } + else + { + rangeing_errors++; + distance = 0; + range_result = 0; + Serial.print(F("NotValid")); + Serial.print(F(",Irq,")); + Serial.print(IrqStatus, HEX); + } + delay(packet_delaymS); + + if (index == rangeingcount) + { + range_result_average = (range_result_sum / rangeing_results); + + if (rangeing_results == 0) + { + distance_average = 0; + } + else + { + distance_average = (distance_sum / rangeing_results); + } + + Serial.print(F(",TotalValid,")); + Serial.print(rangeings_valid); + Serial.print(F(",TotalErrors,")); + Serial.print(rangeing_errors); + Serial.print(F(",AverageRAWResult,")); + Serial.print(range_result_average); + Serial.print(F(",AverageDistance,")); + Serial.print(distance_average, 1); + +#ifdef ENABLEDISPLAY + display_screen1(); +#endif + + delay(2000); + + } + Serial.println(); + } + +} + +#ifdef ENABLEDISPLAY +void display_screen1() +{ + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Distance ")); + disp.print(distance_average, 1); + disp.print(F("m")); + disp.setCursor(0, 2); + disp.print(F("OK,")); + disp.print(rangeings_valid); + disp.print(F(",Err,")); + disp.print(rangeing_errors); +} +#endif + + +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(4, 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("54_Ranging_Master Starting")); + + SPI.begin(); + + led_Flash(2, 125); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, 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 flash indicates device error + } + } + + LT.setupRanging(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, RangingAddress, RANGING_MASTER); + + //LT.setRangingCalibration(Calibration); //override automatic lookup of calibration value from library table + +#ifdef ENABLEDISPLAY + Serial.println("Display Enabled"); + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + disp.setCursor(0, 0); + disp.print(F("Ranging RAW Ready")); + disp.setCursor(0, 1); + disp.print(F("Power ")); + disp.print(RangingTXPower); + disp.print(F("dBm")); + disp.setCursor(0, 2); + disp.print(F("Cal ")); + disp.print(Calibration); + disp.setCursor(0, 3); + disp.print(F("Adjust ")); + disp.print(distance_adjustment, 4); +#endif + + + Serial.print(F("Address ")); + Serial.println(RangingAddress); + Serial.print(F("CalibrationValue ")); + Serial.println(LT.getSetCalibrationValue()); + Serial.println(F("Ranging master RAW ready")); + + delay(2000); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/54_Ranging_Master/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/54_Ranging_Master/Settings.h new file mode 100644 index 0000000..d625341 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/54_Ranging_Master/Settings.h @@ -0,0 +1,47 @@ +/***************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 16/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 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions in hz +const int32_t Offset = 0; //offset frequency in hz for calibration purposes +const uint8_t Bandwidth = LORA_BW_0800; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint16_t Calibration = 11350; //Manual Ranging calibrarion value + +const uint8_t RangingTXPower = 10; //Transmit power used +const uint32_t RangingAddress = 16; //must match address in recever + +const uint16_t waittimemS = 10000; //wait this long in mS for packet before assuming timeout +const uint16_t TXtimeoutmS = 5000; //ranging TX timeout in mS +const uint16_t packet_delaymS = 0; //forced extra delay in mS between ranging requests +const uint16_t rangeingcount = 5; //number of times ranging is cqarried out for each distance measurment +float distance_adjustment = 1.0000; //adjustment factor to calculated distance + + +#define ENABLEOLED //enable this define to use display +#define ENABLEDISPLAY //enable this define to use display + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/55_Ranging_Slave/55_Ranging_Slave.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/55_Ranging_Slave/55_Ranging_Slave.ino new file mode 100644 index 0000000..1c4cc14 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/55_Ranging_Slave/55_Ranging_Slave.ino @@ -0,0 +1,147 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/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 - + + Serial monitor baud rate is set at 9600 +*******************************************************************************************************/ + +#define programversion "V1.0" + +#include +#include +#include "Settings.h" + +SX128XLT LT; + +uint32_t endwaitmS; +uint16_t IrqStatus; +uint32_t response_sent; + + +void loop() +{ + LT.receiveRanging(RangingAddress, 0, TXpower, NO_WAIT); + + endwaitmS = millis() + rangingRXTimeoutmS; + + while (!digitalRead(DIO1) && (millis() <= endwaitmS)); //wait for Ranging valid or timeout + + if (millis() >= endwaitmS) + { + Serial.println("Error - Ranging Receive Timeout!!"); + led_Flash(2, 100); //single flash to indicate timeout + } + else + { + IrqStatus = LT.readIrqStatus(); + digitalWrite(LED1, HIGH); + + if (IrqStatus & IRQ_RANGING_SLAVE_RESPONSE_DONE) + { + response_sent++; + Serial.print(response_sent); + Serial.print(" Response sent"); + } + else + { + Serial.print("Slave error,"); + Serial.print(",Irq,"); + Serial.print(IrqStatus, HEX); + LT.printIrqStatus(); + } + digitalWrite(LED1, LOW); + Serial.println(); + } + +} + + +void led_Flash(unsigned int flashes, unsigned int delaymS) +{ + //flash LED to show board is alive + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +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(F(programversion)); + Serial.println(F("Stuart Robinson")); + Serial.println(); + + Serial.println("55_Ranging_Slave Starting"); + + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, 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 + } + } + + //The function call list below shows the complete setup for the LoRa device for ranging using the information + //defined in the Settings.h file. + //The 'Setup LoRa device for Ranging' list below can be replaced with a single function call, note that + //the calibration value will be loaded automatically from the table in the library; + //LT.setupRanging(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, RangingAddress, RangingRole); + + LT.setupRanging(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, RangingAddress, RANGING_SLAVE); + + //*************************************************************************************************** + //Setup LoRa device for Ranging Slave + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setPacketType(PACKET_TYPE_RANGING); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 0, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setRfFrequency(Frequency, Offset); + LT.setTxParams(TXpower, RADIO_RAMP_02_US); + LT.setRangingMasterAddress(RangingAddress); + LT.setRangingSlaveAddress(RangingAddress); + LT.setRangingCalibration(LT.lookupCalibrationValue(SpreadingFactor, Bandwidth)); + LT.setRangingRole(RANGING_SLAVE); + LT.writeRegister(REG_RANGING_FILTER_WINDOW_SIZE, 8); //set up window size for ranging averaging + LT.setHighSensitivity(); + //*************************************************************************************************** + + LT.setRangingCalibration(11300); //override automatic lookup of calibration value from library table + + Serial.print(F("Calibration,")); + Serial.println(LT.getSetCalibrationValue()); //reads the calibratuion value currently set + delay(2000); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/55_Ranging_Slave/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/55_Ranging_Slave/Settings.h new file mode 100644 index 0000000..1f516c2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/55_Ranging_Slave/Settings.h @@ -0,0 +1,38 @@ +/***************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 16/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 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions in hz +const int32_t Offset = 0; //offset frequency in hz for calibration purposes +const uint8_t Bandwidth = LORA_BW_0800; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint16_t Calibration = 11350; //Manual Ranging calibrarion value + +const uint8_t TXpower = 10; //Transmit power used +const uint32_t RangingAddress = 16; //must match address in recever + +const uint16_t rangingRXTimeoutmS = 0xFFFF; //ranging RX timeout in mS + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/56_Ranging_Calibration_Checker/56_Ranging_Calibration_Checker.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/56_Ranging_Calibration_Checker/56_Ranging_Calibration_Checker.ino new file mode 100644 index 0000000..0d4b9d4 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/56_Ranging_Calibration_Checker/56_Ranging_Calibration_Checker.ino @@ -0,0 +1,204 @@ +/***************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 17/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. +*******************************************************************************************************/ + +#define programversion "V1.1" +#define Serial_Monitor_Baud 9600 + +#include +#include +SX128XLT LT; +#include "Settings.h" + +uint8_t distance_zero_count; +uint16_t calvalue, calibrationstart, calibrationend; +uint16_t rangeing_error_count, rangeing_valid_count; +uint16_t IrqStatus; +uint32_t endwaitmS, startrangingmS, range_result; +float distance; + + +void loop() +{ + uint16_t index; + distance_zero_count = 0; + + for (index = calibrationstart; index <= calibrationend; index = index + 10) + { + digitalWrite(LED1, HIGH); + LT.setRangingCalibration(index); + Serial.print(F("TransmitRanging,Calibration,")); + Serial.print(index); + LT.transmitRanging(RangingAddress, TXtimeoutmS, TXpower, NO_WAIT); + digitalWrite(LED1, LOW); + + endwaitmS = millis() + waittimemS; + startrangingmS = millis(); + + while (!(digitalRead(DIO1)) && (millis() < endwaitmS)); //wait for Ranging valid or timeout + + delay(10); + + IrqStatus = LT.readIrqStatus(); + Serial.print(F(",IRQ,")); + Serial.print(IrqStatus, HEX); + + if (IrqStatus & IRQ_RANGING_MASTER_RESULT_TIMEOUT) + { + rangeing_error_count++; + Serial.print(F(", RangingTimeout! ")); + } + + if (millis() > endwaitmS) + { + Serial.print(F(",ProgramTimeout")); + } + + if (IrqStatus & IRQ_RANGING_MASTER_RESULT_VALID) + { + rangeing_valid_count++; + digitalWrite(LED1, HIGH); + Serial.print(F(",Valid")); + range_result = LT.getRangingResultRegValue(RANGING_RESULT_RAW); + Serial.print(F(",RAW,")); + Serial.print(range_result, HEX); + + distance = LT.getRangingDistance(RANGING_RESULT_RAW, range_result, 1); + + Serial.print(F(",Distance,")); + Serial.print(distance, 1); + Serial.print(F("m")); + Serial.print(F(",Time,")); + Serial.print(millis() - startrangingmS); + Serial.print("mS"); + digitalWrite(LED1, LOW); + } + + Serial.print(F(",OKCount,")); + Serial.print(rangeing_valid_count); + Serial.print(F(",ErrorCount,")); + Serial.print(rangeing_error_count); + + if (distance == 0) + { + Serial.print(F(", Distance is Zero!")); + distance_zero_count++; + } + + if (distance_zero_count >= 3) + { + delay(5000); + break; + } + + Serial.println(); + delay(packet_delaymS); + + } + + Serial.println(); + Serial.println(); + Serial.println(); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + uint16_t Remainder; + Serial.println(); + Serial.println(); + Serial.begin(Serial_Monitor_Baud); //setup Serial console ouput + Serial.println(); + Serial.println(__FILE__); + Serial.print(F("Compiled ")); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(programversion)); + Serial.println(F("Stuart Robinson")); + Serial.println(); + + Serial.println(F("56_Ranging_Calibration_Checker Starting")); + + pinMode(LED1, OUTPUT); + + led_Flash(2, 125); + + Serial.println(F("Checking device")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX_EN, TX_EN, 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 + } + } + + //The function call list below shows the complete setup for the LoRa device for ranging using the information + //defined in the Settings.h file. + //The 'Setup LoRa device for Ranging' list below can be replaced with a single function call, note that + //the calibration value will be loaded automatically from the table in the library; + + //LT.setupRanging(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, RangingAddress, RangingRole); + + //*************************************************************************************************** + //Setup LoRa device for Ranging Master + //*************************************************************************************************** + LT.setMode(MODE_STDBY_RC); + LT.setPacketType(PACKET_TYPE_RANGING); + LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate); + LT.setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 0, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + LT.setRfFrequency(Frequency, Offset); + LT.setTxParams(TXpower, RADIO_RAMP_02_US); + LT.setRangingMasterAddress(RangingAddress); + LT.setRangingSlaveAddress(RangingAddress); + LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RANGING_MASTER_RESULT_VALID + IRQ_RANGING_MASTER_RESULT_TIMEOUT), 0, 0); //set for IRQ on RX done + LT.setRangingCalibration(LT.lookupCalibrationValue(SpreadingFactor, Bandwidth)); + LT.setRangingRole(RANGING_MASTER); + LT.writeRegister(REG_RANGING_FILTER_WINDOW_SIZE, 8); //set up window size for ranging averaging + LT.setHighSensitivity(); + //*************************************************************************************************** + + //LT.setRangingCalibration(Calibration); //override automatic lookup of calibration value from library table + + calvalue = LT.getSetCalibrationValue(); + Remainder = calvalue / 10; + calibrationstart = (Remainder * 10) - 1000; + calibrationend = (Remainder * 10) + 1000; + Serial.print(F("CalibrationStart,")); + Serial.print(calibrationstart); + Serial.print(F(",CalibrationEnd,")); + Serial.println(calibrationend); + Serial.println(); + + delay(2000); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/56_Ranging_Calibration_Checker/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/56_Ranging_Calibration_Checker/Settings.h new file mode 100644 index 0000000..0a4bb42 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/56_Ranging_Calibration_Checker/Settings.h @@ -0,0 +1,48 @@ +/***************************************************************************************************** + Programs for Arduino - Copyright of the author Stuart Robinson - 17/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 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used + +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions in hz +const int32_t Offset = 0; //offset frequency in hz for calibration purposes +const uint8_t Bandwidth = LORA_BW_0800; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF8; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate +const uint16_t Calibration = 11426; //Manual Ranging calibrarion value + +const uint8_t RangingRole = RANGING_SLAVE; //Ranging role, RANGING_MASTER or RANGING_SLAVE +const uint8_t TXpower = 10; //Transmit power used +const uint32_t RangingAddress = 16; //must match address in recever + +const uint16_t waittimemS = 10000; //wait this long in mS for packet before assuming timeout +const uint16_t TXtimeoutmS = 5000; //ranging TX timeout in mS +const uint16_t RXtimeoutmS = 0xFFFF; //ranging RX timeout in mS +const uint16_t packet_delaymS = 250; //forced extra delay in mS between ranging requests +const uint16_t rangeingcount = 5; //number of times ranging is cqarried out for each distance measurment +float distance_adjustment = 1; //adjustment factor to calculated distance diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/Calibration_Values.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/Calibration_Values.jpg new file mode 100644 index 0000000..ca0893a Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/Calibration_Values.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/IMG_2531_Reduced.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/IMG_2531_Reduced.jpg new file mode 100644 index 0000000..e445c9f Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/IMG_2531_Reduced.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/SX128XLT_Ranging_100m.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/SX128XLT_Ranging_100m.jpg new file mode 100644 index 0000000..7ad7063 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/SX128XLT_Ranging_100m.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/SX128X_Ranging_Calibration_Values.jpg b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/SX128X_Ranging_Calibration_Values.jpg new file mode 100644 index 0000000..d6dc2d9 Binary files /dev/null and b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/Pictures/SX128X_Ranging_Calibration_Values.jpg differ diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/ReadMe.md b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/ReadMe.md new file mode 100644 index 0000000..ce8c2d7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Ranging/ReadMe.md @@ -0,0 +1,113 @@ +## Ranging Calibration + +**Note:** The ranging feature of the SX128X is not supported if the module uses external RX and TX switching. + +To measure a distance the master device transmits a ranging request which a slave receives and then sends a response, if the request was for that particular slave. The master receives the slaves response and knows by use of a timer how long the master slave response exchange took. + +The total time for the master slave exchange includes a fixed processing time for the master and slave to transmit and receive the appropriate packets. This fixed time should be static and should be the same no matter how far apart the master initiator and slave receiver are. + +This fixed time then needs to be subtracted from the total round trip time. The remainder of the time is then proportional to the distance in a linear way. + +Thus the ranging function needs a calibration value (the fixed time mentioned above) which changes according to the bandwidth and spreading factor used. Bandwidths of 400khz, 800khz and 1600khz are supported for ranging. The calibration value can also vary slightly between different modules or antennas used. So for the best results its suggested to calibrate a pair of modules together. The SX128XLT library does, by default, do a lookup from a pre-determined range of calibration values. + +Its been noticed in testing that variations in distance measurements of +\-10m are not unusual and this is typically the sort of adjustment that calibration might correct for. If your using the SX128x to measure long distances, into several kilometres, then the standard values provided by the library are probably accurate enough, a variation of 10m over 4km is hardly significant. + +There is a calibration method described in a Semtech document; + +[Introduction to Ranging](https://semtech.my.salesforce.com/sfc/p/#E0000000JelG/a/44000000MDiH/OF02Lve2RzM6pUw9gNgSJXbDNaQJ_NtQ555rLzY3UvY) + +My own approach to the ranging calibration has been simplified. The starting base for the calibration numbers was this table produced by Semtech; + +![Picture 1](Pictures/SX128X_Ranging_Calibration_Values.jpg) + +After running some checks on my own set-ups, I came up with the following set of values, and the ranging programs pick up these numbers by default, you can of course use your own. + +![Picture 1](Pictures/Calibration_Values.jpg) + + +To check the the calibration values from the library a ranging slave was programmed with the **'55\_Ranging\_Slave'** program. Normally the ranging example programs automatically lookup the calibration value from a table in the file 'SX128XLT_Definitions.h'. However the value can be manually configured using the command; + +setRangingCalibration(Calibration); + +where Calibration is the value to use, normally in the range of 10,000 to 13,500. + +Lets follow and example of testing the calibration of the modules for ranging at spreading factor 8, bandwidth 800khz. From the initial table shown above, the calibration value is around 11350. Set the appropriate LoRa settings in the 'Settings.h' file for the slave and ranging calibration programs to; + + const uint8_t Bandwidth = LORA_BW_0800; //LoRa bandwidth + const uint8_t SpreadingFactor = LORA_SF8; //LoRa spreading factor + const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + + +Program the slave device and at start-up the serial monitor should show; + + 55_Ranging_Slave Starting + Device found + Calibration,11350 + RangingListen, + +The example program **'56\_Ranging\_Calibration\_Checker'** varies the calibration value for each master ranging measurement starting at a value 1000 less than the calibration value provided and changing it in steps to a value that is 1000 more than the mid value. At each change of calibration value the distance is measured and sent to the serial monitor. When the distance goes to zero 3 times in a row the process stops. You can then see on the serial monitor which calibration value gives close to a 0m reading. + +When the ranging calibration program starts you should see this; + + 56_Ranging_Calibration_Checker Starting + Checking device + Device found + CalibrationStart,10350,CalibrationEnd,12350 + +After a while the program reported this; + TransmitRanging,Calibration,11220,IRQ,200,Valid,RAW,47,Distance,3.2m,Time,33mS,OKCount,88,ErrorCount,0 + TransmitRanging,Calibration,11230,IRQ,200,Valid,RAW,1F,Distance,1.4m,Time,31mS,OKCount,89,ErrorCount,0 + TransmitRanging,Calibration,11240,IRQ,200,Valid,RAW,19,Distance,1.1m,Time,31mS,OKCount,90,ErrorCount,0 + TransmitRanging,Calibration,11250,IRQ,200,Valid,RAW,36,Distance,2.4m,Time,30mS,OKCount,91,ErrorCount,0 + TransmitRanging,Calibration,11260,IRQ,200,Valid,RAW,FFFFFF,Distance,0.0m,Time,31mS,OKCount,92,ErrorCount,0, Distance is Zero! + TransmitRanging,Calibration,11270,IRQ,200,Valid,RAW,2B,Distance,1.9m,Time,33mS,OKCount,93,ErrorCount,0 + TransmitRanging,Calibration,11280,IRQ,200,Valid,RAW,1D,Distance,1.3m,Time,30mS,OKCount,94,ErrorCount,0 + TransmitRanging,Calibration,11290,IRQ,200,Valid,RAW,0,Distance,0.0m,Time,31mS,OKCount,95,ErrorCount,0, Distance is Zero! + TransmitRanging,Calibration,11300,IRQ,200,Valid,RAW,FFFFD7,Distance,0.0m,Time,33mS,OKCount,96,ErrorCount,0, Distance is Zero! + + +So with the slave using an initial calibration value of 11350 the master got to around 0m at a calibration value of 11300. Lets re-program the slave with a calibration value of 11300. To override the automatic lookup of the calibration value from the table in SX128XLT_Definitions.h ensure this command is enabled in setup() function after the main sequence functions calls configuring the SX128X device; + +**LT.setRangingCalibration(11300); //override automatic lookup of calibration value from library table** + + +The ranging calibration program then produced these results; + + TransmitRanging,Calibration,11300,IRQ,400, RangingTimeout! ,OKCount,94,ErrorCount,2 + TransmitRanging,Calibration,11310,IRQ,200,Valid,RAW,73,Distance,5.2m,Time,31mS,OKCount,95,ErrorCount,2 + TransmitRanging,Calibration,11320,IRQ,200,Valid,RAW,59,Distance,4.0m,Time,31mS,OKCount,96,ErrorCount,2 + TransmitRanging,Calibration,11330,IRQ,200,Valid,RAW,FFFF46,Distance,0.0m,Time,30mS,OKCount,97,ErrorCount,2, Distance is Zero! + TransmitRanging,Calibration,11340,IRQ,200,Valid,RAW,FFFFD0,Distance,0.0m,Time,33mS,OKCount,98,ErrorCount,2, Distance is Zero! + TransmitRanging,Calibration,11350,IRQ,200,Valid,RAW,FFFFCB,Distance,0.0m,Time,33mS,OKCount,99,ErrorCount,2, Distance is Zero! + + +So a calibration value of maybe 11320 seems about right. This value can then be used to manually configure a particular set-up. + +The example program **54_Ranging_Master** can then be programmed with the same calibration value just determined. This program will carry out 5 ranging attempts and average the results to a distance shown on the serial monitor. This program will also drive a SSD1306 OLED for use as a portable distance measuring device. + +The master ranging programs calculates the distance and then adjusts the measured value with this setting in the Settings.h file; + +**const float distance_adjustment = 1.0; //adjustment to calculated distance** + +The adjustment value need to be determined by using the ranging programs to measure the distance over a long known path. I used a location when the master has line of sight over a long path, 4.405km in this case. This distance measurement was obtained from the 1:25000 Ordnance Survey map. + +Over this long path the average distance reported by the SX1280 4.424km, so the adjustment factor is 4.405/4.424 = 0.99571 + + +### Variances at short distances. + +Regardless of the derived calibration value the conversion of the time of flight result from the values reported in the SX1280 registers to distance is a linear one, so any variation in register value over a fixed distance will represent a distance variation. Whilst you can average results the distance variations will be down to the limitations of the internal timing measurements that the SX128x takes. + +I set-up a outdoor test in a large open areas, my local playing field. The slave was placed on a pole about 1.8M off the ground and I stood with the master hand-held, away from my body, at 100m distance. The calibration and adjustment values were determined as mentioned above, so the master ought to be recoding a distance of 100m. The results of around 140 ranging measurements are below; + + +![Picture 1](Pictures/SX128XLT_Ranging_100m.jpg) + +You can see a variation in distance of +\- 10m at 100m distance is not unusual. Apart from long term averaging its difficult to see what can be done to reduce these variances. + +It has also been noted that where there is a possibility of reflections such as in urban areas, larger variances than this have been seen particularly if the antenna orientations are moving or otherwise changed. + + + +### Stuart Robinson +### March 2020 \ No newline at end of file diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/ReadMe.md b/lib/SX12XX-LoRa/examples/SX128x_examples/ReadMe.md new file mode 100644 index 0000000..f0fc777 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/ReadMe.md @@ -0,0 +1,88 @@ +# SX128X Library + + + +This part of the SX12XX library supports the SX1280 and SX1281 2.4Ghz LoRa modules. + +The objective of the SX12XX 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. + + +###SX128X Considerations for pin usage + +There is a range of SX128X 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. + +The basic SX1280 modules from NiceRF and Ebyte were used to test the examples in this library. There may be newer devices out there that have additional features, such as TCXOs, that may require different set-ups or pin usage. + +Of the LoRa devices DIO pins the SX128X library in standard form only uses DIO1. Some SX128x modules have RX and TX enable pins that need to be appropriately 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, LORA\_DEVICE); + +Clearly the above begin statement is somewhat cumbersome and could potentially be shortened for the NiceRF SX128X devices to; + +begin(NSS, NRESET, RFBUSY, DIO1, LORA\_DEVICE); + +And shortened for the Ebyte devices to; + +begin(NSS, NRESET, RFBUSY, DIO1, RX\_EN, TX\_EN, LORA\_DEVICE); + +Which is a lot more manageable. + +You can use the shorter formats of the begin commands can be used in your own programs if you have the appropriate module, NiceRF or Ebyte. + +The full format of begin, see above, is still valid and is used in most of the example programs. 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. + +Valid values for LORA_DEVICE are DEVICE_SX1280 and DEVICE_SX1281. + +Accepted its all a bit confusing, but regrettably module manufacturers have different ideas about design. + +# SX128X Library - LoRa Settings + +In the setModulationParams() function the Spreading factor, Bandwidth, CodeRate LoRa parameters can be set; + + //LoRa Spreading factors + LORA_SF5 + LORA_SF6 + LORA_SF7 + LORA_SF8 + LORA_SF9 + LORA_SF10 + LORA_SF11 + LORA_SF12 + + //LoRa Bandwidths + 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 device types for the SX128X part of the library are; + + DEVICE_SX1280 + DEVICE_SX1281 + +In the transmit() function the TXpower can be set from -18dBm to +12dBm. + +In the setPacketType() function valid packet type are; + + PACKET_TYPE_LORA + PACKET_TYPE_FLRC + PACKET_TYPE_RANGING + PACKET_TYPE_BLE (not implemented) + PACKET_TYPE_NONE + + +### Stuart Robinson + +### April 2020 + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino new file mode 100644 index 0000000..6baf463 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/21_On_Off_Transmitter/21_On_Off_Transmitter.ino @@ -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 +#include +#include "Settings.h" +#include + +#include //watchdog timer library, integral to Arduino IDE +#include //watchdog timer library, integral to Arduino IDE +#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("Transmitter ready")); + Serial.println(); + +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h new file mode 100644 index 0000000..bab1eb9 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/21_On_Off_Transmitter/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + 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 SX1280 devices, set to -1 if not used +const int8_t TX_EN = -1; //pin for TX enable, used on some SX1280 devices, set to -1 if not used + + +#define LORA_DEVICE DEVICE_SX1280 //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 +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +#define TXpower 10 //power for transmissions in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino new file mode 100644 index 0000000..f75c219 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/22_On_Off_Receiver/22_On_Off_Receiver.ino @@ -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 +#include +#include "Settings.h" +#include + + +SX128XLT 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("Receiver ready")); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/22_On_Off_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/22_On_Off_Receiver/Settings.h new file mode 100644 index 0000000..f1748dc --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/22_On_Off_Receiver/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + 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 SX1280 devices, set to -1 if not used +const int8_t TX_EN = -1; //pin for TX enable, used on some SX1280 devices, set to -1 if not used +const int8_t BUZZER = -1; //pin for buzzer, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //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 + + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +#define TXpower 10 //power for transmissions in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino new file mode 100644 index 0000000..7f7182f --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/35_Remote_Control_Servo_Transmitter.ino @@ -0,0 +1,190 @@ +/******************************************************************************************************* + 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. + + 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 +#include +#include "Settings.h" +#include + +SX128XLT 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. + + 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 + TXPacketL = LT.transmitSXBuffer(0, PacketLength, 10000, TXpower, WAIT_TX); + +#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.println(); +#endif + + digitalWrite(LED1, LOW); //LED off, may have been on due to switch press + + 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + attachInterrupts(); + + Serial.println(F("35_Remote_Control_Servo_Transmitter ready")); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h new file mode 100644 index 0000000..a2961b3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/35_Remote_Control_Servo_Transmitter/Settings.h @@ -0,0 +1,49 @@ +/******************************************************************************************************* + 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 SX1280 devices, set to -1 if not used +const int8_t TX_EN = -1; //pin for TX enable, used on some SX1280 devices, set to -1 if not used + + +#define LORA_DEVICE DEVICE_SX1280 //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 +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +const uint8_t PacketLength = 5; //packet length is fixed +const int8_t TXpower = 10; //LoRa transmit power in dBm + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino new file mode 100644 index 0000000..69dc3f3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/36_Remote_Control_Servo_Receiver.ino @@ -0,0 +1,256 @@ +/******************************************************************************************************* + 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 +#include +#include "Settings.h" +#include + +SX128XLT LT; + +#include +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 (IRQStatus & (IRQ_RX_DONE + IRQ_HEADER_VALID) ) + { + packet_is_OK(); + } + else + { + 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, DIO2, DIO3, RX_EN, TX_EN, 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); + + Serial.println(F("36_Remote_Control_Servo_Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h new file mode 100644 index 0000000..8fc2ae3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/RemoteControl/36_Remote_Control_Servo_Receiver/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + 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 SX1280 devices, set to -1 if not used +const int8_t TX_EN = -1; //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //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 + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +#define Frequency 2445000000 //frequency of transmissions +#define Offset 0 //offset frequency for calibration purposes +#define Bandwidth LORA_BW_0400 //LoRa bandwidth +#define SpreadingFactor LORA_SF7 //LoRa spreading factor +#define CodeRate LORA_CR_4_5 //LoRa coding rate + +const uint8_t PacketLength = 5; //packet length is fixed + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino new file mode 100644 index 0000000..45bbde3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/17_Sensor_Transmitter/17_Sensor_Transmitter.ino @@ -0,0 +1,315 @@ +/******************************************************************************************************* + 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 transmits a LoRa packet without using a processor buffer, the LoRa + devices internal buffer is filled directly with variables. + + The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There + is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end. + + Although the LoRa packet transmitted and received has its own internal CRC error checking, you could + still receive packets of the same length from another source. If this valid packet were to be used + to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet + is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet. + This CRC value is read by the receiver and used to check that the received CRC matches the supposed + sensor data in the packet. As an additional check there is some addressing information at the beginning + of the packet which is also checked for validity. Thus we can be relatively confident when reading the + received packet that its genuine and from this transmitter. The packet is built and sent in the + sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to + the packet. + + Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of + 8 seconds using the Atmel processor internal watchdog. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + 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. + + 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 150mAh battery, to see how long + the battery actually lasts. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +#include //watchdog timer library, integral to Arduino IDE +#include //get the library here; https://github.com/rocketscream/Low-Power + +SX128XLT LT; + +#include //get library here; https://github.com/Seeed-Studio/Grove_BME280 +BME280 bme280; //create an instance of the BME280 senosor +#include + +uint32_t TXpacketCount; +uint8_t TXPacketL; + +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t CRCvalue; //the CRC value of the packet data up to this point +uint8_t packetlength; //the packet length that was sent, checked against length received + + +void loop() +{ + TXpacketCount++; + Serial.print(TXpacketCount); //print the numbers of sends + Serial.print(F(" Sending > ")); + + readSensors(); //read the sensor values + printSensorValues(); //print the sensor values + + if (sendSensorPacket()) + { + Serial.println(F("SentOK")); + } + else + { + Serial.print(F("Send Error - IRQreg,")); + Serial.println(LT.readIrqStatus(), HEX); + } + + Serial.print(F("Sleeping zzzz")); + Serial.flush(); //make sure all serial output has gone + + //now put the sensor, LoRa device and processor to sleep + sleepBME280(); //sleep the BME280 + LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep. + sleep8seconds(sleeps); //sleep Atmel processor in units of approx 8 seconds + + //wait a bit ................ + Serial.println(F(" - Awake !!")); //the processor has woken up + Serial.println(); + + LT.wake(); + normalBME280(); //BME280 sensor to normal mode +} + + +uint8_t sendSensorPacket() +{ + //The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the + //receiver uses the same variable types and sequence to read variables out of the receive buffer. + uint8_t len; + + LT.startWriteSXBuffer(0); //start the write packet to buffer process + + LT.writeUint8(Sensor1); //this byte defines the packet type + LT.writeUint8('B'); //this byte identifies the destination node of the packet + LT.writeUint8(1); //this byte identifies the source node of the packet + + /************************************************************************ + Highlighted section - this is where the actual sensor data is added to the packet + ************************************************************************/ + LT.writeFloat(temperature); //add the BME280 temperature + LT.writeFloat(pressure); //add the BME280 pressure + LT.writeUint16(humidity); //add the BME280 humididty + LT.writeUint16(voltage); //add the battery voltage + LT.writeUint8(statusbyte); //add the status byte + /************************************************************************/ + + len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent + + addPacketErrorCheck(len); //add the additional CRC error checking to the packet end + + //now transmit the packet, set a timeout of 5000mS, wait for it to complete sending + digitalWrite(LED1, HIGH); //turn on LED as an indicator + TXPacketL = LT.transmitSXBuffer(0, (len + 2), 5000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); //turn off indicator LED + + return TXPacketL; //TXPacketL will be 0 if there was an error sending +} + + +void addPacketErrorCheck(uint8_t len) +{ + //calculate the CRC of packet sensor data + CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF); + + Serial.print(F("Calculated CRC value ")); + Serial.println(CRCvalue, HEX); + + LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data + LT.writeUint16(CRCvalue); //add the actual CRC value + LT.endWriteSXBuffer(); //close the packet +} + + +void readSensors() +{ + //read the sensor values into the global variables + temperature = bme280.getTemperature(); + pressure = bme280.getPressure(); + humidity = bme280.getHumidity(); + + if (BATVREADON >= 0) + { + voltage = readBatteryVoltage(); //read resistor divider across battery + } + else + { + voltage = 9999; //set a default value + } + statusbyte = 0x55; //manually set this for now, its a test +} + + +void printSensorValues() +{ + Serial.print(F("Temperature,")); + Serial.print(temperature, 1); + Serial.print(F("c,Pressure,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(" ")); + Serial.flush(); +} + + +void sleep8seconds(uint32_t sleeps) +{ + //uses the lowpower library + uint32_t index; + + for (index = 1; index <= sleeps; index++) + { + //sleep 8 seconds + LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); + } +} + + +void sleepBME280() +{ + //write this register value to BME280 to put it to sleep + writeBME280reg(BME280_REGISTER_CONTROL, B01111100); +} + + +void normalBME280() +{ + //write this register value to BME280 to put it to read mode + writeBME280reg(BME280_REGISTER_CONTROL, B01111111); +} + + +void writeBME280reg(byte reg, byte regvalue) +{ + //write a register value to the BME280 + Wire.beginTransmission((uint8_t) BME280_ADDRESS); + Wire.write((uint8_t)reg); + Wire.write((uint8_t)regvalue); + Wire.endTransmission(); +} + + +uint16_t readBatteryVoltage() +{ + //relies on 1V1 internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t volts = 0; + byte index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + analogReference(INTERNAL1V1); + temp = analogRead(BATTERYAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(BATTERYAD); + volts = volts + temp; + } + volts = ((volts / 5) * ADMultiplier) + DIODEMV; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + return volts; +} + + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + Serial.begin(9600); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX_EN, TX_EN, 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); + + if (!bme280.init()) + { + Serial.println("BME280 Device error!"); + led_Flash(100, 15); //long very fast speed flash indicates BME280 device error + } + + Serial.println(F("Transmitter ready")); + Serial.println(); + + readSensors(); //do an initial sensor read +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/17_Sensor_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/17_Sensor_Transmitter/Settings.h new file mode 100644 index 0000000..34a7679 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/17_Sensor_Transmitter/Settings.h @@ -0,0 +1,45 @@ +/******************************************************************************************************* + 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 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //pin for BUZZER, set to -1 if not used + +#define BATVREADON 8 //when high turns on the resistor divider to measure voltage, -1 if not used +#define BATTERYAD A7 //Resitor divider for battery connected here, -1 if not used +#define ADMultiplier 10.00 //adjustment to convert AD value read into mV of battery voltage +#define DIODEMV 98 //mV voltage drop accross diode @ low idle current + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +#define BME280_ADDRESS 0x76 //I2C bus address of BME280 +#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control + +const uint8_t sleeps = 2; //number of 8 second sleeps, gap between transmissions diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino new file mode 100644 index 0000000..ddda0a7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/18_Sensor_Receiver/18_Sensor_Receiver.ino @@ -0,0 +1,358 @@ +/******************************************************************************************************* + 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 - The program receives a LoRa packet without using a processor buffer, the LoRa devices + internal buffer is read direct for the received sensor data. + + The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity, + and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status + value at the end of the packet. + + When the program starts, the LoRa device is setup to set the DIO1 pin high 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. + + For the sensor data to be accepted as valid the folowing need to match; + + The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet. + The packet must start with a byte that matches the packet type sent, 'Sensor1' + The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node' + + In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid + packet is acted on and erroneous values displayed. + + The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. + + With a standard Arduino Pro Mini and SSD1306 display the current consumption was 20.25mA with the + display and 16.6mA without the display. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#include +#include +#include "Settings.h" +#include + +SX128XLT LT; + +#include //get library here > https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306 + +uint32_t RXpacketCount; //count of all packets received +uint32_t ValidPackets; //count of packets received with valid data +uint32_t RXpacketErrors; //count of all packets with errors received +bool packetisgood; + +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet + +uint8_t RXPacketType; +uint8_t RXDestination; +uint8_t RXSource; +float temperature; //the BME280 temperature value +float pressure; //the BME280 pressure value +uint16_t humidity; //the BME280 humididty value +uint16_t voltage; //the battery voltage value +uint8_t statusbyte; //a status byte, not currently used +uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want + } + + digitalWrite(LED1, LOW); + Serial.println(); +} + + +void packet_Received_OK() +{ + //a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from + //an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data + + uint8_t len; + uint8_t contenterrors; //keep a count of errors found in packet + + RXpacketCount++; + Serial.print(RXpacketCount); + Serial.print(F(",PacketsReceived,")); + + LT.startReadSXBuffer(0); + RXPacketType = LT.readUint8(); + RXDestination = LT.readUint8(); + RXSource = LT.readUint8(); + + /************************************************************************ + Highlighted section - this is where the actual sensor data is read from + the packet + ************************************************************************/ + temperature = LT.readFloat(); //the BME280 temperature value + pressure = LT.readFloat(); //the BME280 pressure value + humidity = LT.readUint16(); //the BME280 humididty value + voltage = LT.readUint16(); //the battery voltage value + statusbyte = LT.readUint8(); //a status byte, not currently used + /************************************************************************/ + + len = LT.endReadSXBuffer(); + + printreceptionDetails(); //print details of reception, RSSI etc + Serial.println(); + + contenterrors = checkPacketValid(len); //pass length of packet to check routine + + if (contenterrors == 0) + { + Serial.println(F(" Packet is good")); + ValidPackets++; + printSensorValues(); //print the sensor values + Serial.println(); + printPacketCounts(); //print count of valid packets and errors + displayscreen1(); + Serial.println(); + } + else + { + Serial.println(F(" Packet is not valid")); + RXpacketErrors++; + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +uint8_t checkPacketValid(uint8_t len) +{ + //this function checks if the packet is valid and will be displayed + + uint8_t errors = 0; + + if (RXPacketType != Sensor1) //is it a Sensor1 type packet + { + errors++; + } + + if (RXDestination != This_Node) //was the packet sent to this receiver node ? + { + errors++; + } + + if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ? + { + errors++; + } + + Serial.println(); + Serial.print(F("Error Check Count = ")); + Serial.print(errors); + return errors; +} + + +bool checkCRCvalue(uint8_t len) +{ + uint16_t CRCSensorData; + + Serial.print(F("len = ")); + Serial.println(len); + + CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data + + Serial.print(F("(CRC of Received sensor data ")); + Serial.print(CRCSensorData, HEX); + Serial.print(F(")" )); + + TXCRCvalue = ((LT.getByteSXBuffer(len + 1) << 8) + (LT.getByteSXBuffer(len))); + + Serial.print(F("(CRC transmitted ")); + Serial.print(TXCRCvalue, HEX); + Serial.print(F(")" )); + + if (TXCRCvalue != CRCSensorData) + { + Serial.print(F(" Sensor Data Not Valid")); + return false; + } + else + { + Serial.print(F(" Sensor Data is Valid")); + return true; + } + +} + + +void printSensorValues() +{ + Serial.print(F("Temp,")); + Serial.print(temperature, 1); + Serial.print(F("c,Press,")); + Serial.print(pressure, 0); + Serial.print(F("Pa,Humidity,")); + Serial.print(humidity); + Serial.print(F("%,Voltage,")); + Serial.print(voltage); + Serial.print(F("mV,Status,")); + Serial.print(statusbyte, HEX); + Serial.print(F(",CRC,")); + Serial.print(TXCRCvalue, HEX); + Serial.flush(); +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void printPacketCounts() +{ + Serial.print(F("ValidPackets,")); + Serial.print(ValidPackets); + Serial.print(F(",Errors,")); + Serial.print(RXpacketErrors); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXpacketErrors++; + IRQStatus = LT.readIrqStatus(); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + Serial.println(); + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); + } +} + + +void displayscreen1() +{ + //show sensor data on display + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(F("Sensor ")); + disp.print(RXSource); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(temperature, 1); + disp.print(F("c")); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(pressure, 0); + disp.print(F("Pa")); + disp.clearLine(3); + disp.setCursor(0, 3); + disp.print(humidity); + disp.print(F("%")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(voltage); + disp.print(F("mV")); + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("ValidPkts ")); + disp.print(ValidPackets); + disp.setCursor(0, 7); + disp.print(F("Errors ")); + disp.print(RXpacketErrors); +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + Serial.begin(9600); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Check LoRa")); + disp.setCursor(0, 1); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX_EN, TX_EN, LORA_DEVICE)) + { + disp.print(F("LoRa OK")); + led_Flash(2, 125); + } + else + { + disp.print(F("Device error")); + Serial.println(F("Device error")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/18_Sensor_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/18_Sensor_Receiver/Settings.h new file mode 100644 index 0000000..9833711 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Sensor/18_Sensor_Receiver/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + 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. +*******************************************************************************************************/ + + +//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 set to -1. + +#define NSS 10 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //pin for BUZZER, set to -1 if not used + +#define BATVREADON 8 //when high turns on the resistor divider to measure voltage, -1 if not used +#define BATTERYAD A7 //Resistor divider for battery connected here, -1 if not used +#define ADMultiplier 10.00 //adjustment to convert AD value read into mV of battery voltage +#define DIODEMV 98 //mV voltage drop accross diode @ low idle current + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + + +//*************** Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm + +#define packet_delay 1000 //mS delay between packets +#define This_Node 'B' //this is the node that the remote sensors send data to + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino new file mode 100644 index 0000000..dbcef88 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel.ino @@ -0,0 +1,242 @@ +/******************************************************************************************************* + 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 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 12.2uA. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.0" + +#include //watchdog timer library, integral to Arduino IDE +#include +#include //get the library here; https://github.com/rocketscream/Low-Power + +#include +#include "Settings.h" + +SX128XLT LT; + +boolean SendOK; +int8_t TestPower; +uint8_t TXPacketL; + + +void loop() +{ + digitalWrite(LED1, HIGH); + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket1> ")); + Serial.flush(); + + if (Send_Test_Packet1()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); + + LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep. + Serial.println(F("Sleeping zzzzz....")); + Serial.println(); + Serial.flush(); + digitalWrite(LED1, LOW); + + sleep1second(15); //goto sleep for 15 seconds + + Serial.println(F("Awake !")); + Serial.flush(); + digitalWrite(LED1, HIGH); + LT.wake(); + + Serial.print(TXpower); + Serial.print(F("dBm ")); + Serial.print(F("TestPacket2> ")); + Serial.flush(); + + if (Send_Test_Packet2()) + { + packet_is_OK(); + } + else + { + packet_is_Error(); + } + Serial.println(); + delay(packet_delay); +} + + +void sleep1second(uint32_t sleeps) +{ + //uses the lowpower library + uint32_t index; + + for (index = 1; index <= sleeps; index++) + { + LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); //sleep in 1 second steps + } +} + + +void packet_is_OK() +{ + Serial.print(F(" ")); + Serial.print(TXPacketL); + Serial.print(F(" Bytes SentOK")); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error +} + + +bool Send_Test_Packet1() +{ + uint8_t bufffersize; + + uint8_t buff[] = "Before Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +bool Send_Test_Packet2() +{ + uint8_t bufffersize; + + uint8_t buff[] = "After Device Sleep"; + TXPacketL = sizeof(buff); + buff[TXPacketL - 1] = '*'; + + if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER + { + bufffersize = TXBUFFER_SIZE; + } + else + { + bufffersize = sizeof(buff); + } + + TXPacketL = bufffersize; + + LT.printASCIIPacket( (uint8_t*) buff, bufffersize); + digitalWrite(LED1, HIGH); + + if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX)) + { + digitalWrite(LED1, LOW); + return true; + } + else + { + return false; + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + uint16_t index; + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(__TIME__); + Serial.print(F(" ")); + Serial.println(__DATE__); + Serial.println(F(Program_Version)); + Serial.println(); + Serial.println(F("5_LoRa_TX_Sleep_Timed_Wakeup_Atmel Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, DIO2, DIO3, RX_EN, TX_EN, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate); + + Serial.print(F("Transmitter ready - TXBUFFER_SIZE ")); + Serial.println(TXBUFFER_SIZE); + Serial.println(); +} + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h new file mode 100644 index 0000000..7e0ffa2 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Sleep/5_LoRa_TX_Sleep_Timed_Wakeup_Atmel/Settings.h @@ -0,0 +1,40 @@ +/******************************************************************************************************* + 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 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 +#define RFBUSY 7 +#define NRESET 9 +#define LED1 8 +#define DIO1 3 +#define DIO2 -1 //not used +#define DIO3 -1 //not used +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define BUZZER -1 //pin for BUZZER, set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0400; //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 TXpower = 10; //Power for transmissions in dBm +const uint16_t packet_delay = 1000; //mS delay between packets + +#define TXBUFFER_SIZE 32 //RX buffer size + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino new file mode 100644 index 0000000..54d745d --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/23_GPS_Tracker_Transmitter/23_GPS_Tracker_Transmitter.ino @@ -0,0 +1,407 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program is an example of a basic GPS tracker. The program reads the GPS, + waits for an updated fix and transmits location and altitude, number of satellites in view, the HDOP + value, the fix time of the GPS and the battery voltage. This transmitter can be also be used to + investigate GPS performance. At startup there should be a couple of seconds of recognisable text from + the GPS printed to the serial monitor. If you see garbage or funny characters its likley the GPS baud + rate is wrong. If the transmitter is turned on from cold, the receiver will pick up the cold fix time, + which is an indication of GPS performance. The GPS will be powered on for around 4 seconds before the + timing of the fix starts. Outside with a good view of the sky most GPSs should produce a fix in around + 45 seconds. The number of satellites and HDOP are good indications to how well a GPS is working. + + The program writes direct to the LoRa devices internal buffer, no memory buffer is used. + + The LoRa settings are configured in the Settings.h file. + + The program has the option of using a pin to control the power to the GPS (GPSPOWER), if the GPS module + or board being used has this feature. To not use this feature set the define for GPSPOWER in the + Settings.h file to '#define GPSPOWER -1'. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic + levels. + + There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on + and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON + in 'Settings.h' to the pin used. If not using the feature set the pin number to -1. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" +#define authorname "Stuart Robinson" + +#include +#include + +#include "Settings.h" +#include + +SX128XLT LT; + +#include //get library here > http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + + +#ifdef USE_SOFTSERIAL_GPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#else +#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file +#endif + + +uint8_t TXStatus = 0; //used to store current status flag bits of Tracker transmitter (TX) +uint8_t TXPacketL; //length of LoRa packet (TX) +float TXLat; //Latitude from GPS on Tracker transmitter (TX) +float TXLon; //Longitude from GPS on Tracker transmitter (TX) +float TXAlt; //Altitude from GPS on Tracker transmitter (TX) +uint8_t TXSats; //number of GPS satellites seen (TX) +uint32_t TXHdop; //HDOP from GPS on Tracker transmitter (TX) +uint16_t TXVolts; //Volts (battery) level on Tracker transmitter (TX) +uint32_t TXGPSFixTime; //GPS fix time in hot fix mode of GPS on Tracker transmitter (TX) +uint32_t TXPacketCount, TXErrorsCount; //keep count of OK packets and send errors + + +void loop() +{ + + if (gpsWaitFix(WaitGPSFixSeconds)) + { + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); + Serial.println(); + Serial.print(F("Waiting ")); + Serial.print(Sleepsecs); + Serial.println(F("s")); + delay(Sleepsecs * 1000); //this sleep is used to set overall transmission cycle time + } + else + { + send_Command(NoFix); //send notification of no GPS fix. + } +} + + +bool gpsWaitFix(uint32_t waitSecs) +{ + //waits a specified number of seconds for a fix, returns true for good fix + uint32_t endwaitmS, GPSonTime; + bool GPSfix = false; + float tempfloat; + uint8_t GPSchar; + + GPSonTime = millis(); + GPSserial.begin(9600); //start GPSserial + + Serial.print(F("Wait GPS Fix ")); + Serial.print(waitSecs); + Serial.println(F("s")); + + endwaitmS = millis() + (waitSecs * 1000); + + while (millis() < endwaitmS) + { + if (GPSserial.available() > 0) + { + GPSchar = GPSserial.read(); + gps.encode(GPSchar); + } + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + GPSfix = true; + Serial.print(F("Have GPS Fix ")); + TXGPSFixTime = millis() - GPSonTime; + Serial.print(TXGPSFixTime); + Serial.println(F("mS")); + + TXLat = gps.location.lat(); + TXLon = gps.location.lng(); + TXAlt = gps.altitude.meters(); + TXSats = gps.satellites.value(); + TXHdop = gps.hdop.value(); + tempfloat = ( (float) TXHdop / 100); + + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempfloat, 2); + Serial.println(); + + break; //exit while loop reading GPS + } + } + + //if here then there has either been a fix or no fix and a timeout + + if (GPSfix) + { + setStatusByte(GPSFix, 1); //set status bit to flag a GPS fix + } + else + { + setStatusByte(GPSFix, 0); //set status bit to flag no fix + Serial.println(); + Serial.println(F("Timeout - No GPSFix")); + Serial.println(); + GPSfix = false; + } + + GPSserial.end(); //serial RX interrupts interfere with SPI, so stop GPSserial + return GPSfix; +} + + +void sendLocation(float Lat, float Lon, float Alt, uint32_t Hdop, uint32_t fixtime) +{ + uint8_t len; + uint16_t IRQStatus; + + Serial.print(F("Send Location")); + + TXVolts = readSupplyVoltage(); //get the latest supply\battery volts + + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeUint8(LocationPacket); //indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent too + LT.writeUint8(ThisNode); //tells receiver where is packet from + LT.writeFloat(Lat); //add latitude + LT.writeFloat(Lon); //add longitude + LT.writeFloat(Alt); //add altitude + LT.writeUint8(TXSats); //add number of satellites + LT.writeUint32(Hdop); //add hdop + LT.writeUint8(TXStatus); //add tracker status + LT.writeUint32(fixtime); //add GPS fix time in mS + LT.writeUint16(TXVolts); //add tracker supply volts + LT.writeUint32(millis()); //add uptime in mS + len = LT.endWriteSXBuffer(); //close buffer write + + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); + digitalWrite(LED1, LOW); + + if (TXPacketL) + { + TXPacketCount++; + Serial.println(F(" - Done ")); + Serial.print(F("SentOK,")); + Serial.print(TXPacketCount); + Serial.print(F(",Errors,")); + Serial.println(TXErrorsCount); + } + else + { + //if here there was an error transmitting packet + TXErrorsCount++; + IRQStatus = LT.readIrqStatus(); //read the the interrupt register + Serial.print(F(" SendError,")); + Serial.print(F("Length,")); + Serial.print(TXPacketL); //print transmitted packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); //print IRQ status + LT.printIrqStatus(); //prints the text of which IRQs set + Serial.println(); + } +} + + +void setStatusByte(uint8_t bitnum, uint8_t bitval) +{ + //program the status byte + + if (bitval == 0) + { + bitClear(TXStatus, bitnum); + } + else + { + bitSet(TXStatus, bitnum); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + //flash LED to show tracker is alive + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void send_Command(char cmd) +{ + bool SendOK; + uint8_t len; + + Serial.print(F("Send Cmd ")); + Serial.write(cmd); + + LT.startWriteSXBuffer(0); + LT.writeUint8(cmd); //packet addressing used indentify type of packet + LT.writeUint8(Broadcast); //who is the packet sent to + LT.writeUint8(ThisNode); //where is packet from + LT.writeUint16(TXVolts); + len = LT.endWriteSXBuffer(); + + digitalWrite(LED1, HIGH); + SendOK = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); //timeout set at 10 seconds + digitalWrite(LED1, LOW); + + if (SendOK) + { + Serial.println(F(" - Done")); + } + else + { + Serial.println(F(" - Error")); + } +} + + +uint16_t readSupplyVoltage() +{ + //relies on 1V internal reference and 91K & 11K resistor divider + //returns supply in mV @ 10mV per AD bit read + uint16_t temp; + uint16_t voltage = 0; + uint8_t index; + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit + } + + analogReference(INTERNAL); + temp = analogRead(SupplyAD); + + for (index = 0; index <= 4; index++) //sample AD 5 times + { + temp = analogRead(SupplyAD); + voltage = voltage + temp; + } + + if (BATVREADON >= 0) + { + digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit + } + + + voltage = ((voltage / 5) * ADMultiplier) + DIODEMV; + return voltage; +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void setup() +{ + uint32_t endmS; + + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + GPSON(); + } + + if (BATVREADON >= 0) + { + pinMode(BATVREADON, OUTPUT); + } + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("23_GPS_Tracker_Transmitter Starting")); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, RX_EN, TX_EN, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No device responding")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check + Serial.println(); + + TXVolts = readSupplyVoltage(); + + Serial.print(F("Supply ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + + send_Command(PowerUp); //send power up command, includes supply mV + + Serial.println(F("Startup GPS check")); + + GPSserial.begin(9600); + + endmS = millis() + echomS; + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + + Serial.println(F("Wait for first GPS fix")); + gpsWaitFix(WaitFirstGPSFixSeconds); + + sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime); +} diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h new file mode 100644 index 0000000..a599051 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/23_GPS_Tracker_Transmitter/Settings.h @@ -0,0 +1,67 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX126X busy pin +#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define GPSPOWER 4 //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 + +#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 //On board LED, high for on +#define SupplyAD A7 //pin for reading supply\battery voltage +#define BATVREADON 8 //turns on battery resistor divider, high for on, -1 if not used + +const float ADMultiplier = 10.0; //multiplier for supply volts calculation +#define DIODEMV 98 //mV voltage drop accross diode at approx 8mA + + +#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using + + + +//******* Setup LoRa Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0200; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + +const uint8_t TXpower = 10; //Power for transmissions in dBm + +#define ThisNode '2' //a character that identifies this tracker + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +//#define HardwareSerialPort Serial1 //if using hardware serial enable this define for hardware serial port + +#define GPSBaud 9600 //GPS Baud rate + +#define WaitGPSFixSeconds 30 //time in seconds to wait for a new GPS fix +#define WaitFirstGPSFixSeconds 1800 //time to seconds to wait for the first GPS fix at startup +#define Sleepsecs 5 //seconds between transmissions, this delay is used to set overall transmission cycle time + +#define echomS 2000 //number of mS to run GPS echo at startup + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino new file mode 100644 index 0000000..749a668 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/24_GPS_Tracker_Receiver/24_GPS_Tracker_Receiver.ino @@ -0,0 +1,322 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 22/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 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. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +#define Program_Version "V1.1" + +#include +#include + +SX128XLT LT; + +#include "Settings.h" +#include + + +uint32_t RXpacketCount; //count of received packets + +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //RSSI of received packet +int8_t PacketSNR; //signal to noise ratio of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //A status byte +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint8_t TXSats; //number of sattelites in use +uint32_t TXupTimemS; //up time of TX in mS + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort + + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + + Serial.println(); +} + + +void readPacketAddressing() +{ + //the transmitter is using packet addressing, so read in the details + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + float tempHdop; + + RXpacketCount++; + Serial.print(F("Packet OK > ")); + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from FIFO, not used + LT.readUint8(); //read byte from FIFO, not used + LT.readUint8(); //read byte from FIFO, not used + TXVolts = LT.readUint16(); + LT.endReadSXBuffer(); + Serial.print(F("Tracker transmitter powerup - battery ")); + Serial.print(TXVolts); + Serial.print(F("mV")); + } + + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readFloat(); + TXSats = LT.readUint8(); + TXHdop = LT.readUint32(); + TXStatus = LT.readUint8(); + TXGPSFixTime = LT.readUint32(); + TXVolts = LT.readUint16(); + TXupTimemS = LT.readUint32(); + RXPacketL = LT.endReadSXBuffer(); + + tempHdop = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F("m,")); + Serial.print(TXSats); + Serial.print(F(",")); + Serial.print(tempHdop, 2); + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS / 1000)); + Serial.print(F("s,")); + printpacketDetails(); + return; + } + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + tempHdop = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + printpacketDetails(); + return; + } + + if (PacketType == NoFix) + { + Serial.print(F("No Tracker GPS fix ")); + printpacketDetails(); + return; + } + +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + Serial.print(F("PacketError,RSSI")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + 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("24_GPS_Tracker_Receiver Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + Serial.println(F("BUZZER Enabled")); + } + else + { + Serial.println(F("BUZZER Not Enabled")); + } + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, RX_EN, TX_EN, 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); + + Serial.println(); + LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h new file mode 100644 index 0000000..b0cbef3 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/24_GPS_Tracker_Receiver/Settings.h @@ -0,0 +1,44 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 22/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 - + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + +//******* 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 on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX128X busy pin +#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used + +#define LED1 8 //On board LED, high for on + +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used + +#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0200; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + + + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino new file mode 100644 index 0000000..f56259e --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/25_GPS_Tracker_Receiver_With_Display_and_GPS.ino @@ -0,0 +1,624 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20 + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + +/******************************************************************************************************* + Program Operation - This program is an example of a functional GPS tracker receiver using lora. + It is capable of picking up the trackers location packets from many kilometres away with only basic antennas. + + The program receives the location packets from the remote tracker transmitter and writes them on an OLED + display and also prints the information to the Arduino IDE serial monitor. The program can read a locally + attached GPS and when that has a fix, will display the distance and direction to the remote tracker. + + The program writes direct to the lora devices internal buffer, no memory buffer is used. The lora settings + are configured in the Settings.h file. + + The receiver recognises two types of tracker packet, the one from the matching program '23_GPS_Tracker_Transmitter' + (LocationPacket, 27 bytes) which causes these fields to be printed to the serial monitor; + + Latitude, Longitude, Altitude, Satellites, HDOP, TrackerStatusByte, GPS Fixtime, Battery mV, Distance, Direction, + Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, PacketLength, IRQRegister. + + This is a long packet which at the long range LoRa settings takes just over 3 seconds to transmit. + + The receiver also recognises a much shorter location only packet (LocationBinaryPacket, 11 bytes) and when + received this is printed to the serial monitor; + + Latitude, Longitude, Altitude, TrackerStatusByte, Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, + PacketLength, IRQRegister. + + Most of the tracker information (for both types of packet) is shown on the OLED display. If there has been a + tracker transmitter GPS fix the number\identifier of that tracker is shown on row 0 right of screen and if there + is a recent local (receiver) GPS fix an 'R' is displayed row 1 right of screen. + + When the tracker transmitter starts up or is reset its sends a power up message containing the battery voltage + which is shown on the OLED and printer to the serial monitor. + + The program has the option of using a pin to control the power to the GPS, if the GPS module being used has this + feature. To use the option change the define in Settings.h; + + '#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE defines to + the appropriate logic levels. + + The program by default uses software serial to read the GPS, you can use hardware serial by commenting out this + line in the Settings.h file; + + #define USE_SOFTSERIAL_GPS + + And then defining the hardware serial port you are using, which defaults to Serial1. + + Serial monitor baud rate is set at 9600. +*******************************************************************************************************/ + + +#define Program_Version "V1.1" + +#include +#include +SX128XLT LT; + +#include "Settings.h" +#include + +#include //https://github.com/olikraus/u8g2 +U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306 +//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306 + + +#include //http://arduiniana.org/libraries/tinygpsplus/ +TinyGPSPlus gps; //create the TinyGPS++ object + +#ifdef USE_SOFTSERIAL_GPS +#include +SoftwareSerial GPSserial(RXpin, TXpin); +#else +#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file +#endif + +uint32_t RXpacketCount; //count of received packets +uint8_t RXPacketL; //length of received packet +int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet +int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet +uint8_t PacketType; //for packet addressing, identifies packet type +uint8_t Destination; //for packet addressing, identifies the destination (receiving) node +uint8_t Source; //for packet addressing, identifies the source (transmiting) node +uint8_t TXStatus; //status byte from tracker transmitter +uint8_t TXSats; //number of sattelites in use +float TXLat; //latitude +float TXLon; //longitude +float TXAlt; //altitude +float RXLat; //latitude +float RXLon; //longitude +float RXAlt; //altitude +uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good +uint32_t TXGPSFixTime; //time in mS for fix +uint16_t TXVolts; //supply\battery voltage +uint16_t RXVolts; //supply\battery voltage +float TXdistance; //calculated distance to tracker +uint16_t TXdirection; //calculated direction to tracker +uint16_t RXerrors; +uint32_t TXupTimemS; //up time of TX in mS + +uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix + +bool TXLocation = false; //set to true when at least one tracker location packet has been received +bool RXGPSfix = false; //set to true if the local GPS has a recent fix + +uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated + + +void loop() +{ + RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); //returns 0 if packet error of some sort + + while (!digitalRead(DIO1)) + { + readGPS(); //If the DIO pin is low, no packet arrived, so read the GPS + } + + //something has happened in receiver + digitalWrite(LED1, HIGH); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, HIGH); + } + + RXPacketL = LT.readRXPacketL(); + PacketRSSI = LT.readPacketRSSI(); + PacketSNR = LT.readPacketSNR(); + + + if (RXPacketL == 0) + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + digitalWrite(LED1, LOW); + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); + } + Serial.println(); +} + + +void readGPS() +{ + if (GPSserial.available() > 0) + { + gps.encode(GPSserial.read()); + } + + + if ( millis() > (LastRXGPSfixCheck + NoRXGPSfixms)) + { + RXGPSfix = false; + LastRXGPSfixCheck = millis(); + dispscreen1(); + } + + + if (gps.location.isUpdated() && gps.altitude.isUpdated()) + { + RXGPSfix = true; + RXLat = gps.location.lat(); + RXLon = gps.location.lng(); + RXAlt = gps.altitude.meters(); + printRXLocation(); + LastRXGPSfixCheck = millis(); + + if ( FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1 + { + FixCount = DisplayRate; + dispscreen1(); + } + FixCount--; + } +} + + +bool readTXStatus(byte bitnum) +{ + return bitRead(TXStatus, bitnum); +} + + +void printRXLocation() +{ + Serial.print(F("LocalGPS ")); + Serial.print(RXLat, 5); + Serial.print(F(",")); + Serial.print(RXLon, 5); + Serial.print(F(",")); + Serial.print(RXAlt, 1); + Serial.println(); +} + + +void readPacketAddressing() +{ + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + LT.endReadSXBuffer(); +} + + +void packet_is_OK() +{ + //uint16_t IRQStatus; + float tempfloat; + + RXpacketCount++; + + readPacketAddressing(); + + if (PacketType == PowerUp) + { + LT.startReadSXBuffer(0); + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + LT.readUint8(); //read byte from SXBuffer, not used + TXVolts = LT.readUint16(); //read tracker transmitter voltage + LT.endReadSXBuffer(); + Serial.print(F("Tracker Powerup - Battery ")); + Serial.print(TXVolts); + Serial.println(F("mV")); + dispscreen2(); + } + + if (PacketType == LocationPacket) + { + //packet has been received, now read from the SX12XX FIFO in the correct order. + Serial.print(F("LocationPacket ")); + TXLocation = true; + LT.startReadSXBuffer(0); //start the read of received packet + PacketType = LT.readUint8(); //read in the PacketType + Destination = LT.readUint8(); //read in the Packet destination address + Source = LT.readUint8(); //read in the Packet source address + TXLat = LT.readFloat(); //read in the tracker latitude + TXLon = LT.readFloat(); //read in the tracker longitude + TXAlt = LT.readFloat(); //read in the tracker altitude + TXSats = LT.readUint8(); //read in the satellites in use by tracker GPS + TXHdop = LT.readUint32(); //read in the HDOP of tracker GPS + TXStatus = LT.readUint8(); //read in the tracker status byte + TXGPSFixTime = LT.readUint32(); //read in the last fix time of tracker GPS + TXVolts = LT.readUint16(); //read in the tracker supply\battery volts + TXupTimemS = LT.readUint32(); //read in the TX uptime in mS + RXPacketL = LT.endReadSXBuffer(); //end the read of received packet + + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 1); + Serial.print(F(",")); + Serial.print(TXSats); + Serial.print(F(",")); + + tempfloat = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display + Serial.print(tempfloat, 2); + + Serial.print(F(",")); + Serial.print(TXStatus); + Serial.print(F(",")); + + Serial.print(TXGPSFixTime); + Serial.print(F("mS,")); + Serial.print(TXVolts); + Serial.print(F("mV,")); + Serial.print((TXupTimemS / 1000)); + Serial.print(F("s,")); + + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); //and show the packet detail it on screen + return; + } + + + if (PacketType == LocationBinaryPacket) + { + //packet from locator has been received, now read from the SX12XX FIFO in the correct order. + TXLocation = true; + Serial.print(F("LocationBinaryPacket ")); + LT.startReadSXBuffer(0); + PacketType = LT.readUint8(); + Destination = LT.readUint8(); + Source = LT.readUint8(); + TXLat = LT.readFloat(); + TXLon = LT.readFloat(); + TXAlt = LT.readInt16(); + TXStatus = LT.readUint8(); + RXPacketL = LT.endReadSXBuffer(); + + if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation + { + TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon); + TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon); + } + else + { + TXdistance = 0; + TXdirection = 0; + } + + Serial.write(PacketType); + Serial.write(Destination); + Serial.write(Source); + Serial.print(F(",")); + Serial.print(TXLat, 5); + Serial.print(F(",")); + Serial.print(TXLon, 5); + Serial.print(F(",")); + Serial.print(TXAlt, 0); + Serial.print(F("m,")); + Serial.print(TXStatus); + Serial.print(F(",")); + Serial.print(TXdistance, 0); + Serial.print(F("m,")); + Serial.print(TXdirection); + Serial.print(F("d")); + printpacketDetails(); + dispscreen1(); + return; + } +} + + +void printpacketDetails() +{ + uint16_t IRQStatus; + Serial.print(F(",RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Packets,")); + Serial.print(RXpacketCount); + + Serial.print(F(",Length,")); + Serial.print(RXPacketL); + IRQStatus = LT.readIrqStatus(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } + + IRQStatus = LT.readIrqStatus(); //get the IRQ status + RXerrors++; + Serial.print(F("PacketError,RSSI")); + + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); //get the real packet length + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + digitalWrite(LED1, LOW); + + if (BUZZER >= 0) + { + digitalWrite(BUZZER, LOW); + delay(100); + digitalWrite(BUZZER, HIGH); + } +} + + +void led_Flash(uint16_t flashes, uint16_t delaymS) +{ + unsigned int index; + + for (index = 1; index <= flashes; index++) + { + digitalWrite(LED1, HIGH); + delay(delaymS); + digitalWrite(LED1, LOW); + delay(delaymS); + } +} + + +void dispscreen1() +{ + //show received packet data on display + float tempfloat; + disp.clearLine(0); + disp.setCursor(0, 0); + disp.print(TXLat, 5); + disp.clearLine(1); + disp.setCursor(0, 1); + disp.print(TXLon, 5); + disp.clearLine(2); + disp.setCursor(0, 2); + disp.print(TXAlt, 0); + disp.print(F("m")); + disp.clearLine(3); + disp.setCursor(0, 3); + + disp.print(F("RSSI ")); + disp.print(PacketRSSI); + disp.print(F("dBm")); + disp.clearLine(4); + disp.setCursor(0, 4); + disp.print(F("SNR ")); + + if (PacketSNR > 0) + { + disp.print(F("+")); + } + + if (PacketSNR == 0) + { + disp.print(F(" ")); + } + + if (PacketSNR < 0) + { + disp.print(F("-")); + } + + disp.print(PacketSNR); + disp.print(F("dB")); + + if (PacketType == LocationPacket) + { + disp.clearLine(5); + disp.setCursor(0, 5); + tempfloat = ((float) TXVolts / 1000); + disp.print(F("Batt ")); + disp.print(tempfloat, 2); + disp.print(F("v")); + } + + disp.clearLine(6); + disp.setCursor(0, 6); + disp.print(F("Packets ")); + disp.print(RXpacketCount); + + disp.clearLine(7); + + if (RXGPSfix) + { + disp.setCursor(15, 1); + disp.print(F("R")); + } + else + { + disp.setCursor(15, 1); + disp.print(F(" ")); + disp.setCursor(0, 7); + disp.print(F("No Local Fix")); + } + + if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix + { + disp.clearLine(7); + disp.setCursor(0, 7); + disp.print(TXdistance, 0); + disp.print(F("m ")); + disp.print(TXdirection); + disp.print(F("d")); + } + + if (readTXStatus(GPSFix)) + { + disp.setCursor(15, 0); + disp.write(Source); + } + +} + + +void dispscreen2() +{ + //show tracker powerup data on display + float tempfloat; + disp.clear(); + disp.setCursor(0, 0); + disp.print(F("Tracker Powerup")); + disp.setCursor(0, 1); + disp.print(F("Battery ")); + tempfloat = ((float) TXVolts / 1000); + disp.print(tempfloat, 2); + disp.print(F("v")); +} + + +void GPSON() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS + } +} + + +void GPSOFF() +{ + if (GPSPOWER >= 0) + { + digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS + } +} + + +void setup() +{ + uint32_t endmS; + + pinMode(LED1, OUTPUT); //setup pin as output for indicator LED + led_Flash(2, 125); //two quick LED flashes to indicate program start + + Serial.begin(9600); + Serial.println(); + Serial.print(F(__TIME__)); + Serial.print(F(" ")); + Serial.println(F(__DATE__)); + Serial.println(F(Program_Version)); + Serial.println(); + + Serial.println(F("25_GPS_Tracker_Receiver_With_Display_and_GPS Starting")); + + if (BUZZER >= 0) + { + pinMode(BUZZER, OUTPUT); + } + + SPI.begin(); + + disp.begin(); + disp.setFont(u8x8_font_chroma48medium8_r); + + Serial.print(F("Checking LoRa device - ")); //Initialize LoRa + disp.setCursor(0, 0); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, RX_EN, TX_EN, LORA_DEVICE)) + { + Serial.println(F("Receiver ready")); + disp.print(F("Receiver ready")); + led_Flash(2, 125); + delay(1000); + } + else + { + Serial.println(F("No LoRa device responding")); + disp.print(F("No LoRa device")); + while (1) + { + led_Flash(50, 50); //long fast speed flash indicates device error + } + } + + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate); + + Serial.println(); + Serial.println(F("Startup GPS check")); + + endmS = millis() + echomS; + + //now startup GPS + if (GPSPOWER >= 0) + { + pinMode(GPSPOWER, OUTPUT); + } + + GPSON(); + GPSserial.begin(GPSBaud); + + while (millis() < endmS) + { + while (GPSserial.available() > 0) + Serial.write(GPSserial.read()); + } + Serial.println(); + Serial.println(); + + Serial.println(F("Receiver ready")); + Serial.println(); +} + + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h new file mode 100644 index 0000000..fc36be7 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/25_GPS_Tracker_Receiver_With_Display_and_GPS/Settings.h @@ -0,0 +1,63 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19 + + This program is supplied as is, it is up to the user of the program to decide if the program is + suitable for the intended purpose and free from errors. +*******************************************************************************************************/ + + +//******* Setup hardware pin definitions here ! *************** + +//These are the pin definitions for one of my own boards, the Easy Pro Mini, +//be sure to change the definitiosn to match your own setup. Some pins such as DIO1, +//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be +//connected and should be set to -1. + +//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 on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX128X busy pin +#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done +#define RX_EN -1 //pin for RX enable, used on some SX1280 devices, set to -1 if not used +#define TX_EN -1 //pin for TX enable, used on some SX1280 devices, set to -1 if not used +#define LED1 8 //On board LED, high for on + +#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used + +#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 4 //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 + +#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0200; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + +//************************************************************************************************** +// GPS Settings +//************************************************************************************************** + +#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS +//#define HardwareSerialPort Serial1 //if using hardware serial enable this define for hardware serial port + +#define GPSBaud 9600 //GPS Baud rate +#define WaitGPSFixSeconds 30 //time to wait for a new GPS fix +#define echomS 2000 //number of mS to run GPS echo for at startup + +#define NoRXGPSfixms 15000 //max number of mS to allow before no local fix flagged +#define DisplayRate 7 //when working OK the GPS will get a new fix every second or so + //this rate defines how often the display should be updated + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino new file mode 100644 index 0000000..0a72f77 --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/38_lora_Relay/38_lora_Relay.ino @@ -0,0 +1,173 @@ +/******************************************************************************************************* + 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 will receive a lora packet and relay (re-transmit) it. The receiving + and transmitting can use different frequencies and lora settings, although in this example they are + the same. The receiving and transmitting settings are in the 'Settings.h' file. If the relay is located + in an advantageous position, for instance on top of a tall tree, building or in an radio controlled model + then the range at which trackers or nodes on the ground can be received is considerably increased. + In these circumstances the relay may listen at a long range setting using SF12 for example and then + re-transmit back to the ground at SF7. + + For an example of the use of such a program see this report; + + How to Search 500 Square Kilometres in 10 minutes.pdf in the libraries 'Test_Reports' folder. + + Serial monitor baud rate is set at 9600. + +*******************************************************************************************************/ + + +#include +#include +#include "Settings.h" + +SX128XLT LT; + +uint8_t RXPacketL, TXPacketL; +int8_t PacketRSSI, PacketSNR; +uint16_t RXPacketErrors; + + +void loop() +{ + LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate); + + RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set + + digitalWrite(LED1, HIGH); //something has happened + + if (BUZZER > 0) //turn buzzer on + { + digitalWrite(BUZZER, HIGH); + } + + PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value + PacketSNR = LT.readPacketSNR(); //read the received SNR value + + if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0 + { + packet_is_Error(); + } + else + { + packet_is_OK(); + } + + if (BUZZER > 0) + { + digitalWrite(BUZZER, LOW); //buzzer off + } + + Serial.println(); +} + + +void packet_is_OK() +{ + //a packet has been received, so change to relay settings and transmit buffer + + Serial.print(F("PacketOK ")); + printreceptionDetails(); + delay(packet_delay / 2); + digitalWrite(LED1, LOW); + delay(packet_delay / 2); + + Serial.print(F(" Retransmit")); + LT.setupLoRa(RelayFrequency, RelayOffset, RelaySpreadingFactor, RelayBandwidth, RelayCodeRate); + digitalWrite(LED1, HIGH); + TXPacketL = LT.transmitSXBuffer(0, RXPacketL, 10000, TXpower, WAIT_TX); + Serial.print(F(" - Done")); + digitalWrite(LED1, LOW); +} + + +void packet_is_Error() +{ + uint16_t IRQStatus; + + RXPacketErrors++; + IRQStatus = LT.readIrqStatus(); + + led_Flash(5, 50); + + if (IRQStatus & IRQ_RX_TIMEOUT) + { + Serial.print(F("RXTimeout ")); + } + else + { + Serial.print(F("PacketError ")); + printreceptionDetails(); + Serial.print(F(",IRQreg,")); + Serial.print(IRQStatus, HEX); + LT.printIrqStatus(); + } +} + + +void printreceptionDetails() +{ + Serial.print(F("RSSI,")); + Serial.print(PacketRSSI); + Serial.print(F("dBm,SNR,")); + Serial.print(PacketSNR); + Serial.print(F("dB,Length,")); + Serial.print(LT.readRXPacketL()); +} + + +void led_Flash(uint16_t flashdelay, uint16_t flashes) +{ + uint16_t index; + + for (index = 1; index <= flashes; index++) + { + + delay(flashdelay); + digitalWrite(LED1, HIGH); + delay(flashdelay); + digitalWrite(LED1, LOW); + } +} + + +void setup() +{ + pinMode(LED1, OUTPUT); + led_Flash(2, 125); + + Serial.begin(9600); + + SPI.begin(); + + if (LT.begin(NSS, NRESET, RFBUSY, DIO1, 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); + Serial.print("ListenSettings,"); + LT.printModemSettings(); + Serial.println(); + LT.setupLoRa(RelayFrequency, RelayOffset, RelaySpreadingFactor, RelayBandwidth, RelayCodeRate); + Serial.print("RelaySettings,"); + LT.printModemSettings(); + Serial.println(); + Serial.println("Relay Ready"); +} + + diff --git a/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/38_lora_Relay/Settings.h b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/38_lora_Relay/Settings.h new file mode 100644 index 0000000..a84a0ff --- /dev/null +++ b/lib/SX12XX-LoRa/examples/SX128x_examples/Tracker/38_lora_Relay/Settings.h @@ -0,0 +1,46 @@ +/******************************************************************************************************* + 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. + +#define NSS 10 //select on LoRa device +#define NRESET 9 //reset on LoRa device +#define RFBUSY 7 //SX128X busy pin +#define DIO1 3 //DIO1 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 LED1 8 //On board LED, high for on +#define BUZZER -1 //normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using + + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 2445000000; //frequency of transmissions +const int32_t Offset = 0; //offset frequency for calibration purposes +const uint8_t Bandwidth = LORA_BW_0200; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate + +//LoRa relay (re-transmitting) parameters +const uint32_t RelayFrequency = 2445000000; //frequency of transmissions +const uint32_t RelayOffset = 0; //offset frequency for calibration purposes + +const uint8_t RelayBandwidth = LORA_BW_0400; //LoRa bandwidth +const uint8_t RelaySpreadingFactor = LORA_SF7; //LoRa spreading factor +const uint8_t RelayCodeRate = LORA_CR_4_5; //LoRa coding rate + + +const int8_t TXpower = 10; //LoRa TX power in dBm + +#define packet_delay 1000 //mS delay before received packet transmitted + diff --git a/lib/SX12XX-LoRa/keywords.txt b/lib/SX12XX-LoRa/keywords.txt new file mode 100644 index 0000000..7ecf5d5 --- /dev/null +++ b/lib/SX12XX-LoRa/keywords.txt @@ -0,0 +1,191 @@ +####################################### +# Syntax Coloring Map For SX12XXXLT +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SX126XLT KEYWORD1 +SX127XLT KEYWORD1 +SX128XLT KEYWORD1 +ProgramLT_Definitions KEYWORD1 +SX127XLT_Definitions KEYWORD1 +SX126XLT_Definitions KEYWORD1 +SX128XLT_Definitions KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +pinInit KEYWORD2 +spiInit KEYWORD2 +setupLoRa KEYWORD2 +resetDevice KEYWORD2 +setMode KEYWORD2 +checkBusy KEYWORD2 +setSleep KEYWORD2 +setRegulatorMode KEYWORD2 +checkDevice KEYWORD2 +setDevice KEYWORD2 +config KEYWORD2 +readsavedRegulatorMode KEYWORD2 +setDIO2AsRfSwitchCtrl KEYWORD2 +setDIO3AsTCXOCtrl KEYWORD2 +clearDeviceErrors KEYWORD2 +calibrateDevice KEYWORD2 +printDeviceErrors KEYWORD2 +wake KEYWORD2 +calibrateImage KEYWORD2 +CRCCCITTSX KEYWORD2 +CRCCCITT KEYWORD2 +printSXBufferASCII KEYWORD2 +receiveAddressed KEYWORD2 +getByteSXBuffer KEYWORD2 +startWriteSXBuffer KEYWORD2 +transmitAddressed KEYWORD2 +startReadSXBuffer KEYWORD2 +endReadSXBuffer KEYWORD2 +readBuffer KEYWORD2 +receiveSXBuffer KEYWORD2 +transmitSXBuffer KEYWORD2 +endWriteSXBuffer KEYWORD2 +writeBuffer KEYWORD2 +readPacket KEYWORD2 +setSleep KEYBOARD2 +getOperatingMode KEYWORD2 +writeCommand KEYWORD2 +readCommand KEYWORD2 +writeRegisters KEYWORD2 +writeRegister KEYWORD2 +readRegisters KEYWORD2 +readRegister KEYWORD2 +printRegisters KEYWORD2 +setPacketParams KEYWORD2 +setModulationParams KEYWORD2 +printSavedModulationParams KEYWORD2 +setRfFrequency KEYWORD2 +getFreqInt KEYWORD2 +getFrequencyErrorRegValue KEYWORD2 +getFrequencyErrorHz KEYWORD2 +setTxParams KEYWORD2 +setTx KEYWORD2 +readTXDone KEYWORD2 +setRx KEYWORD2 +setLowPowerRX KEYWORD2 +setHighSensitivity KEYWORD2 +setRXGain KEYWORD2 +readRXDone KEYWORD2 +readRXBufferStatus KEYWORD2 +readRXPacketL KEYWORD2 +readPacketRSSI KEYWORD2 +readPacketSNR KEYWORD2 +setPaConfig KEYWORD2 +setRx2 KEYWORD2 +setRxDutyCycle KEYWORD2 +readRXBufferPointer KEYWORD2 +readsavedFrequency KEYWORD2 +readsavedOffset KEYWORD2 +setBufferBaseAddress KEYWORD2 +setPacketType KEYWORD2 +readsavedPacketType KEYWORD2 +clearIrqStatus KEYWORD2 +readIrqStatus KEYWORD2 +setDioIrqParams KEYWORD2 +printIrqStatus KEYWORD2 +readPacketCRCError KEYWORD2 +readPacketHeaderValid KEYWORD2 +readPacketHeaderError KEYWORD2 +readsavedPower KEYWORD2 +printASCIIorHEX KEYWORD2 +printHEXByte KEYWORD2 +printHEXByte0x KEYWORD2 +printASCIIPacket KEYWORD2 +printHEXPacket KEYWORD2 +readsavedModParam1 KEYWORD2 +readsavedModParam2 KEYWORD2 +readsavedModParam3 KEYWORD2 +readsavedModParam4 KEYWORD2 +readRXPacketType KEYWORD2 +readRXDestination KEYWORD2 +readRXSource KEYWORD2 +printAddressInfo KEYWORD2 +returnSF KEYWORD2 +returnbandwidth KEYWORD2 +readPacketAddressedLoRa KEYWORD2 +getOptimisation KEYWORD2 +calcSymbolTime KEYWORD2 +printModemSettings KEYWORD2 +printOperatingSettings KEYWORD2 +setSyncWord KEYWORD2 +startWriteFIFO KEYWORD2 +endWriteFIFO KEYWORD2 +startReadFIFO KEYWORD2 +endReadFIFO KEYWORD2 +writeUint8 KEYWORD2 +readUint8 KEYWORD2 +writeInt8 KEYWORD2 +readInt8 KEYWORD2 +writeInt16 KEYWORD2 +readInt16 KEYWORD2 +writeUint16 KEYWORD2 +readUint16 KEYWORD2 +writeInt32 KEYWORD2 +readInt32 KEYWORD2 +writeUint32 KEYWORD2 +readUint32 KEYWORD2 +writeFloat KEYWORD2 +readFloat KEYWORD2 +rxtxInit KEYWORD2 +rxEnable KEYWORD2 +txEnable KEYWORD2 +getLoRaBandwidth KEYWORD2 +setRangingRangingAddress KEYWORD2 +setRangingRequestAddress KEYWORD2 +setRangingRole KEYWORD2 +setRangingCalibration KEYWORD2 +getRangingResult KEYWORD2 +complement2 KEYWORD2 +getRangingResultRegValue KEYWORD2 +setupRanging KEYWORD2 +transmitRanging KEYWORD2 +receiveRanging KEYWORD2 +getRangingDistance KEYWORD2 +setRangingMasterAddress KEYWORD2 +setRangingSlaveAddress KEYWORD2 +getRangingCalibrationValue KEYWORD2 +toneFM KEYWORD2 +setupDirect KEYWORD2 +printDevice KEYWORD2 +getLoRaSF KEYWORD2 +getLoRaCodingRate KEYWORD2 +getSyncWord KEYWORD2 +getInvertIQ KEYWORD2 +getPreamble KEYWORD2 +printOperatingMode KEYWORD2 +getVersion KEYWORD2 +getPacketMode KEYWORD2 +getHeaderMode KEYWORD2 +getCRCMode KEYWORD2 +getAGC KEYWORD2 +getLNAgain KEYWORD2 +getLNAboostHF KEYWORD2 +getLNAboostLF KEYWORD2 +getOpmode KEYWORD2 +fillSXBuffer KEYWORD2 +writeByteSXBuffer KEYWORD2 +doAFC KEYWORD2 +getOffset KEYWORD2 +startFSKRTTY KEYWORD2 +transmitFSKRTTY KEYWORD2 +printRTTYregisters KEYWORD2 +endFSKRTTY KEYWORD2 +printSXBufferHEX KEYWORD2 +readBufferChar KEYWORD2 +writeBufferChar KEYWORD2 +setLowPowerReceive KEYWORD2 +doAFCPPM KEYWORD2 +setTXDirect KEYWORD2 + + diff --git a/lib/SX12XX-LoRa/library.properties b/lib/SX12XX-LoRa/library.properties new file mode 100644 index 0000000..d78e4eb --- /dev/null +++ b/lib/SX12XX-LoRa/library.properties @@ -0,0 +1,9 @@ +name=SX12XXLT LoRa library +version=1.0.0 +author=Stuart Robinson +maintainer=sorry@no.spam +sentence=Arduino library for SX12xx LoRa device +paragraph=Supports SX1261,SX1262,SX1268,SX1272,SX1276,SX1277,SX1278,SX1279,SX1280,SX1281 devices +category=Communication +url=https://github.com/StuartsProjects/SX12XX-LoRa +architectures=* diff --git a/lib/SX12XX-LoRa/pictures/Atmel Watchdog Sleep Time.jpg b/lib/SX12XX-LoRa/pictures/Atmel Watchdog Sleep Time.jpg new file mode 100644 index 0000000..04ec92d Binary files /dev/null and b/lib/SX12XX-LoRa/pictures/Atmel Watchdog Sleep Time.jpg differ diff --git a/lib/SX12XX-LoRa/pictures/ESP32_Bare_Bones_circuit.pdf b/lib/SX12XX-LoRa/pictures/ESP32_Bare_Bones_circuit.pdf new file mode 100644 index 0000000..d307b14 Binary files /dev/null and b/lib/SX12XX-LoRa/pictures/ESP32_Bare_Bones_circuit.pdf differ diff --git a/lib/SX12XX-LoRa/src/AFSKRTTY.h b/lib/SX12XX-LoRa/src/AFSKRTTY.h new file mode 100644 index 0000000..e8cb1c8 --- /dev/null +++ b/lib/SX12XX-LoRa/src/AFSKRTTY.h @@ -0,0 +1,75 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 12/05/20 +*/ + +void startAFSKRTTY(int8_t audiopin, uint16_t freq, uint32_t afskleadinmS) +{ + tone(audiopin, freq); //lead in is high tone + delay(afskleadinmS); +} + + +void endAFSKRTTY(int8_t audiopin) +{ + delay(500); //500mS seconds of high tone to finish + noTone(audiopin); +} + + +void sendAFSKRTTY(uint8_t chartosend, int8_t audiopin, int8_t checkpin, uint16_t tonelowHz, uint16_t tonehighHz, uint32_t perioduS) +//send the byte in chartosend as AFSK RTTY, assumes mark condition (idle) is already present +//Format is 7 bits, no parity and 2 stop bits +{ + uint8_t numbits; + uint32_t startuS; + + startuS = micros(); + digitalWrite(checkpin, LOW); + tone(audiopin, tonelowHz); + + while ( (uint32_t) (micros() - startuS) < perioduS); //wait for start bit end + + for (numbits = 1; numbits <= 7; numbits++) //send 7 bits, LSB first + { + startuS = micros(); + if ((chartosend & 0x01) != 0) + { + digitalWrite(checkpin, HIGH); + tone(audiopin, tonehighHz); + } + else + { + digitalWrite(checkpin, LOW); + tone(audiopin, tonelowHz); //start 0 bit low tone + } + chartosend = (chartosend / 2); //get the next bit + while ( (uint32_t) (micros() - startuS) < perioduS); //wait bit period uS + } + perioduS = perioduS * 2; + startuS = micros(); + digitalWrite(checkpin, HIGH); //start mark condition + tone(audiopin, tonehighHz); //start high tone + while ( (uint32_t) (micros() - startuS) < perioduS); +} + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/lib/SX12XX-LoRa/src/AFSKRTTY2.h b/lib/SX12XX-LoRa/src/AFSKRTTY2.h new file mode 100644 index 0000000..98e1b1e --- /dev/null +++ b/lib/SX12XX-LoRa/src/AFSKRTTY2.h @@ -0,0 +1,180 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 18/12/20 +*/ + + +/* + This is the AFSK RTTY send library specifically for microcontrollers that do not have a tone() function + such as Arduino DUE and ESP32. Tones are generated here by manually toggling the selected tone pin with + a suitable delay between toggles. + + The baud rate and tone frequecies used can be adjusted by usin the startAFSKRTTY() command. + + The library has been tested and will work on an Arduion Pro Mini 8Mhz, Arduino DUE and ESP32 and when + used with this startup command; + + startAFSKRTTY(AUDIOOUTpin, CHECKpin, 5, 1000, 7, 714, 0, 1000); + + This outputs AFSKRTTY at 100baud, 7bit, no parity, 1stop bit, low tone 1000hz, hightone 1400hz. + + The audio comes out of the pin passed via AUDIOOUTpin and the bit timing can be checked by looking at + the CHECKpin on a scope or analyser. + + A low pass filter consiting of a 47K resistor and 470nF capacitor was used to redice the output for + feeding into a PC soundcard. + +*/ + + + +#define AFSKRTTY_UNUSED(v) (void) (v) //add AFSKRTTY_UNUSED(variable); in functions to avoid compiler warnings + +int8_t _audiopin, _checkpin, _adjust; +uint8_t _lowcycles, _highcycles; +uint32_t _lowperioduS, _highperioduS; + +void startAFSKRTTY(int8_t audiopin, int8_t checkpin, uint8_t lowcycles, uint16_t lowperioduS, uint8_t highcycles, uint16_t highperioduS, int16_t adjust, uint16_t leadinmS); +void sendAFSKRTTY(uint8_t chartosend); +void toneHigh(); +void toneLow(); + + +void startAFSKRTTY(int8_t audiopin, int8_t checkpin, uint8_t lowcycles, uint16_t lowperioduS, uint8_t highcycles, uint16_t highperioduS, int16_t adjust, uint16_t leadinmS) +{ + uint32_t startmS; + _audiopin = audiopin; + _checkpin = checkpin; + _lowperioduS = (lowperioduS / 2) + adjust; //period passed is equal to frequency, but delays are in two halfs + _highperioduS = (highperioduS / 2) + adjust; + _lowcycles = lowcycles; + _highcycles = highcycles; + _adjust = adjust; + + if (audiopin > 0) + { + pinMode(audiopin, OUTPUT); + } + + if (checkpin > 0) + { + pinMode(checkpin, OUTPUT); + } + + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < leadinmS) //allows for millis() overflow + { + digitalWrite(audiopin, HIGH); + delayMicroseconds(_highperioduS); + digitalWrite(audiopin, LOW); + delayMicroseconds(_highperioduS); + } +} + + +void endAFSKRTTY(int8_t audiopin, int8_t checkpin, uint16_t leadoutmS) +{ + uint32_t startmS; + + startmS = millis(); + + while ( (uint32_t) (millis() - startmS) < leadoutmS) //allows for millis() overflow + { + digitalWrite(audiopin, HIGH); + delayMicroseconds(_highperioduS); + digitalWrite(audiopin, LOW); + delayMicroseconds(_highperioduS); + } + + if (audiopin > 0) + { + pinMode(audiopin, INPUT); + } + + if (checkpin > 0) + { + pinMode(checkpin, INPUT); + } +} + + +void toneHigh() +{ + uint8_t index; + + for (index = 1; index <= _highcycles; index++) + { + digitalWrite(_audiopin, HIGH); + delayMicroseconds(_highperioduS); + digitalWrite(_audiopin, LOW); + delayMicroseconds(_highperioduS); + } + +} + + +void toneLow() +{ + uint8_t index; + + for (index = 1; index <= _lowcycles; index++) + { + digitalWrite(_audiopin, HIGH); + delayMicroseconds(_lowperioduS); + digitalWrite(_audiopin, LOW); + delayMicroseconds(_lowperioduS); + } + +} + + + +void sendAFSKRTTY(uint8_t chartosend) +//send the byte in chartosend as AFSK RTTY, assumes mark condition (idle) is already present +//Format is 7 bits, no parity and 2 stop bits +{ + + uint8_t numbits; + digitalWrite(_checkpin, LOW); + toneLow(); + + for (numbits = 1; numbits <= 7; numbits++) //send 7 bits, LSB first + { + if ((chartosend & 0x01) != 0) + { + digitalWrite(_checkpin, HIGH); + toneHigh(); + } + else + { + digitalWrite(_checkpin, LOW); + toneLow(); + } + chartosend = (chartosend / 2); //get the next bit + } + digitalWrite(_checkpin, HIGH); //start mark condition + toneHigh(); + toneHigh(); +} + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/lib/SX12XX-LoRa/src/AtmelSleep.h b/lib/SX12XX-LoRa/src/AtmelSleep.h new file mode 100644 index 0000000..96bf09f --- /dev/null +++ b/lib/SX12XX-LoRa/src/AtmelSleep.h @@ -0,0 +1,101 @@ +/******************************************************************************************************* + Programs for Arduino - Copyright of the author Stuart Robinson - 24/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. + + These are sleep routines for Atmel processors, tested on ATmega328. When calling the sleep routines be + sure there are no pending interrupts such as from Serial.print(), strange things can happen otherwise. +*******************************************************************************************************/ + + + +#include //sleep library for Atmel processor +#include //watchdog library for Atmel processor + + +//Atmel watchdog sleep times +#define sleep16mS 0x00 +#define sleep32mS 0x01 +#define sleep64mS 0x02 +#define sleep125mS 0x03 +#define sleep250mS 0x04 +#define sleep500mS 0x05 +#define sleep1000mS 0x06 +#define sleep2000mS 0x07 +#define sleep4000mS 0x20 +#define sleep8000mS 0x21 + + +void SleepSeconds(uint32_t secs); +void SleepmS(uint32_t sleeps, uint8_t numbermS); +void atmelSleepPermanent(); + + +void SleepSeconds(uint32_t secs) +{ + //for Atmel processor only + uint16_t sleeps8secs, sleeps1secs; + + sleeps8secs = secs >> 3; + sleeps1secs = secs - (sleeps8secs << 3); + SleepmS(sleeps8secs, sleep8000mS); + SleepmS(sleeps1secs, sleep1000mS); +} + + + +void SleepmS(uint32_t sleeps, uint8_t numbermS) +{ + //for Atmel processor only + 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) + numbermS; //set the number of mS for sleep + wdt_reset(); //pat the pet, could be a 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 atmelSleepPermanent() +{ + 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(); +} + + + +ISR (WDT_vect) +{ + //watchdog interrupt + wdt_disable(); // disable watchdog +} + + diff --git a/lib/SX12XX-LoRa/src/EEPROM_Memory.h b/lib/SX12XX-LoRa/src/EEPROM_Memory.h new file mode 100644 index 0000000..e61f89f --- /dev/null +++ b/lib/SX12XX-LoRa/src/EEPROM_Memory.h @@ -0,0 +1,88 @@ +/* + Copyright 2020 - Stuart Robinson + 24/04/20 +*/ + +/******************************************************************************************************* + Library Operation - This library is for reading from and writing to the EEPROM. These routines provide + a funtional match to the libraries for FRAM. + +*******************************************************************************************************/ + +#include +#define LTUNUSED(v) (void) (v) //add LTUNUSED(variable); in functions to avoid compiler warnings + +void memoryStart(uint16_t addr) //yes I know the EEPROM does not have an address, but the other memory types do +{ + //left empty for future use + LTUNUSED(addr); //avoids compliler warning +} + + +void memoryEnd() +{ + //left empty for future use +} + + +void writeMemoryUint8(uint16_t addr, uint8_t x) +{ + //write a byte to the EEPROM + EEPROM.put(addr, x); +} + + +uint16_t readMemoryUint16(uint16_t addr) +{ + uint16_t x; + EEPROM.get(addr, x); + return x; +} + + +uint32_t readMemoryUint32(uint16_t addr) +{ + uint32_t x; + EEPROM.get(addr, x); + return x; +} + + +void writeMemoryUint32(uint16_t addr, uint32_t x) +{ + EEPROM.put(addr, x); +} + + +void writeMemoryUint16(uint16_t addr, uint16_t x) +{ + EEPROM.put(addr, x); +} + + +float readMemoryFloat(uint16_t addr) +{ + float x; + EEPROM.get(addr, x); + return x; +} + + +void writeMemoryFloat(uint16_t addr, float x) +{ + EEPROM.put(addr, x); +} + + +void fillMemory(uint16_t startaddr, uint16_t endaddr, uint8_t lval) +{ + uint32_t i; + for (i = startaddr; i <= endaddr; i++) + { + writeMemoryUint8(i, lval); + } +} + + + + diff --git a/lib/SX12XX-LoRa/src/FRAM_FM24CL64.h b/lib/SX12XX-LoRa/src/FRAM_FM24CL64.h new file mode 100644 index 0000000..574a4df --- /dev/null +++ b/lib/SX12XX-LoRa/src/FRAM_FM24CL64.h @@ -0,0 +1,462 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + 14/04/20 +*/ + + +/******************************************************************************************************* + Library Operation - This library is for reading from and writing to the 64kbit (8kbyte) I2C FRAMS. + + Take care when writing variables to the end of the address space, the writes and reads may wrap + around back to address 0 +*******************************************************************************************************/ + +#include + +int16_t Memory_I2C_Addr = 0x50; //default I2C address of FM24CL64 FRAM + + +void memoryStart(int16_t addr) +{ + Memory_I2C_Addr = addr; + Wire.begin(); +} + + +void memorySetAddress(int16_t addr) +{ + Memory_I2C_Addr = addr; + +} + + +void memoryEnd() +{ + //left empty for future use +} + + +/*************************************************************************** + Write Routines + *************************************************************************** +*/ + + +void writeMemoryChar(uint16_t addr, char x) +{ + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.write(x); + Wire.endTransmission(); +} + + +void writeMemoryInt8(uint16_t addr, int8_t x) +{ + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.write(x); + Wire.endTransmission(); +} + + +void writeMemoryUint8(uint16_t addr, uint8_t x) +{ + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.write(x); + Wire.endTransmission(); +} + + +void writeMemoryInt16(uint16_t addr, int16_t x) +{ + + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + uint8_t msb_data = highByte(x); + uint8_t lsb_data = lowByte(x); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.write(lsb_data); + Wire.write(msb_data); + Wire.endTransmission(); +} + + +void writeMemoryUint16(uint16_t addr, uint16_t x) +{ + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + uint8_t msb_data = highByte(x); + uint8_t lsb_data = lowByte(x); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.write(lsb_data); + Wire.write(msb_data); + Wire.endTransmission(); +} + + +void writeMemoryInt32(uint16_t addr, int32_t x) +{ + uint8_t index, val; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + union + { + uint8_t b[4]; + uint32_t f; + } data; + + data.f = x; + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + + for (index = 0; index < 4; index++) + { + val = data.b[index]; + Wire.write(val); //write the data + } + + Wire.endTransmission(); +} + + +void writeMemoryUint32(uint16_t addr, uint32_t x) +{ + uint8_t index, val; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + union + { + uint8_t b[4]; + uint32_t f; + } data; + + data.f = x; + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + + for (index = 0; index < 4; index++) + { + val = data.b[index]; + Wire.write(val); //write the data + } + + Wire.endTransmission(); +} + + +void writeMemoryFloat(uint16_t addr, float x) +{ + uint8_t index, val; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + union + { + uint8_t b[4]; + float f; + } data; + + data.f = x; + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + + for (index = 0; index < 4; index++) + { + val = data.b[index]; + Wire.write(val); //write the data + } + + Wire.endTransmission(); +} + + +/*************************************************************************** + Read Routines + ************************************************************************** +*/ + +char readMemoryChar(uint16_t addr) +{ + char data; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom((Memory_I2C_Addr), 1); + data = Wire.read(); + return data; +} + + +int8_t readMemoryInt8(uint16_t addr) +{ + int8_t data; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom((Memory_I2C_Addr), 1); + data = Wire.read(); + return data; +} + + +uint8_t readMemoryUint8(uint16_t addr) +{ + uint8_t data; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom((Memory_I2C_Addr), 1); + data = Wire.read(); + return data; +} + + +int16_t readMemoryInt16(uint16_t addr) +{ + + uint8_t lsb_data, msb_data; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr, 2); + lsb_data = Wire.read(); + msb_data = Wire.read(); + + return (lsb_data + (msb_data * 256)); +} + + +uint16_t readMemoryUint16(uint16_t addr) +{ + + uint8_t lsb_data, msb_data; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr, 2); + lsb_data = Wire.read(); + msb_data = Wire.read(); + + return (lsb_data + (msb_data * 256)); +} + + +int32_t readMemoryInt32(uint16_t addr) +{ + uint8_t val; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr, 4); + + union + { + uint8_t b[4]; + unsigned long f; + } readdata; + + for (int index = 0; index < 4; index++) + { + val = Wire.read(); // read the uint8_t + readdata.b[index] = val; + } + + return readdata.f; +} + + +uint32_t readMemoryUint32(uint16_t addr) +{ + uint8_t val; + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr, 4); + + union + { + uint8_t b[4]; + unsigned long f; + } readdata; + + for (int index = 0; index < 4; index++) + { + val = Wire.read(); // read the uint8_t + readdata.b[index] = val; + } + + return readdata.f; +} + + +float readMemoryFloat(uint16_t addr) +{ + uint8_t val; + + uint8_t msb_addr = highByte(addr); + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr); + Wire.write(msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr, 4); + + union + { + uint8_t b[4]; + float f; + } readdata; + + + for (int index = 0; index < 4; index++) + { + val = Wire.read(); // read the uint8_t + readdata.b[index] = val; + } + return readdata.f; +} + + +/*************************************************************************** + Start of general purpose memory routines +***************************************************************************/ + +uint16_t CRCMemory(uint16_t startaddr, uint16_t endaddr, uint16_t startval) +{ + uint16_t i, libraryCRC; + uint8_t j; + + libraryCRC = startval; //start value for CRC16, often 0xffff + + for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start + { + libraryCRC ^= ((uint16_t)readMemoryUint8(i) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + return libraryCRC; + +} + + +void printMemory(uint16_t start_addr, uint16_t end_addr) +{ + //print the contents of Memory + + uint8_t value; + + for (uint16_t a = start_addr; a <= end_addr; a++) + { + value = readMemoryUint8(a); + if ((a % 16) == 0) + { + Serial.println(); + Serial.print(F("0x")); + if (a < 0x10) + { + Serial.print('0'); + } + Serial.print(a, HEX); + Serial.print(F(": ")); + } + Serial.print(F("0x")); + if (value < 0x10) + Serial.print('0'); + Serial.print(value, HEX); + Serial.print(F(" ")); + } + Serial.println(); +} + + +void fillMemory(uint16_t startaddr, uint16_t endaddr, uint8_t lval) +{ + uint16_t i; + for (i = startaddr; i <= endaddr; i++) + { + writeMemoryUint8(i, lval); + } +} + + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ diff --git a/lib/SX12XX-LoRa/src/FRAM_MB85RC16PNF.h b/lib/SX12XX-LoRa/src/FRAM_MB85RC16PNF.h new file mode 100644 index 0000000..d879ed7 --- /dev/null +++ b/lib/SX12XX-LoRa/src/FRAM_MB85RC16PNF.h @@ -0,0 +1,447 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + 14/04/20 +*/ + +/******************************************************************************************************* + Library Operation - This library is for reading from and writing to the 16kbit (2Kbyte) I2C FRAMS. + These FRAMS present as a series of eight 256 byte pages at I2C addresses 0X50 to 0x57. The library + calculates from the passed address which page to write to. For variables that are larger than one + uint8_t take care not to set the address so that a write would cross a page boundary. The library + does not deal with writes or reads that cross the 256 byte pages of the device. +*******************************************************************************************************/ + +#include + +int16_t Memory_I2C_Addr = 0x50; //default I2C address of MB85RC16PNF FRAM + + +void memoryStart(int16_t addr) +{ + Memory_I2C_Addr = addr; + Wire.begin(); +} + + +void memorySetAddress(int16_t addr) +{ + Memory_I2C_Addr = addr; + +} + + +void memoryEnd() +{ + //left empty for future use +} + + +/*************************************************************************** + Write Routines + **************************************************************************/ + +void writeMemoryChar(uint16_t addr, char x) +{ + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.write(x); + Wire.endTransmission(); +} + + +void writeMemoryInt8(uint16_t addr, int8_t x) +{ + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.write(x); + Wire.endTransmission(); +} + + +void writeMemoryUint8(uint16_t addr, uint8_t x) +{ + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.write(x); + Wire.endTransmission(); +} + + +void writeMemoryInt16(uint16_t addr, int16_t x) +{ + + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + uint8_t msb_data = highByte(x); + uint8_t lsb_data = lowByte(x); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.write(lsb_data); + Wire.write(msb_data); + Wire.endTransmission(); +} + + +void writeMemoryUint16(uint16_t addr, uint16_t x) +{ + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + uint8_t msb_data = highByte(x); + uint8_t lsb_data = lowByte(x); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.write(lsb_data); + Wire.write(msb_data); + Wire.endTransmission(); +} + + +void writeMemoryInt32(uint16_t addr, int32_t x) +{ + uint8_t index, val; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + union + { + uint8_t b[4]; + uint32_t f; + } data; + + data.f = x; + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + + for (index = 0; index < 4; index++) + { + val = data.b[index]; + Wire.write(val); //write the data + } + + Wire.endTransmission(); +} + + + +void writeMemoryUint32(uint16_t addr, uint32_t x) +{ + uint8_t index, val; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + union + { + uint8_t b[4]; + uint32_t f; + } data; + + data.f = x; + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + + for (index = 0; index < 4; index++) + { + val = data.b[index]; + Wire.write(val); //write the data + } + + Wire.endTransmission(); +} + + +void writeMemoryFloat(uint16_t addr, float x) +{ + uint8_t index, val; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + union + { + uint8_t b[4]; + float f; + } data; + + data.f = x; + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + + for (index = 0; index < 4; index++) + { + val = data.b[index]; + Wire.write(val); //write the data + } + + Wire.endTransmission(); +} + +/*************************************************************************** + Read Routines + ************************************************************************** +*/ + + +char readMemoryChar(uint16_t addr) +{ + char data; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom((Memory_I2C_Addr + msb_addr), 1); + data = Wire.read(); + return data; +} + + +int8_t readMemoryInt8(uint16_t addr) +{ + int8_t data; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom((Memory_I2C_Addr + msb_addr), 1); + data = Wire.read(); + return data; +} + + +uint8_t readMemoryUint8(uint16_t addr) +{ + uint8_t data; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom((Memory_I2C_Addr + msb_addr), 1); + data = Wire.read(); + return data; +} + + +int16_t readMemoryInt16(uint16_t addr) +{ + + uint8_t lsb_data, msb_data; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr + msb_addr, 2); + lsb_data = Wire.read(); + msb_data = Wire.read(); + + return (lsb_data + (msb_data * 256)); +} + + +uint16_t readMemoryUint16(uint16_t addr) +{ + + uint8_t lsb_data, msb_data; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr + msb_addr, 2); + lsb_data = Wire.read(); + msb_data = Wire.read(); + + return (lsb_data + (msb_data * 256)); +} + + +int32_t readMemoryInt32(uint16_t addr) +{ + uint8_t val, index; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr + msb_addr, 4); + + union + { + uint8_t b[4]; + uint32_t f; + } readdata; + + for (index = 0; index < 4; index++) + { + val = Wire.read(); // read the uint8_t + readdata.b[index] = val; + } + + return readdata.f; +} + + +uint32_t readMemoryUint32(uint16_t addr) +{ + uint8_t val, index; + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr + msb_addr, 4); + + union + { + uint8_t b[4]; + uint32_t f; + } readdata; + + for (index = 0; index < 4; index++) + { + val = Wire.read(); // read the uint8_t + readdata.b[index] = val; + } + + return readdata.f; +} + + +float readMemoryFloat(uint16_t addr) +{ + uint8_t val, index; + + uint8_t msb_addr = (highByte(addr) & 0x07); //get 3 MSB bits of address + uint8_t lsb_addr = lowByte(addr); + + Wire.beginTransmission(Memory_I2C_Addr + msb_addr); + Wire.write(lsb_addr); + Wire.endTransmission(); + Wire.requestFrom(Memory_I2C_Addr + msb_addr, 4); + + union + { + uint8_t b[4]; + float f; + } readdata; + + + for (index = 0; index < 4; index++) + { + val = Wire.read(); // read the uint8_t + readdata.b[index] = val; + } + return readdata.f; +} + + +/*************************************************************************** + Start of general purpose memory routines +***************************************************************************/ + +uint16_t CRCMemory(uint16_t startaddr, uint16_t endaddr, uint16_t startval) +{ + uint16_t i, libraryCRC; + uint8_t j; + + libraryCRC = startval; //start value for CRC16, often 0xffff + + for (i = startaddr; i <= endaddr; i++) //element 4 is first character after $$$$ at start + { + libraryCRC ^= ((uint16_t)readMemoryUint8(i) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + return libraryCRC; + +} + + +void printMemory(uint16_t start_addr, uint16_t end_addr) +{ + //print the contents of Memory + + uint8_t value; + + for (uint16_t a = start_addr; a <= end_addr; a++) + { + value = readMemoryUint8(a); + if ((a % 16) == 0) + { + Serial.println(); + Serial.print(F("0x")); + if (a < 0x10) + { + Serial.print('0'); + } + Serial.print(a, HEX); + Serial.print(F(": ")); + } + Serial.print(F("0x")); + if (value < 0x10) + Serial.print('0'); + Serial.print(value, HEX); + Serial.print(F(" ")); + } + Serial.println(); +} + + +void fillMemory(uint16_t startaddr, uint16_t endaddr, uint8_t lval) +{ + uint16_t i; + for (i = startaddr; i <= endaddr; i++) + { + writeMemoryUint8(i, lval); + } +} + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + + + diff --git a/lib/SX12XX-LoRa/src/LICENSE.txt b/lib/SX12XX-LoRa/src/LICENSE.txt new file mode 100644 index 0000000..d6dfb1b --- /dev/null +++ b/lib/SX12XX-LoRa/src/LICENSE.txt @@ -0,0 +1,25 @@ +--- Revised BSD License --- +Copyright (c) 2013, SEMTECH S.A. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Semtech corporation nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/lib/SX12XX-LoRa/src/ProgramLT_Definitions.h b/lib/SX12XX-LoRa/src/ProgramLT_Definitions.h new file mode 100644 index 0000000..5284f53 --- /dev/null +++ b/lib/SX12XX-LoRa/src/ProgramLT_Definitions.h @@ -0,0 +1,123 @@ +/******************************************************************************************************* + 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. +*******************************************************************************************************/ + + +/* +****************************************************************************************************** + Definitions for packet types +****************************************************************************************************** +*/ + +const char Sensor1 = '!'; //Sensor packet1 +const char HABPacket = '$'; //HAB style CSV ASCII packet +const char Broadcast = '*'; //Broadcast destination address +const char RControl1 = 'D'; //Remote Control packet +const char TestMode1 = '1'; //used to switch to Testmode1 settings +const char TestPacket = 'T'; //Test packet +const char TXError = 't'; //Transmitter error +const char PowerUp = 'P'; //sent on tracker start +const char LocationPacket = 'L'; //LT library tracker location packet in binary format +const char LocationBinaryPacket = 's'; //short location packet in binary format +const char NoFix = 'F'; //GPS no fix +const char NoGPS = 'G'; //No GPS found, or GPS error. +const char ACK = 'A'; //Acknowledge +const char NACK = 'N'; //Not Acknowledge, error +const char AFC = 'a'; //Packet sent for AFC purposes + +const uint8_t Reliable = 0x80; //this packet type indicates reliable data packet +const uint8_t ReliableACK = 0x81; //this packet type indicates reliable data packet acknowledge +const uint8_t FTtype = 0xF0; //FTsubtype file transfer type +const uint8_t FTstart = 0xF1; //FTsubtype file transfer start information, filename etc +const uint8_t FTsegment = 0xF2; //FTsubtype packet contains a numbered segment +const uint8_t FTACK = 0xF3; //FTsubtype ACK response for file transfers +const uint8_t FTNACK = 0xF4; //FTsubtype NACK response for file transfers +const uint8_t FTclose = 0xF5; //FTsubtype request from TX to close file, transfer finished +const uint8_t FTrestart = 0xF6; //FTsubtype request from RX to restart current file transfer + +//GPS Tracker Status byte settings +const uint8_t GPSFix = 0; //flag bit set when GPS has a current fix +const uint8_t GPSConfigError = 1; //flag bit set to indicate cannot configure GPS or wrong configuration +const uint8_t CameraError = 2; //flag bit indicating a camera device error +const uint8_t GPSError = 3; //flag bit set to indicate GPS error, response timeout for instance +const uint8_t LORAError = 4; //flag bit indication a lora device error +const uint8_t SDError = 5; //flag bit indication a SD card device error +const uint8_t TrackerLost = 6; //flag bit indication that tracker in lost mode +const uint8_t NoGPSTestMode = 7; //flag bit number to indicate tracker in no GPS test mode + +/********************************************************************* + START Stored Program data +**********************************************************************/ +const uint16_t addr_StartMemory = 0x00; //the start of memory +const uint16_t addr_StartProgramData = 0x100; //the start of program data in memory +const uint16_t addr_ResetCount = 0x100; //unsigned long int 4 bytes +const uint16_t addr_SequenceNum = 0x104; //unsigned long int 4 bytes +const uint16_t addr_TXErrors = 0x108; //uint16_t 2 bytes +const uint16_t addr_EndMemory = 0x3FF; + + +/********************************************************************* + START GPS CoordinateData +**********************************************************************/ +//for storing last received GPS co-ordinates from local and remote tracker GPS +const uint16_t addr_StartCoordinateData = 0x300; +const uint16_t addr_RemoteLat = 0x300; //float 4 bytes +const uint16_t addr_RemoteLon = 0x304; //float 4 bytes +const uint16_t addr_RemoteAlt = 0x308; //uint16_t 2 bytes +const uint16_t addr_RemoteHour = 0x30C; //byte 1 byte; Note times for last tracker co-ordinates come from local GPS time +const uint16_t addr_RemoteMin = 0x310; //byte 1 byte +const uint16_t addr_RemoteSec = 0x311; //byte 1 byte +const uint16_t addr_RemoteDay = 0x312; //byte 1 byte +const uint16_t addr_RemoteMonth = 0x313; //byte 1 byte +const uint16_t addr_RemoteYear = 0x314; //byte 1 byte +const uint16_t addr_LocalLat = 0x318; //float 4 bytes +const uint16_t addr_LocalLon = 0x31C; //float 4 bytes +const uint16_t addr_LocalAlt = 0x320; //uint16_t 2 bytes +const uint16_t addr_LocalHour = 0x322; //byte 1 byte +const uint16_t addr_LocalMin = 0x323; //byte 1 byte +const uint16_t addr_LocalSec = 0x324; //byte 1 byte +const uint16_t addr_LocalDay = 0x325; //byte 1 byte +const uint16_t addr_LocalMonth = 0x326; //byte 1 byte +const uint16_t addr_LocalYear = 0x327; //byte 1 byte +const uint16_t addr_EndCoordinateData = 0x327; + +const uint16_t addr_RemotelocationCRC = 0x340; //the 16 bit CRC of the last tracker location data is saved here +const uint16_t addr_LocallocationCRC = 0x342; //the 16 bit CRC of the last local location data is saved here + +const uint16_t addr_TestLocation_page3 = 0x3FF; //used as a location for read\write tests + +/********************************************************************* + END GPS CoordinateData +**********************************************************************/ + + +/* +****************************************************************************************************** + Bit numbers for current_config byte settings end definitions for packet types +****************************************************************************************************** +*/ + +//Bit numbers for current_config byte settings in transmitter (addr_Default_config1) +const uint8_t SearchEnable = 0; //bit num to set in config byte to enable search mode packet +const uint8_t TXEnable = 1; //bit num to set in config byte to enable transmissions +const uint8_t FSKRTTYEnable = 2; //bit num to set in config byte to enable FSK RTTY +const uint8_t DozeEnable = 4; //bit num to set in config byte to put tracker in Doze mode +const uint8_t GPSHotFix = 7; //bit when set enables GPS Hot Fix mode. + + +/* +****************************************************************************************************** + Values for reliable transmit\receive errors +****************************************************************************************************** +*/ +const uint16_t packettypeErr = 0x01; +const uint16_t destErr = 0x02; +const uint16_t sourceErr = 0x04; +const uint16_t timeoutErr = 0x08; +const uint16_t IDErr = 0x10; +const uint16_t crcErr = 0x20; +const uint16_t seqErr = 0x40; +const uint16_t packetErr = 0x80; \ No newline at end of file diff --git a/lib/SX12XX-LoRa/src/QuectelSerialGPS.h b/lib/SX12XX-LoRa/src/QuectelSerialGPS.h new file mode 100644 index 0000000..79ac20c --- /dev/null +++ b/lib/SX12XX-LoRa/src/QuectelSerialGPS.h @@ -0,0 +1,608 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 12/05/20 +*/ + + +/******************************************************************************************************* + Program Operation - This is a library file for the Quectel L70,L76,L80 and L86 GPSs + + The routines assume that the GPS has been setup on GPSserial which could be either software serial or + hardware serial. This library file has optimisations that the use of SoftwareSerial requires. + + The calling program should include a define for the GPS baud rate as follows + + #define GPSBaud 9600 + + If this define is missing then 9600 baud is assumed +*******************************************************************************************************/ + +const PROGMEM uint8_t SetBalloonMode[] = {"$PMTK886,3*2B"}; //response should be $PMTK001,886,3*36 +const PROGMEM uint8_t ClearConfig[] = {"$PMTK104*37"}; //no response +const PROGMEM uint8_t PMTK_ACK[] = {"$PMTK001,xxx,?"}; //? = 0 = invalid, 1 = unsupported, 2 = valid failed, 3 = valids succeeded +const PROGMEM uint8_t SoftwareBackup[] = {"$PMTK161,0*28"}; //response should be $PMTK001,161,3*36 +const PROGMEM uint8_t HotStart[] = {"$PMTK101*32"}; +const PROGMEM uint8_t GGARMCOnly[] = {"$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"}; + +uint8_t GPS_GetByte(); +void GPS_OutputOn(); +void GPS_OutputOff(); +void GPS_PowerOn(int8_t pin, uint8_t state); +void GPS_PowerOff(int8_t pin, uint8_t state); +bool GPS_Setup(); +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts); +bool GPS_WaitAck(uint32_t waitms, uint8_t length); +bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS); +uint8_t GPS_GetNextChar(uint32_t waitmS); +bool GPS_CheckAck(); +bool GPS_SetBalloonMode(); +bool GPS_CheckBalloonMode(); +bool GPS_ClearConfig(); +bool GPS_SetCyclicMode(); +bool GPS_SoftwareBackup(); +bool GPS_HotStart(); +bool GPS_PollNavigation(); +bool GPS_SaveConfig(); + +bool GPS_GLONASSOff(); //not currently implemented on Quectel GPS +bool GPS_GPGLLOff(); //not currently implemented on Quectel GPS +bool GPS_GPGLSOff(); //not currently implemented on Quectel GPS +bool GPS_GPGSAOff(); //not currently implemented on Quectel GPS +bool GPS_GPGSVOff(); //not currently implemented on Quectel GPS +bool GPS_GNSSmode(); //not currently implemented on Quectel GPS +bool GPS_GGARMCOnly(); + + +const uint32_t GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const uint8_t GPS_attempts = 10; //number of times the sending of GPS config will be attempted. +const uint8_t GPS_Reply_Size = 20; //size of GPS reply buffer +const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent +uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands + + +#define QUECTELINUSE //so complier can know which GPS library is used //so complier can know which GPS library is used +//#define GPSDebug + + +#ifndef GPSBaud +#define GPSBaud 9600 +#endif + + +void GPS_OutputOn() +{ +#ifdef GPSDebug + Serial.print(F("GPS_OutputOn() ")); +#endif + //turns on serial output from GPS + GPSserial.begin(GPSBaud); + while (GPSserial.available()) GPSserial.read(); //make sure input buffer is empty +} + + +void GPS_OutputOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_OutputOff() ")); +#endif + //turns off serial output from GPS + GPSserial.end(); +} + + +void GPS_PowerOn(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOn() ")); +#endif + + if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +void GPS_PowerOff(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOff() ")); +#endif + +if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +bool GPS_Setup() +{ +#ifdef GPSDebug + Serial.print(F("GPS_Setup() ")); +#endif + + if (!GPS_SetBalloonMode()) + { + return false; + } + + if (!GPS_GGARMCOnly()) + { + return false; + } + + return true; +} + + +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts) +{ +#ifdef GPSDebug + Serial.print(F("GPS_SendConfig() ")); +#endif + + uint8_t byteread, index; + uint8_t config_attempts = attempts; + + memset(GPS_Reply, 0, sizeof(GPS_Reply)); //clear the reply buffer + + Serial.flush(); //ensure there are no pending interrupts from serial monitor printing + + do + { + if (config_attempts == 0) + { + return false; + } + + GPS_OutputOff(); + + Serial.print(F("GPSSend ")); + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + Serial.write(byteread); + } + + Serial.flush(); //make sure serial out buffer is empty + + GPS_OutputOn(); + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + GPSserial.write(byteread); + } + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start, in case config command retried + + GPSserial.write(13); + GPSserial.write(10); + + if (replylength == 0) + { + break; + } + GPSserial.flush(); //make sure all of config command has been sent + config_attempts--; + } + while (!GPS_WaitAck(GPS_WaitAck_mS, replylength)); + + delay(100); //GPS can sometimes be a bit slow getting ready for next config + return true; +} + + +bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS) +{ + uint8_t GPSchar; + uint32_t startmS; + + startmS = millis(); + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + if (GPSchar == waitforchar) + { + GPS_Reply[0] = GPSchar; + return true; + } + } + } + while ((uint32_t) (millis() - startmS) < waitmS); //use the timeout to ensure a lack of GPS does not cause the program to hang + return false; +} + + +uint8_t GPS_GetNextChar(uint32_t waitmS) +{ + uint8_t GPSchar; + uint32_t startmS; + + startmS = millis(); + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + GPS_Reply[1] = GPSchar; + return GPSchar; + } + } + while ((uint32_t) (millis() - startmS) < waitmS); //use the timeout to ensure a lack of GPS does not cause the program to hang + return '*'; +} + + +bool GPS_WaitAck(uint32_t waitmS, uint8_t length) +{ +#ifdef GPSDebug + Serial.print(F("GPS_WaitAck() ")); + Serial.print(F(" Reply length ")); + Serial.print(length); + Serial.print(F(" ")); +#endif + + uint8_t GPSchar; + uint32_t startmS; + + startmS = millis(); + uint8_t ptr = 0; //used as pointer to store GPS reply + bool found; + + Serial.println(); + Serial.print(F("Received ")); + Serial.flush(); + + found = false; + + do + { + if (!GPS_WaitChar('$', waitmS)) + { + Serial.print(F("Timeout Error")); + found = false; + break; + } + + Serial.print(F("$")); + + GPSchar = GPS_GetNextChar(waitmS); + Serial.write(GPSchar); + + if (GPSchar == 'P') + { + found = true; + break; + } + else + { + Serial.print(F(" ")); + found = false; + } + } + while ((uint32_t) (millis() - startmS) < waitmS); + + if (found) + { + ptr = 2; + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + GPS_Reply[ptr++] = GPSchar; + } + } + while (((uint32_t) (millis() - startmS) < waitmS) && (ptr < length)); //use the timeout to ensure a lack of GPS does not cause the program to hang + } + + GPS_OutputOff(); + + + for (ptr = 2; ptr < length; ptr++) + { + GPSchar = GPS_Reply[ptr]; + Serial.write(GPSchar); + } + + Serial.println(); + + if (GPS_CheckAck()) + { + return true; + } + + return false; +} + + +bool GPS_CheckBalloonMode() +{ + //Reply to set balloon mode ought to be $PMTK886,3*2B, the 3 is for balloon mode + +#ifdef GPSDebug + Serial.print(F("GPS_CheckBalloonMode() ")); +#endif + + if (GPS_SetBalloonMode()) + { + return true; + } + return false; +} + + +bool GPS_PollNavigation() +{ +#ifdef GPSDebug + Serial.print(F("GPS_PollNavigation() ")); +#endif +//empty function for compatibility reasons with other GPS libraries +return true; +} + + +bool GPS_SaveConfig() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SaveConfig() ")); +#endif +//empty function for compatibility reasons with other GPS libraries +return true; +} + + +bool GPS_CheckAck() +{ + +#ifdef GPSDebug + Serial.print(F("GPS_CheckAck() ")); +#endif + + uint8_t response[] = {"$PMTK001,xxx,?"}; + uint8_t index; + + for (index = 2; index <= 7; index++) //check up to the eighth ([7]) character, which is the ',' + { + if ( GPS_Reply[index] != response[index]) + { + return false; + } + } + + if ((index == 8) && (GPS_Reply[13] == '3') ) //if we got to index 8 there was a match for $PMTK001, so check reply type + { + return true; + } + + Serial.print(index); + Serial.print(F(" ")); + return false; +} + + +/********************************************************************* + // GPS configuration commands +*********************************************************************/ + + +bool GPS_SetBalloonMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetBalloonMode() ")); +#endif + + Serial.println(F("SetBalloonMode ")); + size_t SIZE = sizeof(SetBalloonMode); + + if (GPS_SendConfig(SetBalloonMode, SIZE, 17, GPS_attempts)) + { + Serial.println(F("OK")); + Serial.println(); + return true; + } + Serial.println(F("Fail")); + Serial.println(); + return false; +} + + +bool GPS_GGARMCOnly() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GGARMCOnly() ")); +#endif + + Serial.println(F("Set GGA and RMC only ")); + size_t SIZE = sizeof(GGARMCOnly); + + if (GPS_SendConfig(GGARMCOnly, SIZE, 17, GPS_attempts)) + { + Serial.println(F("OK")); + Serial.println(); + return true; + } + Serial.println(F("Fail")); + Serial.println(); + return false; +} + + + +bool GPS_ClearConfig() + { + Serial.println(F("ClearConfig()")); + size_t SIZE = sizeof(ClearConfig); + GPS_SendConfig(ClearConfig, SIZE, 0, GPS_attempts); //full cold start, no response is given, so replylength = 0 + + #ifdef GPSDebug + Serial.print(F("No Response given for full cold start")); + #endif + + Serial.println(); + Serial.println(F("Wait clear")); + delay(GPS_Clear_DelaymS); + return true; + } + + +bool GPS_SetCyclicMode() + { + #ifdef GPSDebug + Serial.print(F("GPS_SetCyclicMode() ")); + #endif + //no clyclic mode config for Quectel + return true; + + } + + + bool GPS_SoftwareBackup() + { + #ifdef GPSDebug + Serial.print(F("GPS_SoftwareBackup() ")); + #endif + + size_t SIZE = sizeof(SoftwareBackup); + Serial.println(F("SoftwareBackup")); + + if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_HotStart() + { + #ifdef GPSDebug + Serial.print(F("GPS_HotStart() ")); + #endif + + size_t SIZE = sizeof(HotStart); + Serial.println(F("HotStart")); + + if (GPS_SendConfig(HotStart, SIZE, 0, GPS_attempts)) //reply is $PMTK010,002*2D, so not receognised by check ack + { + return true; + } + + return false; +} + + +bool GPS_GPGLLOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLLOff() ")); +#endif + + //setup to be added later + //function included for compatibility with other GPS library + return true; +} + + +bool GPS_GPGLSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLSOff() ")); +#endif + + //setup to be added later + //function included for compatibility with other GPS library + return true; +} + + +bool GPS_GPGSAOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSAOff() ")); +#endif + + //setup to be added later + //function included for compatibility with other GPS library + return true; +} + + +bool GPS_GPGSVOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSVOff() ")); +#endif + + //setup to be added later + //function included for compatibility with other GPS library + return true; +} + +bool GPS_GLONASSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GLONASSOff() ")); +#endif + + //setup to be added later + //function included for compatibility with other GPS library + return true; +} + + +bool GPS_GNSSmode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GNSSmode() ")); +#endif + + //setup to be added later + //function included for compatibility with other GPS library + return true; +} + + +uint8_t GPS_GetByte() //get a byte for GPS +{ + if (GPSserial.available() == 0) + { + return 0xFF; //for compatibility with I2C reading of GPS + } + else + { + return GPSserial.read(); + } +} + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/lib/SX12XX-LoRa/src/Quectel_HWSerialGPS.h b/lib/SX12XX-LoRa/src/Quectel_HWSerialGPS.h new file mode 100644 index 0000000..344efef --- /dev/null +++ b/lib/SX12XX-LoRa/src/Quectel_HWSerialGPS.h @@ -0,0 +1,474 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 12/05/20 +*/ + + +/******************************************************************************************************* + Program Operation - This is a library file for the Quectel L70,L76,L80 and L86 GPSs + + The routines assume that the GPS has been setup on GPSserial which could be either software serial or + hardware serial. The calling program should include a define for the GPS baud rate as follows + + #define GPSBaud 9600 + + If this define is missing then 9600 baud is assumed +*******************************************************************************************************/ + +const PROGMEM uint8_t SetBalloonMode[] = {"$PMTK886,3*2B"}; //response should be $PMTK001,886,3*36 +const PROGMEM uint8_t ClearConfig[] = {"$PMTK104*37"}; //no response +const PROGMEM uint8_t PMTK_ACK[] = {"$PMTK001,xxx,?"}; //? = 0 = invalid, 1 = unsupported, 2 = valid failed, 3 = valids succeeded +const PROGMEM uint8_t SoftwareBackup[] = {"$PMTK161,0*28"}; //response should be $PMTK001,161,3*36 +const PROGMEM uint8_t HotStart[] = {"$PMTK101*32"}; + +uint8_t GPS_GetByte(); +void GPS_OutputOn(); +void GPS_OutputOff(); +void GPS_PowerOn(int8_t pin, uint8_t state); +void GPS_PowerOff(int8_t pin, uint8_t state); +bool GPS_Setup(); +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts); +bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS); +uint8_t GPS_GetNextChar(uint32_t waitmS); +bool GPS_WaitAck(uint32_t waitms, uint8_t length); +bool GPS_CheckConfiguration(); +bool GPS_CheckAck(); +bool GPS_SetBalloonMode(); +bool GPS_ClearConfig(); +bool GPS_SetCyclicMode(); +bool GPS_SoftwareBackup(); +bool GPS_HotStart(); + + +const uint32_t GPS_WaitAck_mS = 2000; //number of mS to wait for an ACK response from GPS +const uint8_t GPS_attempts = 5; //number of times the sending of GPS config will be attempted. +const uint8_t GPS_Reply_Size = 20; //size of GPS reply buffer +const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent + +uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands + +#define QUECTELINUSE //so complier can know which GPS library is used //so complier can know which GPS library is used +//#define GPSDebug + +#ifndef GPSConfigSerial // if GPSDebugSerial is not defined set to Serial as default + #define GPSConfigSerial Serial +#endif + +#ifndef GPSDebugSerial // if GPSDebugSerial is not defined set to Serial as default + #define GPSDebugSerial Serial +#endif + +#ifndef GPSBaud +#define GPSBaud 9600 +#endif + +void GPS_OutputOn() +{ +#ifdef GPSDebug + Serial.print(F("GPS_OutputOn() ")); +#endif + //turns on serial output from GPS + GPSserial.begin(GPSBaud); +} + + +void GPS_OutputOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_OutputOff() ")); +#endif + //turns off serial output from GPS + GPSserial.end(); +} + + +void GPS_PowerOn(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOn() ")); +#endif + + if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +void GPS_PowerOff(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOff() ")); +#endif + +if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +bool GPS_Setup() +{ +#ifdef GPSDebug + Serial.print(F("GPS_Setup() ")); +#endif + + if (!GPS_SetBalloonMode()) + { + return false; + } + + return true; +} + + +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts) +{ +#ifdef GPSDebug + Serial.print(F("GPS_SendConfig() ")); +#endif + + uint8_t byteread, index; + uint8_t config_attempts = attempts; + + memset(GPS_Reply, 0, sizeof(GPS_Reply)); //clear the reply buffer + + Serial.flush(); //ensure there are no pending interrupts from serial monitor printing + + do + { + if (config_attempts == 0) + { + return false; + } + + Serial.print(F("GPSSend ")); + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + Serial.write(byteread); + } + + Serial.flush(); //make sure serial out buffer is empty + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + GPSserial.write(byteread); + } + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start, in case config command retried + + + GPSserial.write(13); + GPSserial.write(10); + + if (replylength == 0) + { + break; + } + + config_attempts--; + } + while (!GPS_WaitAck(GPS_WaitAck_mS, replylength)); + + delay(100); //GPS can sometimes be a bit slow getting ready for next config + return true; +} + + +bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS) +{ + uint8_t GPSchar; + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + if (GPSchar == waitforchar) + { + GPS_Reply[0] = GPSchar; + return true; + } + } + } + while ((millis() < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang + return false; +} + + +uint8_t GPS_GetNextChar(uint32_t waitmS) +{ + uint8_t GPSchar; + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + GPS_Reply[1] = GPSchar; + return GPSchar; + } + } + while ((millis() < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang + return '*'; +} + + +bool GPS_WaitAck(uint32_t waitmS, uint8_t length) +{ +#ifdef GPSDebug + Serial.print(F("GPS_WaitAck() ")); + Serial.print(F(" Reply length ")); + Serial.print(length); + Serial.print(F(" ")); +#endif + + uint8_t GPSchar; + + uint32_t endmS; + endmS = millis() + waitmS; + uint8_t ptr = 0; //used as pointer to store GPS reply + bool found; + + Serial.println(); + Serial.print(F("Received ")); + Serial.flush(); + + endmS = millis() + GPS_WaitAck_mS; + + found = false; + + do + { + if (!GPS_WaitChar('$', endmS)) + { + Serial.print(F("Timeout Error")); + found = false; + break; + } + + Serial.print(F("$")); + + GPSchar = GPS_GetNextChar(endmS); + Serial.write(GPSchar); + + if (GPSchar == 'P') + { + found = true; + break; + } + else + { + Serial.print(F(" ")); + found = false; + } + } + while (millis() <= endmS); + + if (found) + { + ptr = 2; + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + GPS_Reply[ptr++] = GPSchar; + } + } + while ((millis() < endmS) && (ptr < length)); //use the timeout to ensure a lack of GPS does not cause the program to hang + } + + + for (ptr = 2; ptr < length; ptr++) + { + GPSchar = GPS_Reply[ptr]; + Serial.write(GPSchar); + } + + Serial.println(); + + if (GPS_CheckAck()) + { + return true; + } + + return false; +} + + +bool GPS_CheckConfiguration() +{ + //Reply to set balloon mode ought to be $PMTK886,3*2B, the 3 is for balloon mode + +#ifdef GPSDebug + Serial.print(F("GPS_CheckConfiguration() ")); +#endif + + if (GPS_SetBalloonMode()) + { + return true; + } + return false; +} + + + +bool GPS_CheckAck() +{ + +#ifdef GPSDebug + Serial.print(F("GPS_CheckAck() ")); +#endif + + uint8_t response[] = {"$PMTK001,xxx,?"}; + uint8_t index; + + for (index = 2; index <= 7; index++) //check up to the eighth ([7]) character, which is the ',' + { + if ( GPS_Reply[index] != response[index]) + { + return false; + } + } + + if ((index == 8) && (GPS_Reply[13] == '3') ) //if we got to index 8 there was a match for $PMTK001, so check reply type + { + return true; + } + + Serial.print(index); + Serial.print(F(" ")); + return false; +} + + +/********************************************************************* + // GPS configuration commands +*********************************************************************/ + + +bool GPS_SetBalloonMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetBalloonMode() ")); +#endif + + Serial.println(F("SetBalloonMode ")); + size_t SIZE = sizeof(SetBalloonMode); + + if (GPS_SendConfig(SetBalloonMode, SIZE, 17, GPS_attempts)) + { + Serial.println(F("OK")); + Serial.println(); + return true; + } + Serial.println(F("Fail")); + Serial.println(); + return false; +} + + +bool GPS_ClearConfig() + { + Serial.println(F("ClearConfig()")); + size_t SIZE = sizeof(ClearConfig); + GPS_SendConfig(ClearConfig, SIZE, 0, GPS_attempts); //full cold start, no response is given, so replylength = 0 + + #ifdef GPSDebug + Serial.print(F("No Response given for full cold start")); + #endif + + Serial.println(); + Serial.println(F("Wait clear")); + delay(GPS_Clear_DelaymS); + return true; + } + + +bool GPS_SetCyclicMode() + { + #ifdef GPSDebug + Serial.print(F("GPS_SetCyclicMode() ")); + #endif + //no clyclic mode config for Quectel + return true; + + } + + + bool GPS_SoftwareBackup() + { + #ifdef GPSDebug + Serial.print(F("GPS_SoftwareBackup() ")); + #endif + + size_t SIZE = sizeof(SoftwareBackup); + + if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_HotStart() + { + #ifdef GPSDebug + Serial.print(F("GPS_HotStart() ")); + #endif + + size_t SIZE = sizeof(HotStart); + Serial.println(F("HotStart")); + + if (GPS_SendConfig(HotStart, SIZE, 0, GPS_attempts)) //reply is $PMTK010,002*2D, so not receognised by check ack + { + return true; + } + + return false; +} + + +uint8_t GPS_GetByte() //get a byte for GPS +{ + if (GPSserial.available() == 0) + { + return 0xFF; //for compatibility with I2C reading of GPS + } + else + { + return GPSserial.read(); + } +} + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/lib/SX12XX-LoRa/src/SX126XLT.cpp b/lib/SX12XX-LoRa/src/SX126XLT.cpp new file mode 100644 index 0000000..8940294 --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX126XLT.cpp @@ -0,0 +1,3494 @@ +/* + Copyright 2019 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + 17/12/19 +*/ + +/* +Parts of code Copyright (c) 2013, SEMTECH S.A. +See LICENSE.TXT file included in the library +*/ + + +#include +#include + +#define LTUNUSED(v) (void) (v) //add LTUNUSED(variable); to avoid compiler warnings +#define USE_SPI_TRANSACTION + +//#define DEBUGBUSY //comment out if you do not want a busy timeout message +//#define SX126XDEBUG //enable debug messages +//#define SX126XDEBUG3 //enable debug messages +//#define SX126XDEBUGPINS //enable pin allocation debug messages +//#define DEBUGFSKRTTY //enable for FSKRTTY debugging + +/* +**************************************************************************** + To Do: + + +**************************************************************************** +*/ + +SX126XLT::SX126XLT() +{ + //Anything you need when instantiating your object goes here +} + +/* Formats for :begin + original > 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); +1 All pins > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, int8_t pinSW, uint8_t device) +2 NiceRF > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device) +3 Dorji > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinSW, uint8_t device) +4 Ebyte > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device) +*/ + + +bool SX126XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, int8_t pinSW, uint8_t device) +{ + + //format 1 pins, assign all available pins + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = pinDIO2; + _DIO3 = pinDIO3; + _RXEN = pinRXEN; + _TXEN = pinTXEN; + _SW = pinSW; + _Device = device; + + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + + +#ifdef SX126XDEBUGPINS + Serial.println(F("format 1 begin()")); + Serial.println(F("SX126XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TXEN ")); + Serial.println(_TXEN); + Serial.print(F("SW ")); + Serial.println(_SW); +#endif + + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + if (_DIO2 >= 0) + { + pinMode( _DIO2, INPUT); + } + + if (_DIO3 >= 0) + { + pinMode( _DIO3, INPUT); + } + + + if ((_RXEN >= 0) && (_TXEN >= 0)) + { + #ifdef SX126XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching enabled")); + #endif + pinMode(_RXEN, OUTPUT); + pinMode(_TXEN, OUTPUT); + _rxtxpinmode = true; + } + else + { + #ifdef SX126XDEBUGPINS + Serial.println(F("RX_EN & TX_EN not used")); + #endif + _rxtxpinmode = false; + } + + + if (_SW >= 0) + { + pinMode( _SW, OUTPUT); //Dorji devices have an RW pin that needs to be set high to power antenna switch + digitalWrite(_SW, HIGH); + } + + resetDevice(); + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool SX126XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device) +{ + + //format 2 pins for NiceRF, NSS, NRESET, RFBUSY, DIO1 + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = -1; + _DIO3 = -1; + _RXEN = -1; + _TXEN = -1; + _SW = -1; + _Device = device; + + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + + +#ifdef SX126XDEBUGPINS + Serial.println(F("format 2 NiceRF begin()")); + Serial.println(F("SX126XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TX_EN ")); + Serial.println(_TXEN); + Serial.print(F("SW ")); + Serial.println(_SW); +#endif + + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + + #ifdef SX126XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching disabled")); + #endif + + _rxtxpinmode = false; + + resetDevice(); + + if (checkDevice()) + { + return true; + } + + return false; +} + + + +bool SX126XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinSW, uint8_t device) +{ + + //format 3 pins for Dorji, NSS, NRESET, RFBUSY, DIO1, SW + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = -1; + _DIO3 = -1; + _RXEN = -1; + _TXEN = -1; + _SW = pinSW; + _Device = device; + + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + + +#ifdef SX126XDEBUGPINS + Serial.println(F("format 3 Dorji begin()")); + Serial.println(F("SX126XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TX_EN ")); + Serial.println(_TXEN); + Serial.print(F("SW ")); + Serial.println(_SW); +#endif + + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + #ifdef SX126XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching disabled")); + #endif + + _rxtxpinmode = false; + + + if (_SW >= 0) + { + pinMode( _SW, OUTPUT); //Dorji devices have an RW pin that needs to be set high to power antenna switch + digitalWrite(_SW, HIGH); + } + + resetDevice(); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool SX126XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device) +{ + + //format 4 pins for Ebyte (not tested) , NSS, NRESET, RFBUSY, DIO1, RXEN, TXEN + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = -1; + _DIO3 = -1; + _RXEN = pinRXEN; + _TXEN = pinTXEN; + _SW = -1; + _Device = device; + + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + + +#ifdef SX126XDEBUGPINS + Serial.println(F("format 4 Ebyte begin()")); + Serial.println(F("SX126XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TX_EN ")); + Serial.println(_TXEN); + Serial.print(F("SW ")); + Serial.println(_SW); +#endif + + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + if ((_RXEN >= 0) && (_TXEN >= 0)) + { + #ifdef SX126XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching enabled")); + #endif + pinMode(_RXEN, OUTPUT); + pinMode(_TXEN, OUTPUT); + _rxtxpinmode = true; + } + else + { + #ifdef SX126XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching disabled")); + #endif + _rxtxpinmode = false; + } + + + if (_SW >= 0) + { + pinMode( _SW, OUTPUT); //Dorji devices have an RW pin that needs to be set high to power antenna switch + digitalWrite(_SW, HIGH); + } + + resetDevice(); + if (checkDevice()) + { + return true; + } + + return false; +} + + +void SX126XLT::checkBusy() +{ +#ifdef SX126XDEBUG + //Serial.println(F("checkBusy()")); +#endif + + uint8_t busy_timeout_cnt; + busy_timeout_cnt = 0; + + while (digitalRead(_RFBUSY)) + { + delay(1); + busy_timeout_cnt++; + + + //this function checks for a timeout on the busy pin + //if there is a timeout the device is set back to the saved settings + //the fuction is of limited benefit, since you cannot know at which stage of the + //operation the timeout occurs, so operation could resume + if (busy_timeout_cnt > 10) //wait 10mS for busy to complete + { + busy_timeout_cnt = 0; +#ifdef DEBUGBUSY + Serial.println(F("ERROR - Busy Timeout!")); +#endif + resetDevice(); //reset device + setMode(MODE_STDBY_RC); + config(); //re-run saved config + break; + } + } +} + + +void SX126XLT::writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size) +{ +#ifdef SX126XDEBUG + //Serial.println(F("writeCommand()")); +#endif + + uint8_t index; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(Opcode); + + for (index = 0; index < size; index++) + { + SPI.transfer(buffer[index]); + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + if (Opcode != RADIO_SET_SLEEP) + { + checkBusy(); + } +} + + +void SX126XLT::readCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size) +{ +#ifdef SX126XDEBUG + //Serial.println(F("readCommand()")); +#endif + + uint8_t i; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(Opcode); + SPI.transfer(0xFF); + + for ( i = 0; i < size; i++ ) + { + + *(buffer + i) = SPI.transfer(0xFF); + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +void SX126XLT::writeRegisters(uint16_t address, uint8_t *buffer, uint16_t size) +{ +#ifdef SX126XDEBUG + //Serial.println(F("writeRegisters()")); +#endif + uint8_t addr_l, addr_h; + uint8_t i; + + addr_l = address & 0xff; + addr_h = address >> 8; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + 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); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif +} + + +void SX126XLT::writeRegister(uint16_t address, uint8_t value) +{ +#ifdef SX126XDEBUG + //Serial.println(F("writeRegisters()")); +#endif + + writeRegisters( address, &value, 1 ); +} + +void SX126XLT::readRegisters(uint16_t address, uint8_t *buffer, uint16_t size) +{ +#ifdef SX126XDEBUG + //Serial.println(F("readRegisters()")); +#endif + + uint16_t index; + uint8_t addr_l, addr_h; + + addr_h = address >> 8; + addr_l = address & 0x00FF; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + 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); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +uint8_t SX126XLT::readRegister(uint16_t address) +{ +#ifdef SX126XDEBUG + //Serial.println(F("readRegister()")); +#endif + + uint8_t data; + + readRegisters(address, &data, 1); + return data; +} + +void SX126XLT::resetDevice() +{ +#ifdef SX126XDEBUG + Serial.println(F("resetDevice()")); +#endif + + delay(10); + digitalWrite(_NRESET, LOW); + delay(2); + digitalWrite(_NRESET, HIGH); + delay(25); + checkBusy(); +} + + + +bool SX126XLT::checkDevice() +{ + //check there is a device out there, writes a register and reads back +#ifdef SX126XDEBUG + Serial.println(F("checkDevice()")); +#endif + + 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 SX126XLT::setupLoRa(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4) +{ + //order of passed parameters is, frequency, offset, spreadingfactor, bandwidth, coderate, optimisation + +#ifdef SX126XDEBUG + Serial.println(F("setupLoRa()")); +#endif + setMode(MODE_STDBY_RC); + setRegulatorMode(USE_DCDC); + setPaConfig(0x04, PAAUTO, _Device); //use _Device, saved by begin. + setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V); + calibrateDevice(ALLDevices); //is required after setting TCXO + calibrateImage(frequency); + setDIO2AsRfSwitchCtrl(); + setPacketType(PACKET_TYPE_LORA); + setRfFrequency(frequency, offset); + setModulationParams(modParam1, modParam2, modParam3, modParam4); + setBufferBaseAddress(0, 0); + setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1 + setHighSensitivity(); //set for maximum gain + setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); +} + + +void SX126XLT::setMode(uint8_t modeconfig) +{ +#ifdef SX126XDEBUG + Serial.println(F("setMode()")); +#endif + + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_SET_STANDBY); + SPI.transfer(modeconfig); + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + _OperatingMode = modeconfig; +} + + +void SX126XLT::setRegulatorMode(uint8_t mode) +{ +#ifdef SX126XDEBUG + Serial.println(F("setRegulatorMode()")); +#endif + + savedRegulatorMode = mode; + + writeCommand(RADIO_SET_REGULATORMODE, &mode, 1); +} + + +void SX126XLT::setPaConfig(uint8_t dutycycle, uint8_t hpMax, uint8_t device) +{ +#ifdef SX126XDEBUG + Serial.println(F("setPaConfig()")); +#endif + + + uint8_t buffer[4]; + + if (hpMax == PAAUTO) + { + if (device == DEVICE_SX1261) + { + hpMax = 0x00; + } + if (device == DEVICE_SX1262) + { + hpMax = 0x07; + } + if (device == DEVICE_SX1268) + { + hpMax = 0x07; + } + } + + if (_Device == DEVICE_SX1261) + { + device = 1; + } + else + { + device = 0; + } + + buffer[0] = dutycycle; //paDutyCycle + buffer[1] = hpMax; //hpMax:0x00~0x07; 7 for =22dbm + buffer[2] = device; //deviceSel: 0 = SX1262; 1 = SX1261; 0 = SX1268; + buffer[3] = 0x01; //reserved, always 0x01 + + writeCommand(RADIO_SET_PACONFIG, buffer, 4); +} + + +void SX126XLT::setDIO3AsTCXOCtrl(uint8_t tcxoVoltage) +{ +#ifdef SX126XDEBUG + Serial.println(F("setDIO3AsTCXOCtrl()")); +#endif + + uint8_t buffer[4]; + + buffer[0] = tcxoVoltage; + buffer[1] = 0x00; + buffer[2] = 0x00; + buffer[3] = 0x64; + + writeCommand(RADIO_SET_TCXOMODE, buffer, 4); +} + + +void SX126XLT::calibrateDevice(uint8_t devices) +{ +#ifdef SX126XDEBUG + Serial.println(F("calibrateDevice()")); +#endif + + writeCommand(RADIO_CALIBRATE, &devices, 1); + delay(5); //calibration time for all devices is 3.5mS, SX126x + +} + + +void SX126XLT::calibrateImage(uint32_t freq) +{ +#ifdef SX126XDEBUG + Serial.println(F("calibrateImage()")); +#endif + + uint8_t calFreq[2]; + + if ( freq > 900000000 ) + { + calFreq[0] = 0xE1; + calFreq[1] = 0xE9; + } + else if ( freq > 850000000 ) + { + calFreq[0] = 0xD7; + calFreq[1] = 0xD8; + } + else if ( freq > 770000000 ) + { + calFreq[0] = 0xC1; + calFreq[1] = 0xC5; + } + else if ( freq > 460000000 ) + { + calFreq[0] = 0x75; + calFreq[1] = 0x81; + } + else if ( freq > 425000000 ) + { + calFreq[0] = 0x6B; + calFreq[1] = 0x6F; + } + writeCommand( RADIO_CALIBRATEIMAGE, calFreq, 2 ); +} + + +void SX126XLT::setDIO2AsRfSwitchCtrl() +{ +#ifdef SX126XDEBUG + Serial.println(F("setDIO2AsRfSwitchCtrl()")); +#endif + + uint8_t mode = 0x01; + + writeCommand(RADIO_SET_RFSWITCHMODE, &mode, 1); +} + + +void SX126XLT::setPacketType(uint8_t packettype ) +{ +#ifdef SX126XDEBUG + Serial.println(F("setPacketType()")); +#endif + savedPacketType = packettype; + + writeCommand(RADIO_SET_PACKETTYPE, &packettype, 1); +} + + +void SX126XLT::setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4) +{ + //order for LoRa is spreading factor, bandwidth, code rate, optimisation + +#ifdef SX126XDEBUG + Serial.println(F("setModulationParams()")); +#endif + uint8_t regvalue; + uint8_t buffer[4]; + + regvalue = readRegister(REG_TX_MODULATION); + + savedModParam1 = modParam1; + savedModParam2 = modParam2; + savedModParam3 = modParam3; + + if (modParam2 == LORA_BW_500) + { + writeRegister(REG_TX_MODULATION, (regvalue & 0xFB)); //if bandwidth is 500k set bit 2 to 0, see datasheet 15.1.1 + } + else + { + writeRegister(REG_TX_MODULATION, (regvalue | 0x04)); //if bandwidth is < 500k set bit 2 to 0 see datasheet 15.1.1 + } + + if (modParam4 == LDRO_AUTO) + { + modParam4 = returnOptimisation(modParam1, modParam2); //pass Spreading factor then bandwidth to optimisation calc + } + + savedModParam4 = modParam4; + + buffer[0] = modParam1; + buffer[1] = modParam2; + buffer[2] = modParam3; + buffer[3] = modParam4; + + writeCommand(RADIO_SET_MODULATIONPARAMS, buffer, 4); +} + + +uint8_t SX126XLT::returnOptimisation(uint8_t SpreadingFactor, uint8_t Bandwidth) +{ + //from the passed bandwidth (bandwidth) and spreading factor this routine + //calculates whether low data rate optimisation should be on or off + +#ifdef SX126XDEBUG + Serial.println(F("returnOptimisation()")); +#endif + + uint32_t tempBandwidth; + float symbolTime; + + tempBandwidth = returnBandwidth(Bandwidth); + + symbolTime = calcSymbolTime(tempBandwidth, SpreadingFactor); + + if (symbolTime > 16) + { + return LDRO_ON; + } + else + { + return LDRO_OFF; + } +} + + +uint32_t SX126XLT::returnBandwidth(uint8_t BWregvalue) +{ + +#ifdef SX126XDEBUG + Serial.println(F("returnBandwidth()")); +#endif + + switch (BWregvalue) + { + case 0: + return 7800; + + case 8: + return 10400; + + case 1: + return 15600; + + case 9: + return 20800; + + case 2: + return 31200; + + case 10: + return 41700; + + case 3: + return 62500; + + case 4: + return 125000; + + case 5: + return 250000; + + case 6: + return 500000; + + default: + break; + } + return 0xFFFF; //so that a bandwidth not set can be identified +} + + + +float SX126XLT::calcSymbolTime(float Bandwidth, uint8_t SpreadingFactor) +{ + //calculates symbol time from passed bandwidth (lbandwidth) and Spreading factor (lSF)and returns in mS + +#ifdef SX126XDEBUG + Serial.println(F("calcSymbolTime()")); +#endif + + float symbolTimemS; + symbolTimemS = (Bandwidth / pow(2, SpreadingFactor)); + symbolTimemS = (1000 / symbolTimemS); + return symbolTimemS; +} + + +void SX126XLT::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) +{ +#ifdef SX126XDEBUG + Serial.println(F("setBufferBaseAddress()")); +#endif + + uint8_t buffer[2]; + + buffer[0] = txBaseAddress; + buffer[1] = rxBaseAddress; + writeCommand(RADIO_SET_BUFFERBASEADDRESS, buffer, 2); +} + + +void SX126XLT::setPacketParams(uint16_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5) +{ + //order is preamble, header type, packet length, CRC, IQ + +#ifdef SX126XDEBUG + Serial.println(F("SetPacketParams()")); +#endif + + uint8_t preambleMSB, preambleLSB; + + preambleMSB = packetParam1 >> 8; + preambleLSB = packetParam1 & 0xFF; + + savedPacketParam1 = packetParam1; + savedPacketParam2 = packetParam2; + savedPacketParam3 = packetParam3; + savedPacketParam4 = packetParam4; + savedPacketParam5 = packetParam5; + + uint8_t buffer[9]; + buffer[0] = preambleMSB; + buffer[1] = preambleLSB; + buffer[2] = packetParam2; + buffer[3] = packetParam3; + buffer[4] = packetParam4; + buffer[5] = packetParam5; + buffer[6] = 0xFF; + buffer[7] = 0xFF; + buffer[8] = 0xFF; + writeCommand(RADIO_SET_PACKETPARAMS, buffer, 9); +} + + +void SX126XLT::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ) +{ +#ifdef SX126XDEBUG + Serial.println(F("setDioIrqParams()")); +#endif + + savedIrqMask = irqMask; + savedDio1Mask = dio1Mask; + savedDio2Mask = dio2Mask; + savedDio3Mask = dio3Mask; + + uint8_t buffer[8]; + + buffer[0] = (uint8_t) (irqMask >> 8); + buffer[1] = (uint8_t) (irqMask & 0xFF); + buffer[2] = (uint8_t) (dio1Mask >> 8); + buffer[3] = (uint8_t) (dio1Mask & 0xFF); + buffer[4] = (uint8_t) (dio2Mask >> 8); + buffer[5] = (uint8_t) (dio2Mask & 0xFF); + buffer[6] = (uint8_t) (dio3Mask >> 8); + buffer[7] = (uint8_t) (dio3Mask & 0xFF); + writeCommand(RADIO_CFG_DIOIRQ, buffer, 8); +} + + +void SX126XLT::setHighSensitivity() +{ + //set RX Boosted gain mode +#ifdef SX126XDEBUG + Serial.println(F("setHighSensitivity()")); +#endif + writeRegister( REG_RX_GAIN, BOOSTED_GAIN ); //max LNA gain, increase current by ~2mA for around ~3dB in sensivity +} + +void SX126XLT::setLowPowerRX() +{ + //set RX power saving mode +#ifdef SX126XDEBUG + Serial.println(F("setLowPowerRX()")); +#endif + + writeRegister( REG_RX_GAIN, POWER_SAVE_GAIN ); // min LNA gain, reduce current by 2mA for around 3dB loss in sensivity +} + + +void SX126XLT::setSyncWord(uint16_t syncword) +{ +#ifdef SX126XDEBUG + Serial.println(F("setSyncWord()")); +#endif + writeRegister( REG_LR_SYNCWORD, ( syncword >> 8 ) & 0xFF ); + writeRegister( REG_LR_SYNCWORD + 1, syncword & 0xFF ); +} + + +void SX126XLT::printModemSettings() +{ +#ifdef SX126XDEBUG + Serial.println(F("printModemSettings()")); +#endif + + printDevice(); + Serial.print(F(",")); + Serial.print(getFreqInt()); + Serial.print(F("hz,SF")); + Serial.print(getLoRaSF()); + Serial.print(F(",BW")); + Serial.print(returnBandwidth(savedModParam2)); + Serial.print(F(",CR4:")); + Serial.print((getLoRaCodingRate() + 4)); + Serial.print(F(",LDRO_")); + + if (getOptimisation()) + { + Serial.print(F("On")); + } + else + { + Serial.print(F("Off")); + } + + Serial.print(F(",SyncWord_0x")); + Serial.print(getSyncWord(), HEX); + if (getInvertIQ() == LORA_IQ_INVERTED) + { + Serial.print(F(",IQInverted")); + } + else + { + Serial.print(F(",IQNormal")); + } + Serial.print(F(",Preamble_")); + Serial.print(getPreamble()); +} + + +uint32_t SX126XLT::getFreqInt() +{ + //get the current set device frequency from registers, return as long integer +#ifdef SX126XDEBUG + Serial.println(F("getFreqInt()")); +#endif + + 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 * FREQ_STEP) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +uint8_t SX126XLT::getLoRaCodingRate() +{ +#ifdef SX126XDEBUG + Serial.println(F("getLoRaCodingRate")); +#endif + + return savedModParam3; +} + + +uint8_t SX126XLT::getOptimisation() +{ +#ifdef SX126XDEBUG + Serial.println(F("getOptimisation")); +#endif + + return savedModParam4; +} + + +uint16_t SX126XLT::getSyncWord() +{ +#ifdef SX126XDEBUG + Serial.println(F("getSyncWord")); +#endif + + uint8_t msb, lsb; + uint16_t syncword; + msb = readRegister(REG_LR_SYNCWORD); + lsb = readRegister(REG_LR_SYNCWORD + 1); + syncword = (msb << 8) + lsb; + + return syncword; +} + + +uint16_t SX126XLT::getPreamble() +{ +#ifdef SX126XDEBUG + Serial.println(F("getPreamble")); +#endif + + return savedPacketParam1; +} + + +void SX126XLT::printOperatingSettings() +{ +#ifdef SX126XDEBUG + Serial.println(F("printOperatingSettings()")); +#endif + + printDevice(); + + Serial.print(F(",PacketMode_")); + + if (savedPacketType == PACKET_TYPE_LORA) + { + Serial.print(F("LoRa")); + } + + if (savedPacketType == PACKET_TYPE_GFSK) + { + Serial.print(F("GFSK")); + } + + if (getHeaderMode()) + { + Serial.print(F(",Implicit")); + } + else + { + Serial.print(F(",Explicit")); + } + + Serial.print(F(",LNAgain_")); + + if (getLNAgain() == BOOSTED_GAIN) + { + Serial.print(F("Boosted")); + } + else + { + Serial.print(F("Powersave")); + } + +} + + +uint8_t SX126XLT::getHeaderMode() +{ +#ifdef SX126XDEBUG + Serial.println(F("getHeaderMode")); +#endif + + return savedPacketParam2; +} + + +uint8_t SX126XLT::getLNAgain() +{ +#ifdef SX126XDEBUG + Serial.println(F("getLNAgain")); +#endif + + return readRegister(REG_RX_GAIN); +} + + +void SX126XLT::setTxParams(int8_t TXpower, uint8_t RampTime) +{ + + //note this routine does not check if power levels are valid for the module in use +#ifdef SX126XDEBUG + Serial.println(F("setTxParams()")); +#endif + + uint8_t buffer[2]; + + savedTXPower = TXpower; + + buffer[0] = TXpower; + buffer[1] = (uint8_t)RampTime; + writeCommand(RADIO_SET_TXPARAMS, buffer, 2); +} + + +void SX126XLT::setTx(uint32_t timeout) +{ + //SX126x base timeout in units of 15.625 µs + //Note: timeout passed to function is in mS + +#ifdef SX126XDEBUG + Serial.println(F("setTx()")); +#endif + uint8_t buffer[3]; + + clearIrqStatus(IRQ_RADIO_ALL); + + if (_rxtxpinmode) + { + txEnable(); + } + + timeout = timeout << 6; //timeout passed in mS, convert to units of 15.625us + + buffer[0] = (timeout >> 16) & 0xFF; + buffer[1] = (timeout >> 8) & 0xFF; + buffer[2] = timeout & 0xFF; + + writeCommand(RADIO_SET_TX, buffer, 3 ); + _OperatingMode = MODE_TX; +} + + +void SX126XLT::clearIrqStatus(uint16_t irqMask) +{ +#ifdef SX126XDEBUG + Serial.println(F("clearIrqStatus()")); +#endif + + uint8_t buffer[2]; + + buffer[0] = (uint8_t) (irqMask >> 8); + buffer[1] = (uint8_t) (irqMask & 0xFF); + writeCommand(RADIO_CLR_IRQSTATUS, buffer, 2); +} + + +uint16_t SX126XLT::readIrqStatus() +{ +#ifdef SX126XDEBUG + Serial.print(F("readIrqStatus()")); +#endif + + uint16_t temp; + uint8_t buffer[2]; + + readCommand(RADIO_GET_IRQSTATUS, buffer, 2); + temp = ((buffer[0] << 8) + buffer[1]); + return temp; +} + + +uint16_t SX126XLT::CRCCCITT(uint8_t *buffer, uint8_t size, uint16_t start) +{ +#ifdef SX126XDEBUG + Serial.println(F("CRCCCITT()")); +#endif + + uint16_t index, libraryCRC; + uint8_t j; + + libraryCRC = start; //start value for CRC16 + + for (index = 0; index < size; index++) + { + libraryCRC ^= (((uint16_t)buffer[index]) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + + return libraryCRC; +} + + +uint8_t SX126XLT::transmit(uint8_t *txbuffer, uint8_t size, uint32_t txtimeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX126XDEBUG + Serial.println(F("transmit()")); +#endif + uint8_t index; + uint8_t bufferdata; + + if (size == 0) + { + return false; + } + + setMode(MODE_STDBY_RC); + setBufferBaseAddress(0, 0); + + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(0); + + for (index = 0; index < size; index++) + { + bufferdata = txbuffer[index]; + SPI.transfer(bufferdata); + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + _TXPacketL = size; + writeRegister(REG_LR_PAYLOADLENGTH, _TXPacketL); + setTxParams(txpower, RADIO_RAMP_200_US); + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1 + setTx(txtimeout); //this starts the TX + + if (!wait) + { + return _TXPacketL; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RX_TX_TIMEOUT ) //check for timeout + { + return 0; + } + else + { + return _TXPacketL; + } +} + + +void SX126XLT::printIrqStatus() +{ +#ifdef SX126XDEBUG + Serial.println(F("printIrqStatus()")); +#endif + + uint16_t _IrqStatus; + _IrqStatus = readIrqStatus(); + + //0x0001 + if (_IrqStatus & IRQ_TX_DONE) + { + Serial.print(F(",IRQ_TX_DONE")); + } + + //0x0002 + if (_IrqStatus & IRQ_RX_DONE) + { + Serial.print(F(",IRQ_RX_DONE")); + } + + //0x0004 + if (_IrqStatus & IRQ_PREAMBLE_DETECTED) + { + Serial.print(F(",IRQ_PREAMBLE_DETECTED")); + } + + //0x0008 + if (_IrqStatus & IRQ_SYNCWORD_VALID) + { + Serial.print(F(",IRQ_SYNCWORD_VALID")); + } + + //0x0010 + if (_IrqStatus & IRQ_HEADER_VALID) + { + Serial.print(F(",IRQ_HEADER_VALID")); + } + + //0x0020 + if (_IrqStatus & IRQ_HEADER_ERROR) + { + Serial.print(F(",IRQ_HEADER_ERROR")); + } + + //0x0040 + if (_IrqStatus & IRQ_CRC_ERROR) + { + Serial.print(F(",IRQ_CRC_ERROR")); + } + + //0x0080 + if (_IrqStatus & IRQ_CAD_DONE) + { + Serial.print(F(",IRQ_CAD_DONE")); + } + + //0x0100 + if (_IrqStatus & IRQ_CAD_ACTIVITY_DETECTED) + { + Serial.print(",IRQ_CAD_ACTIVITY_DETECTED"); + } + + //0x0200 + if (_IrqStatus & IRQ_RX_TX_TIMEOUT) + { + Serial.print(F(",IRQ_RX_TX_TIMEOUT")); + } + +} + + +void SX126XLT::printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of SX1262 registers to serial monitor + +#ifdef SX126XDEBUG + Serial.println(F("printRegisters()")); +#endif + + 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 SX126XLT::printDevice() +{ +#ifdef SX126XDEBUG + Serial.println(F("printDevice()")); +#endif + + + switch (_Device) + { + case DEVICE_SX1261: + Serial.print(F("SX1261")); + break; + + case DEVICE_SX1262: + Serial.print(F("SX1262")); + break; + + case DEVICE_SX1268: + Serial.print(F("SX1268")); + break; + + default: + Serial.print(F("Unknown Device")); + + } +} + + +bool SX126XLT::config() +{ +#ifdef SX126XDEBUG + Serial.println(F("config()")); +#endif + + resetDevice(); + setMode(MODE_STDBY_RC); + setRegulatorMode(savedRegulatorMode); + setPacketType(savedPacketType); + setRfFrequency(savedFrequency, savedOffset); + setModulationParams(savedModParam1, savedModParam2, savedModParam3, LDRO_ON); + setPacketParams(savedPacketParam1, savedPacketParam2, savedPacketParam3, savedPacketParam4, savedPacketParam5); + setDioIrqParams(savedIrqMask, savedDio1Mask, savedDio2Mask, savedDio3Mask); //set for IRQ on RX done on DIO1 + _TXPacketL = 0; + _RXPacketL = 0; + return true; +} + + +void SX126XLT::setRfFrequency( uint32_t frequency, int32_t offset ) +{ + //Note RF_Freq = freq_reg*32M/(2^25)-----> freq_reg = (RF_Freq * (2^25))/32 + +#ifdef SX126XDEBUG + Serial.print(F("setRfFrequency() ")); + Serial.println(frequency + offset); +#endif + + uint8_t buffer[4]; + uint32_t localfrequencyRegs; + + savedFrequency = frequency; + savedOffset = offset; + + localfrequencyRegs = frequency + offset; + + localfrequencyRegs = ( uint32_t )( ( double )localfrequencyRegs / ( double )FREQ_STEP ); + + savedFrequencyReg = localfrequencyRegs; + + buffer[0] = (localfrequencyRegs >> 24) & 0xFF; //MSB + buffer[1] = (localfrequencyRegs >> 16) & 0xFF; + buffer[2] = (localfrequencyRegs >> 8) & 0xFF; + buffer[3] = localfrequencyRegs & 0xFF;//LSB + + _freqregH = buffer[0]; + _freqregMH = buffer[1]; + _freqregML = buffer[2]; + _freqregL = buffer[3]; + + writeCommand(RADIO_SET_RFFREQUENCY, buffer, 4); +} + + +uint8_t SX126XLT::getLoRaSF() +{ +#ifdef SX126XDEBUG + Serial.println(F("getLoRaSF()")); +#endif + + return savedModParam1; +} + + +uint8_t SX126XLT::getInvertIQ() +{ + //IQ mode reg 0x33 +#ifdef SX126XDEBUG + Serial.println(F("getInvertIQ")); +#endif + + return readRegister(REG_IQ_POLARITY_SETUP); +} + + +void SX126XLT::rxEnable() +{ +#ifdef SX126XDEBUG + Serial.println(F("rxEnable()")); +#endif + + digitalWrite(_RXEN, HIGH); + digitalWrite(_TXEN, LOW); +} + + +void SX126XLT::txEnable() +{ +#ifdef SX126XDEBUGPINS + Serial.println(F("txEnable()")); +#endif + + digitalWrite(_RXEN, LOW); + digitalWrite(_TXEN, HIGH); +} + +void SX126XLT::printASCIIPacket(uint8_t *buffer, uint8_t size) +{ +#ifdef SX126XDEBUGPINS + Serial.println(F("printASCIIPacket()")); +#endif + + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } + +} + + +uint8_t SX126XLT::receive(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait) +{ +#ifdef SX126XDEBUG + Serial.println(F("receive()")); +#endif + + uint8_t index, RXstart, RXend; + uint16_t regdata; + uint8_t buffer[2]; + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on RX done or timeout + setRx(rxtimeout); + + if (!wait) + { + return 0; //not wait requested so no packet length to pass + } + + while (!digitalRead(_RXDonePin)); //Wait for DIO1 to go high + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + regdata = readIrqStatus(); + + if ( (regdata & IRQ_HEADER_ERROR) | (regdata & IRQ_CRC_ERROR) | (regdata & IRQ_RX_TX_TIMEOUT ) ) //check if any of the preceding IRQs is set + { + //packet is errored somewhere so return 0 + return 0; + } + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + + RXstart = buffer[1]; + + RXend = RXstart + _RXPacketL; + + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(RXstart); + SPI.transfer(0xFF); + + for (index = RXstart; index < RXend; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX126XLT::readPacketRSSI() +{ +#ifdef SX126XDEBUG + Serial.println(F("readPacketRSSI()")); +#endif + + uint8_t status[5]; + + readCommand(RADIO_GET_PACKETSTATUS, status, 5) ; + _PacketRSSI = -status[0] / 2; + + return _PacketRSSI; +} + + +uint8_t SX126XLT::readPacketSNR() +{ +#ifdef SX126XDEBUG + Serial.println(F("readPacketSNR()")); +#endif + + uint8_t status[5]; + + readCommand(RADIO_GET_PACKETSTATUS, status, 5) ; + + if ( status[1] < 128 ) + { + _PacketSNR = status[1] / 4 ; + } + else + { + _PacketSNR = (( status[1] - 256 ) / 4); + } + + return _PacketSNR; +} + +uint8_t SX126XLT::readRXPacketL() +{ +#ifdef SX126XDEBUG + Serial.println(F("readRXPacketL()")); +#endif + + uint8_t buffer[2]; + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + return _RXPacketL; +} + + +void SX126XLT::setRx(uint32_t timeout) +{ + //SX126x base timeout in units of 15.625 µs + //timeout passed to function in mS + //range is 1mS to 262 seconds + +#ifdef SX126XDEBUG + Serial.println(F("setRx()")); +#endif + uint8_t buffer[3]; + clearIrqStatus(IRQ_RADIO_ALL); + + if (_rxtxpinmode) + { + rxEnable(); + } + + timeout = timeout << 6; //timeout passed in mS, multiply by 64 to convert units of 15.625us to 1mS + + buffer[0] = (timeout >> 16) & 0xFF; + buffer[1] = (timeout >> 8) & 0xFF; + buffer[2] = timeout & 0xFF; + writeCommand(RADIO_SET_RX, buffer, 3 ); +} + +/*************************************************************************** +//Start direct access SX buffer routines +***************************************************************************/ + +void SX126XLT::startWriteSXBuffer(uint8_t ptr) +{ +#ifdef SX126XDEBUG + Serial.println(F("startWriteSXBuffer()")); +#endif + + _TXPacketL = 0; //this variable used to keep track of bytes written + setMode(MODE_STDBY_RC); + setBufferBaseAddress(ptr, 0); //TX,RX + + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(ptr); + //SPI interface ready for byte to write to buffer +} + + +uint8_t SX126XLT::endWriteSXBuffer() +{ +#ifdef SX126XDEBUG + Serial.println(F("endWriteSXBuffer()")); +#endif + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _TXPacketL; + +} + + +void SX126XLT::startReadSXBuffer(uint8_t ptr) +{ +#ifdef SX126XDEBUG + Serial.println(F("startReadSXBuffer")); +#endif + + _RXPacketL = 0; + + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); + #endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(ptr); + SPI.transfer(0xFF); + + //next line would be data = SPI.transfer(0); + //SPI interface ready for byte to read from +} + + +uint8_t SX126XLT::endReadSXBuffer() +{ +#ifdef SX126XDEBUG + Serial.println(F("endReadSXBuffer()")); +#endif + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; +} + + +void SX126XLT::writeUint8(uint8_t x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeUint8()")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + +uint8_t SX126XLT::readUint8() +{ +#ifdef SX126XDEBUG + Serial.println(F("readUint8()")); +#endif + byte x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX126XLT::writeInt8(int8_t x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeInt8()")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + + +int8_t SX126XLT::readInt8() +{ +#ifdef SX126XDEBUG + Serial.println(F("readInt8()")); +#endif + int8_t x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX126XLT::writeInt16(int16_t x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeInt16()")); +#endif + + SPI.transfer(lowByte(x)); + SPI.transfer(highByte(x)); + + _TXPacketL = _TXPacketL + 2; //increment count of bytes written +} + + +int16_t SX126XLT::readInt16() +{ +#ifdef SX126XDEBUG + Serial.println(F("readInt16()")); +#endif + byte lowbyte, highbyte; + + lowbyte = SPI.transfer(0); + highbyte = SPI.transfer(0); + + _RXPacketL = _RXPacketL + 2; //increment count of bytes read + return ((highbyte << 8) + lowbyte); +} + + +void SX126XLT::writeUint16(uint16_t x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeUint16()")); +#endif + + SPI.transfer(lowByte(x)); + SPI.transfer(highByte(x)); + + _TXPacketL = _TXPacketL + 2; //increment count of bytes written +} + + +uint16_t SX126XLT::readUint16() +{ +#ifdef SX126XDEBUG + Serial.println(F("writeUint16()")); +#endif + byte lowbyte, highbyte; + + lowbyte = SPI.transfer(0); + highbyte = SPI.transfer(0); + + _RXPacketL = _RXPacketL + 2; //increment count of bytes read + return ((highbyte << 8) + lowbyte); +} + + +void SX126XLT::writeInt32(int32_t x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeInt32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + int32_t f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +int32_t SX126XLT::readInt32() +{ +#ifdef SX126XDEBUG + Serial.println(F("readInt32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + int32_t f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX126XLT::writeUint32(uint32_t x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeUint32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + uint32_t f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +uint32_t SX126XLT::readUint32() +{ +#ifdef SX126XDEBUG + Serial.println(F("readUint32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + uint32_t f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX126XLT::writeFloat(float x) +{ +#ifdef SX126XDEBUG + Serial.println(F("writeFloat()")); +#endif + + byte i, j; + + union + { + byte b[4]; + float f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +float SX126XLT::readFloat() +{ +#ifdef SX126XDEBUG + Serial.println(F("readFloat()")); +#endif + + byte i, j; + + union + { + byte b[4]; + float f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +uint8_t SX126XLT::transmitSXBuffer(uint8_t startaddr, uint8_t length, uint32_t txtimeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX126XDEBUG + Serial.println(F("transmitSXBuffer()")); +#endif + + setBufferBaseAddress(startaddr, 0); //TX, RX + + setPacketParams(savedPacketParam1, savedPacketParam2, length, savedPacketParam4, savedPacketParam5); + setTxParams(txpower, RAMP_TIME); + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1 + setTx(txtimeout); //this starts the TX + + if (!wait) + { + return _TXPacketL; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RX_TX_TIMEOUT ) //check for timeout + { + return 0; + } + else + { + return _TXPacketL; + } +} + + +void SX126XLT::writeBuffer(uint8_t *txbuffer, uint8_t size) +{ +#ifdef SX126XDEBUG1 + Serial.println(F("writeBuffer()")); +#endif + + uint8_t index, regdata; + + _TXPacketL = _TXPacketL + size; //these are the number of bytes that will be added + + size--; //loose one byte from size, the last byte written MUST be a 0 + + for (index = 0; index < size; index++) + { + regdata = txbuffer[index]; + SPI.transfer(regdata); + } + + SPI.transfer(0); //this ensures last byte of buffer written really is a null (0) + +} + + +uint8_t SX126XLT::receiveSXBuffer(uint8_t startaddr, uint32_t rxtimeout, uint8_t wait ) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("receiveSXBuffer()")); +#endif + + uint16_t regdata; + uint8_t buffer[2]; + + setMode(MODE_STDBY_RC); + + setBufferBaseAddress(0, startaddr); //order is TX RX + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on RX done or timeout + setRx(rxtimeout); //no actual RX timeout in this function + + if (!wait) + { + return 0; + } + + while (!digitalRead(_RXDonePin)); //Wait for DIO1 to go high + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + regdata = readIrqStatus(); + + if ( (regdata & IRQ_HEADER_ERROR) | (regdata & IRQ_CRC_ERROR) | (regdata & IRQ_RX_TX_TIMEOUT ) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + return _RXPacketL; +} + + +uint8_t SX126XLT::readBuffer(uint8_t *rxbuffer) +{ +#ifdef SX126XDEBUG1 + Serial.println(F("readBuffer()")); +#endif + + uint8_t index = 0, regdata; + + do //need to find the size of the buffer first + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; //fill the buffer. + index++; + } while (regdata != 0); //keep reading until we have reached the null (0) at the buffer end + //or exceeded size of buffer allowed + _RXPacketL = _RXPacketL + index; //increment count of bytes read + return index; //return the actual size of the buffer, till the null (0) detected + +} + +/*************************************************************************** +//End direct access SX buffer routines +***************************************************************************/ + +uint16_t SX126XLT::CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue) +{ + //genrates a CRC of an area of the internal SX buffer + +#ifdef SX126XDEBUG1 + Serial.println(F("CRCCCITTSX()")); +#endif + + + uint16_t index, libraryCRC; + uint8_t j; + + libraryCRC = startvalue; //start value for CRC16 + + startReadSXBuffer(startadd); //begin the buffer read + + for (index = startadd; index <= endadd; index++) + { + libraryCRC ^= (((uint16_t) readUint8() ) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + + endReadSXBuffer(); //end the buffer read + + return libraryCRC; +} + + +void SX126XLT::setSleep(uint8_t sleepconfig) +{ +#ifdef SX126XDEBUG + Serial.println(F("setSleep()")); +#endif + setMode(MODE_STDBY_RC); + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_SET_SLEEP); + SPI.transfer(sleepconfig); + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); + #endif + + if (_SW >= 0) + { + digitalWrite(_SW, LOW); //turn off antenna switch if SW pin in use, saves 9uA. + } + + delay(1); //allow time for shutdown +} + + +void SX126XLT::wake() +{ +#ifdef SX126XDEBUG + Serial.println(F("wake()")); +#endif + +if (_SW >= 0) + { + digitalWrite(_SW, HIGH); //turn on antenna switch if SW pin in use + } + +digitalWrite(_NSS, LOW); +delay(1); +digitalWrite(_NSS, HIGH); +delay(1); +} + + +void SX126XLT::setupDirect(uint32_t frequency, int32_t offset) +{ + //setup LoRa device for direct modulation mode +#ifdef SX126XDEBUG1 + Serial.print(F("setupDirect()")); +#endif + setMode(MODE_STDBY_RC); + setRegulatorMode(USE_DCDC); + setPaConfig(0x04, PAAUTO, _Device); //use _Device, saved by begin. + setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V); + calibrateDevice(ALLDevices); //is required after setting TCXO + calibrateImage(frequency); + setDIO2AsRfSwitchCtrl(); + setRfFrequency(frequency, offset); +} + + +void SX126XLT::setTXDirect() +{ + //turns on transmitter,in direct mode for FSK and audio power level is from 2 to 17 +#ifdef SX127XDEBUG1 + Serial.print(F("setTxFSK()")); +#endif + writeCommand(RADIO_SET_TXCONTINUOUSWAVE, 0, 0); +} + + +void SX126XLT::toneFM(uint16_t frequency, uint32_t length, uint32_t deviation, float adjust, uint8_t txpower) +{ +#ifdef SX126XDEBUG1 + Serial.print(F("toneFM()")); +#endif + uint16_t index; + uint32_t ToneDelayus; + uint32_t registershift; + uint32_t shiftedfreqregH, shiftedfreqregL; + uint32_t loopcount; + + registershift = deviation/FREQ_STEP; + shiftedfreqregH = savedFrequencyReg + registershift; + shiftedfreqregL = savedFrequencyReg - registershift; + + uint8_t HighShiftH = shiftedfreqregH >> 24; + uint8_t HighShiftMH = shiftedfreqregH >> 16; + uint8_t HighShiftML = shiftedfreqregH >> 8; + uint8_t HighShiftL = shiftedfreqregH; + uint8_t LowShiftH = shiftedfreqregL >> 24; + uint8_t LowShiftMH = shiftedfreqregL >> 16; + uint8_t LowShiftML = shiftedfreqregL >> 8; + uint8_t LowShiftL = shiftedfreqregL; + uint8_t freqregH = savedFrequencyReg >> 24; + uint8_t freqregMH = savedFrequencyReg >> 16; + uint8_t freqregML = savedFrequencyReg >> 8; + uint8_t freqregL = savedFrequencyReg; + + + ToneDelayus = ((500000/frequency)); + loopcount = (length * 500) / (ToneDelayus); + ToneDelayus = ToneDelayus * adjust; + + + #ifdef SX126XDEBUG3 + Serial.print(F("frequency ")); + Serial.println(frequency); + Serial.print(F("length ")); + Serial.println(length); + + Serial.print(F("savedFrequencyReg ")); + Serial.println(savedFrequencyReg, HEX); + Serial.print(F("registershift ")); + Serial.println(registershift); + shiftedfreqregH = savedFrequencyReg + (registershift/2); + shiftedfreqregL = savedFrequencyReg - (registershift/2); + Serial.print(F("shiftedfreqregH ")); + Serial.println(shiftedfreqregH, HEX); + Serial.print(F("shiftedfreqregL ")); + Serial.println(shiftedfreqregL, HEX); + + Serial.print(F("ShiftedHigh,")); + Serial.print(HighShiftH,HEX); + Serial.print(F(",")); + Serial.print(HighShiftMH,HEX); + Serial.print(F(",")); + Serial.print(HighShiftML,HEX); + Serial.print(F(",")); + Serial.println(HighShiftL,HEX); + + Serial.print(F("ShiftedLow,")); + Serial.print(LowShiftH,HEX); + Serial.print(F(",")); + Serial.print(LowShiftMH,HEX); + Serial.print(F(",")); + Serial.print(LowShiftML,HEX); + Serial.print(F(",")); + Serial.println(LowShiftL,HEX); + Serial.print(F("ToneDelayus,")); + Serial.println(ToneDelayus); + Serial.print(F("loopcount,")); + Serial.println(loopcount); + Serial.println(); + Serial.println(); + #endif + + setTxParams(txpower, RADIO_RAMP_200_US); + setTXDirect(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); + #endif + + for (index = 1; index <= loopcount; index++) +{ + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_SET_RFFREQUENCY); + SPI.transfer(HighShiftH); + SPI.transfer(HighShiftMH); + SPI.transfer(HighShiftML); + SPI.transfer(HighShiftL); + digitalWrite(_NSS, HIGH); + + + delayMicroseconds(ToneDelayus); + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_SET_RFFREQUENCY); + SPI.transfer(LowShiftH); + SPI.transfer(LowShiftMH); + SPI.transfer(LowShiftML); + SPI.transfer(LowShiftL); + digitalWrite(_NSS, HIGH); + + delayMicroseconds(ToneDelayus); +} + + //now set the frequency registers back to centre + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(0x86); //address for write to REG_FRMSB + SPI.transfer(freqregH); + SPI.transfer(freqregMH); + SPI.transfer(freqregML); + SPI.transfer(freqregL); + digitalWrite(_NSS, HIGH); //set NSS high + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); + #endif + + setMode(MODE_STDBY_RC); //turns off carrier +} + + +uint8_t SX126XLT::getByteSXBuffer(uint8_t addr) +{ +#ifdef SX126XDEBUG1 + Serial.println(F("getByteSXBuffer()")); +#endif + + uint8_t regdata; + setMode(MODE_STDBY_RC); //this is needed to ensure we can read from buffer OK. + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(addr); + SPI.transfer(0xFF); + regdata = SPI.transfer(0); + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return regdata; +} + + +void SX126XLT::printSXBufferHEX(uint8_t start, uint8_t end) +{ +#ifdef SX126XDEBUG + Serial.println(F("printSXBufferHEX()")); +#endif + + uint8_t index, regdata; + + setMode(MODE_STDBY_RC); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(start); + SPI.transfer(0xFF); + + for (index = start; index <= end; index++) + { + regdata = SPI.transfer(0); + printHEXByte(regdata); + Serial.print(F(" ")); + + } + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +int32_t SX126XLT::getFrequencyErrorHz() +{ + //Note: Semtech appear to have stated that the frequency error function that this code uses, + //is not supported for SX126X, for reasons that have not been given, so use at your own risk. + //The fuctions here are a replication of the routines for the very similar SX128X + + #ifdef SX126XDEBUG + Serial.println(F("getFrequencyErrorHz()")); + #endif + + int32_t error, regvalue; + uint32_t bandwidth; + float divider; + + bandwidth = returnBandwidth(savedModParam2); //gets the last configured bandwidth in hz + divider = (float) 1625000 / bandwidth; //why the values from the SX1280 datasheet work I have no idea + + regvalue = getFrequencyErrorRegValue(); + + error = (FREQ_ERROR_CORRECTION * regvalue) / divider; + + return error; +} + + +int32_t SX126XLT::getFrequencyErrorRegValue() +{ + #ifdef SX126XDEBUG + Serial.println(F("getFrequencyErrorRegValue()")); +#endif + +int32_t FrequencyError; + uint32_t regmsb, regmid, reglsb, allreg; + + setMode(MODE_STDBY_XOSC); + + regmsb = readRegister( REG_FREQUENCY_ERRORBASEADDR ); + regmsb = regmsb & 0x0F; //clear bit 20 which is always set + + regmid = readRegister( REG_FREQUENCY_ERRORBASEADDR + 1 ); + + reglsb = readRegister( REG_FREQUENCY_ERRORBASEADDR + 2 ); + + setMode(MODE_STDBY_RC); + + #ifdef SX126XDEBUG + Serial.println(); + Serial.print(F("Registers ")); + Serial.print(regmsb,HEX); + Serial.print(F(" ")); + Serial.print(regmid,HEX); + Serial.print(F(" ")); + Serial.println(reglsb,HEX); + #endif + + allreg = (uint32_t) ( regmsb << 16 ) | ( regmid << 8 ) | reglsb; + + if (allreg & 0x80000) + { + FrequencyError = (0xFFFFF - allreg) * -1; + } + else + { + FrequencyError = allreg; + } + + return FrequencyError; +} + + + +void SX126XLT::printHEXByte(uint8_t temp) +{ + if (temp < 0x10) + { + Serial.print(F("0")); + } + Serial.print(temp, HEX); +} + + + +uint8_t SX126XLT::transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t txtimeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX126XDEBUG + Serial.println(F("transmitAddressed()")); +#endif + + uint8_t index; + uint8_t bufferdata; + + if (size == 0) + { + return false; + } + + setMode(MODE_STDBY_RC); + + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(0); + + SPI.transfer(txpackettype); //Write the packet type + SPI.transfer(txdestination); //Destination node + SPI.transfer(txsource); //Source node + _TXPacketL = 3 + size; //we have added 3 header bytes to size + + for (index = 0; index < size; index++) + { + bufferdata = txbuffer[index]; + SPI.transfer(bufferdata); + } + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + //checkBusy(); + + writeRegister(REG_LR_PAYLOADLENGTH, _TXPacketL); + setTxParams(txpower, RAMP_TIME); + setTx(txtimeout); //this starts the TX + + if (!wait) + { + return _TXPacketL; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RX_TX_TIMEOUT ) //check for timeout + { + return 0; + } + else + { + return _TXPacketL; + } +} + + +uint8_t SX126XLT::readRXPacketType() +{ + #ifdef SX126XDEBUG + Serial.println(F("readRXPacketType()")); +#endif +return _RXPacketType; +} + + +uint8_t SX126XLT::readRXDestination() +{ + #ifdef SX126XDEBUG + Serial.println(F("readRXDestination()")); +#endif + return _RXDestination; +} + + +uint8_t SX126XLT::readRXSource() +{ +#ifdef SX126XDEBUG + Serial.println(F("readRXSource()")); +#endif +return _RXSource; +} + + + +uint8_t SX126XLT::receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait) +{ +#ifdef SX126XDEBUG + Serial.println(F("receiveAddressed()")); +#endif + + uint8_t index, RXstart, RXend; + uint16_t regdata; + uint8_t buffer[2]; + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on RX done or timeout + setRx(rxtimeout); + + if (!wait) + { + return 0; //not wait requested so no packet length to pass + } + + while (!digitalRead(_RXDonePin)); //Wait for DIO1 to go high + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + regdata = readIrqStatus(); + + if ( (regdata & IRQ_HEADER_ERROR) | (regdata & IRQ_CRC_ERROR) | (regdata & IRQ_RX_TX_TIMEOUT ) ) //check if any of the preceding IRQs is set + { + //packet is errored somewhere so return 0 + return 0; + } + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + + RXstart = buffer[1]; + + RXend = RXstart + _RXPacketL; + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(RXstart); + SPI.transfer(0xFF); + + _RXPacketType = SPI.transfer(0); + _RXDestination = SPI.transfer(0); + _RXSource = SPI.transfer(0); + + for (index = RXstart; index < RXend; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +void SX126XLT::clearDeviceErrors() +{ + #ifdef SX126XDEBUG + Serial.println(F("clearDeviceErrors()")); + #endif + + + uint8_t buffer[2]; + + buffer[0] = 0x00; //can only clear all errors + buffer[1] = 0x00; + + writeCommand(RADIO_CLEAR_ERRORS, buffer, 2); +} + + +void SX126XLT::printDeviceErrors() +{ +#ifdef SX126XDEBUG + Serial.println(F("printDeviceErrors()")); +#endif + + uint16_t errors; + uint8_t buffer[2]; + + readCommand(RADIO_GET_ERROR, buffer, 2); + + errors = (buffer[0] << 8) + buffer[1]; + + //0x0001 + if (errors & RC64K_CALIB_ERR) + { + Serial.print(F(",RC64K_CALIB_ERR")); + } + + //0x0002 + if (errors & RC13M_CALIB_ERR) + { + Serial.print(F(",RC13M_CALIB_ERR")); + } + + //0x0004 + if (errors & PLL_CALIB_ERR) + { + Serial.print(F(",PLL_CALIB_ERR")); + } + + //0x0008 + if (errors & ADC_CALIB_ERR) + { + Serial.print(F(",ADC_CALIB_ERR")); + } + + //0x0010 + if (errors & IMG_CALIB_ERR) + { + Serial.print(F(",IMG_CALIB_ERR")); + } + + //0x0020 + if (errors & XOSC_START_ERR) + { + Serial.print(F(",XOSC_START_ERR")); + } + + //0x0040 + if (errors & PLL_LOCK_ERR) + { + Serial.print(F(",PLL_LOCK_ERR")); + } + + //0x0080 + if (errors & RFU) + { + Serial.print(F(",RFU")); + } + + //0x0100 + if (errors & PA_RAMP_ERR) + { + Serial.print(",PA_RAMP_ERR"); + } +} + + +void SX126XLT::printHEXPacket(uint8_t *buffer, uint8_t size) +{ +#ifdef SX126XDEBUG + Serial.println(F("printHEXPacket()")); +#endif + + uint8_t index; + + for (index = 0; index < size; index++) + { + //Serial.print(F("[")); + //Serial.print(index); + //Serial.print(F("],")); + printHEXByte(buffer[index]); + Serial.print(F(" ")); + } +} + + +void SX126XLT::printHEXByte0x(uint8_t temp) +{ + //print a byte, adding 0x + Serial.print(F("0x")); + if (temp < 0x10) + { + Serial.print(F("0")); + } + Serial.print(temp, HEX); +} + + +uint8_t SX126XLT::readsavedModParam1() +{ +//return previously set spreading factor +#ifdef SX126XDEBUG + Serial.println(F("readsavedModParam1()")); +#endif +return savedModParam1; +} + + +uint8_t SX126XLT::readsavedModParam2() +{ +//return previously set bandwidth +#ifdef SX126XDEBUG + Serial.println(F("readsavedModParam2()")); +#endif + return savedModParam2; +} + + +uint8_t SX126XLT::readsavedModParam3() +{ +//return previously set code rate + #ifdef SX126XDEBUG + Serial.println(F("readsavedModParam3()")); +#endif +return savedModParam3; +} + + +uint8_t SX126XLT::readsavedModParam4() +{ +//return previously set optimisation +#ifdef SX126XDEBUG + Serial.println(F("readsavedModParam4()")); +#endif + return savedModParam4; +} + +uint8_t SX126XLT::readsavedPower() +{ + #ifdef SX126XDEBUG + Serial.println(F("readsavedPower()")); +#endif +return savedTXPower; +} + +uint8_t SX126XLT::getPacketMode() +{ + //its either LoRa or FSK + + #ifdef SX126XDEBUG + Serial.println(F("getPacketMode()")); + #endif + + return savedPacketType; +} + + +uint8_t SX126XLT::readsavedPacketParam1() +{ +//return previously set preamble +#ifdef SX126XDEBUG + Serial.println(F("readsavedPacketParam1()")); +#endif + return savedPacketParam1; +} + + +uint8_t SX126XLT::readsavedPacketParam2() +{ +//return previously set header type +#ifdef SX126XDEBUG + Serial.println(F("readsavedPacketParam2()")); +#endif + return savedPacketParam2; +} + + +uint8_t SX126XLT::readsavedPacketParam3() +{ +//return previously set packet length +#ifdef SX126XDEBUG + Serial.println(F("readsavedPacketParam3()")); +#endif + return savedPacketParam3; +} + + + +uint8_t SX126XLT::readsavedPacketParam4() +{ +//return previously set CRC +#ifdef SX126XDEBUG + Serial.println(F("readsavedPacketParam4()")); +#endif + return savedPacketParam4; +} + + +uint8_t SX126XLT::readsavedPacketParam5() +{ +//return previously set IQ +#ifdef SX126XDEBUG + Serial.println(F("readsavedPacketParam5()")); +#endif + return savedPacketParam5; +} + +uint8_t SX126XLT::getOpmode() +{ +//return last saved opmode +#ifdef SX126XDEBUG + Serial.println(F("getOpmode()")); +#endif + return _OperatingMode; +} + +uint8_t SX126XLT::getCRCMode() +{ +//return last saved opmode +#ifdef SX126XDEBUG + Serial.println(F("getCRCMode()")); +#endif + return savedPacketParam4; +} + + + +void SX126XLT::fillSXBuffer(uint8_t startaddress, uint8_t size, uint8_t character) +{ +#ifdef SX126XDEBUG1 + Serial.println(F("fillSXBuffer()")); +#endif + uint8_t index; + + setMode(MODE_STDBY_RC); + //writeRegister(REG_FIFOADDRPTR, startaddress); //and save in FIFO access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(startaddress); + //SPI interface ready for byte to write to buffer + + for (index = 0; index < size; index++) + { + SPI.transfer(character); + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +uint8_t SX126XLT::readPacket(uint8_t *rxbuffer, uint8_t size) +{ +#ifdef SX126XDEBUG + Serial.println(F("readPacket()")); +#endif + + uint8_t index, regdata, RXstart, RXend; + uint8_t buffer[2]; + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + + RXstart = buffer[1]; + + RXend = RXstart + _RXPacketL; + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(RXstart); + SPI.transfer(0xFF); + + for (index = RXstart; index < RXend; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +void SX126XLT::writeByteSXBuffer(uint8_t addr, uint8_t regdata) +{ +#ifdef SX126XDEBUG1 + Serial.println(F("writeByteSXBuffer")); +#endif + + setMode(MODE_STDBY_RC); //this is needed to ensure we can write to buffer OK. + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(addr); + SPI.transfer(regdata); + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); + #endif + +} + + +void SX126XLT::printSXBufferASCII(uint8_t start, uint8_t end) +{ +#ifdef SX126XDEBUG1 + Serial.println(F("printSXBufferASCII)")); +#endif + + uint8_t index, regdata; + setMode(MODE_STDBY_RC); + + for (index = start; index <= end; index++) + { + regdata = getByteSXBuffer(index); + Serial.write(regdata); + } + +} + + +void SX126XLT::startFSKRTTY(uint32_t freqshift, uint8_t pips, uint16_t pipPeriodmS, uint16_t pipDelaymS, uint16_t leadinmS) +{ + + #ifdef SX126XDEBUG1 + Serial.print(F("startFSKRTTY()")); + #endif + + uint32_t shiftedFrequencyRegisters; + uint8_t index; + uint32_t endmS; + uint32_t calculatedRegShift; + + calculatedRegShift = (uint32_t) (freqshift/FREQ_STEP); + + shiftedFrequencyRegisters = savedFrequencyReg + calculatedRegShift; + + _ShiftfreqregH = (shiftedFrequencyRegisters >> 24) & 0xFF; //MSB + _ShiftfreqregMH = (shiftedFrequencyRegisters >> 16) & 0xFF; + _ShiftfreqregML = (shiftedFrequencyRegisters >> 8) & 0xFF; + _ShiftfreqregL = shiftedFrequencyRegisters & 0xFF; //LSB + + #ifdef DEBUGFSKRTTY + Serial.print(F("NotShiftedFrequencyRegisters ")); + Serial.println(savedFrequencyReg, HEX); + Serial.print(F("calculatedRegShift ")); + Serial.println(calculatedRegShift, HEX); + Serial.print(F("ShiftedFrequencyRegisters ")); + Serial.print((uint32_t) shiftedFrequencyRegisters, HEX); + Serial.print(F(" (")); + Serial.print(_ShiftfreqregH,HEX); + Serial.print(F(" ")); + Serial.print(_ShiftfreqregMH,HEX); + Serial.print(F(" ")); + Serial.print(_ShiftfreqregML,HEX); + Serial.print(F(" ")); + Serial.print(_ShiftfreqregL,HEX); + Serial.print(F(" )")); + Serial.println(); + #endif + + setTxParams(10, RADIO_RAMP_200_US); + + for (index = 1; index <= pips; index++) + { + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency + setTXDirect(); //turn on carrier + delay(pipPeriodmS); + setMode(MODE_STDBY_RC); //turns off carrier + delay(pipDelaymS); + } + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML,_ShiftfreqregL); //set carrier frequency + endmS = millis() + leadinmS; + setTXDirect(); //turn on carrier + while (millis() < endmS); //leave leadin on + +} + + + void SX126XLT::transmitFSKRTTY(uint8_t chartosend, uint8_t databits, uint8_t stopbits, uint8_t parity, uint16_t baudPerioduS, int8_t pin) +{ + //micros() will rollover at 4294967295 or 71mins 35secs + //assume slowest baud rate is 45 (baud period of 22222us) then with 11 bits max to send if routine starts + //when micros() > (4294967295 - (22222 * 11) = 4294722855 = 0xFFFC4525 then it could overflow during send + //Rather than deal with rolloever in the middle of a character lets wait till it overflows and then + //start the character + + + #ifdef SX126XDEBUG1 + Serial.print(F("transmitFSKRTTY()")); + #endif + + uint8_t numbits; + uint32_t enduS; + uint8_t bitcount = 0; //set when a bit is 1 + + if (micros() > 0xFFFB6000) //check if micros would overflow within circa 300mS, approx 1 char at 45baud + { + + #ifdef DEBUGFSKRTTY + Serial.print(F("Overflow pending - micros() = ")); + Serial.println(micros(),HEX); + #endif + + while (micros() > 0xFFFB6000); //wait a short while until micros overflows to 0 + + #ifdef DEBUGFSKRTTY + Serial.print(F("Paused - micros() = ")); + Serial.println(micros(),HEX); + #endif + + } + + enduS = micros() + baudPerioduS; + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency (low) + + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + + while (micros() < enduS); //start bit + + for (numbits = 1; numbits <= databits; numbits++) //send bits, LSB first + { + enduS = micros() + baudPerioduS; //start the timer + if ((chartosend & 0x01) != 0) //test for bit set, a 1 + { + bitcount++; + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency for a 1 + } + else + { + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency for a 0 + } + chartosend = (chartosend >> 1); //get the next bit + while (micros() < enduS); + } + + enduS = micros() + baudPerioduS; //start the timer for possible parity bit + + switch (parity) + { + case ParityNone: + break; + + case ParityZero: + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency for a 0 + while (micros() < enduS); + break; + + case ParityOne: + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency for a 1 + while (micros() < enduS); + break; + + case ParityOdd: + if (bitRead(bitcount, 0)) + { + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency for a 1 + } + else + { + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency for a 0 + } + while (micros() < enduS); + break; + + case ParityEven: + if (bitRead(bitcount, 0)) + { + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency for a 0 + } + else + { + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency for a 1 + } + while (micros() < enduS); + break; + + default: + break; + } + + //stop bits, normally 1 or 2 + enduS = micros() + (baudPerioduS * stopbits); + + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency for a 1 + + while (micros() < enduS); + +} + + + +void SX126XLT::transmitFSKRTTY(uint8_t chartosend, uint16_t baudPerioduS, int8_t pin) +{ + //micros() will rollover at 4294967295 or 71mins 35secs + //assume slowest baud rate is 45 (baud period of 22222us) then with 11 bits max to send if routine starts + //when micros() > (4294967295 - (22222 * 11) = 4294722855 = 0xFFFC4525 then it could overflow during send + //Rather than deal with rolloever in the middle of a character lets wait till it overflows and then + //start the character + //This overloaded version of transmitFSKRTTY() uses 1 start bit, 7 data bits, no parity and 2 stop bits. + + + #ifdef SX126XDEBUG1 + Serial.print(F("transmitFSKRTTY()")); + #endif + + uint8_t numbits; + uint32_t enduS; + + if (micros() > 0xFFFB6000) //check if micros would overflow within circa 300mS, approx 1 char at 45baud + { + #ifdef DEBUGFSKRTTY + Serial.print(F("Overflow pending - micros() = ")); + Serial.println(micros(),HEX); + #endif + while (micros() > 0xFFFB6000); //wait a short while until micros overflows to 0 + #ifdef DEBUGFSKRTTY + Serial.print(F("Paused - micros() = ")); + Serial.println(micros(),HEX); + #endif + } + + enduS = micros() + baudPerioduS; + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency (low) + + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + + while (micros() < enduS); //start bit + + for (numbits = 1; numbits <= 7; numbits++) //send bits, LSB first + { + enduS = micros() + baudPerioduS; //start the timer + if ((chartosend & 0x01) != 0) //test for bit set, a 1 + { + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency for a 1 + } + else + { + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + setRfFrequencyDirect(_freqregH, _freqregMH, _freqregML, _freqregL); //set carrier frequency for a 0 + } + chartosend = (chartosend >> 1); //get the next bit + while (micros() < enduS); + } + + //stop bits, normally 1 or 2 + enduS = micros() + (baudPerioduS * 2); + + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL); //set carrier frequency + + while (micros() < enduS); + +} + + + + + +void SX126XLT::printRTTYregisters() +{ + + #ifdef SX126XDEBUG1 + Serial.print(F("printRTTYregisters()")); + #endif + +Serial.print(F("NoShift Registers ")); +Serial.print(_freqregH, HEX); +Serial.print(F(" ")); +Serial.print(_freqregMH, HEX); +Serial.print(F(" ")); +Serial.print(_freqregML, HEX); +Serial.print(F(" ")); +Serial.println(_freqregL, HEX); + +Serial.print(F("Shifted Registers ")); +Serial.print(_ShiftfreqregH, HEX); +Serial.print(F(" ")); +Serial.print(_ShiftfreqregMH, HEX); +Serial.print(F(" ")); +Serial.print(_ShiftfreqregML, HEX); +Serial.print(F(" ")); +Serial.println(_ShiftfreqregL, HEX); + +} + + +void SX126XLT::endFSKRTTY() +{ + #ifdef SX126XDEBUG1 + Serial.print(F("endFSKRTTY()")); + #endif + + setMode(MODE_STDBY_RC); + +} + + +void SX126XLT::getRfFrequencyRegisters(uint8_t *buff) +{ + //returns the register values for the current set frequency + + #ifdef SX126XDEBUG1 + Serial.print(F("getRfFrequencyRegisters()")); + #endif + + buff[0] = _freqregH; + buff[1] = _freqregMH; + buff[2] = _freqregML; + buff[3] = _freqregL; + +} + + +void SX126XLT::setRfFrequencyDirect(uint8_t high, uint8_t midhigh, uint8_t midlow, uint8_t low) +{ + + #ifdef SX126XDEBUG1 + Serial.print(F("setRfFrequencyDirect()")); + #endif + + uint8_t buffer[4]; + + buffer[0] = high; //MSB + buffer[1] = midhigh; + buffer[2] = midlow; + buffer[3] = low;//LSB + + writeCommand(RADIO_SET_RFFREQUENCY, buffer, 4); + +} + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ diff --git a/lib/SX12XX-LoRa/src/SX126XLT.h b/lib/SX12XX-LoRa/src/SX126XLT.h new file mode 100644 index 0000000..400f966 --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX126XLT.h @@ -0,0 +1,229 @@ + +#ifndef SX126XLT_h +#define SX126XLT_h + +#include "Arduino.h" +#include + +/************************************************************************** + + ToDO + + DONE - Check setDIOIRQ is before all setTX SetRX calls + DONE - Check for checkbusy, before all uses of SPI + DONE - Match printlorasettings and printdevice settings with sx127x library + DONE - Check if SX126X has AGCauto_ + DONE - Check correct setting of optimisation + DONE - Check in addressed send txpacketL = 3 + size; //we have added 3 header bytes to size + DONE - Investigate use of clearDeviceErrors() - Not used in Semtech sample code + ABANDONED - Investigate if setPacketParams(savedPacketParam1, savedPacketParam2 in send routine can be avoided - TXpacketL + DONE - Test rxEnable and txenable functionality + DONE - Check TX power settings at 17dBm + + + Description of how to include RxGain register in the retention memory, see Section 9.6 - manual p58 + + Add a library function for SetRxDutyCycle ? + Add a library function to allow changing of ramptime from RADIO_RAMP_200_US ? + Check use of RADIO_RAMP_DEFAULT + + +**************************************************************************/ + +class SX126XLT { + public: + + SX126XLT(); + + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, int8_t pinSW, uint8_t device); + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device); + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinSW, uint8_t device); + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device); + + void checkBusy(); + void writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size ); + void readCommand( uint8_t Opcode, uint8_t *buffer, uint16_t size ); + void writeRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + void writeRegister( uint16_t address, uint8_t value ); + void readRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + uint8_t readRegister( uint16_t address ); + void resetDevice(); + bool checkDevice(); + void setupLoRa(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4); + void setMode(uint8_t modeconfig); + void setRegulatorMode(uint8_t mode); + + void setPaConfig(uint8_t dutycycle, uint8_t hpMax, uint8_t device); + void setDIO3AsTCXOCtrl(uint8_t tcxoVoltage); + void calibrateDevice(uint8_t devices); + void calibrateImage(uint32_t freq); + void setDIO2AsRfSwitchCtrl(); + void setPacketType(uint8_t PacketType); + void setRfFrequency( uint32_t frequency, int32_t offset ); + void setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4); + uint8_t returnOptimisation(uint8_t SpreadingFactor, uint8_t Bandwidth); + uint32_t returnBandwidth(uint8_t BWregvalue); + float calcSymbolTime(float Bandwidth, uint8_t SpreadingFactor); + void setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress); + void setPacketParams(uint16_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5); + void setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ); + void setHighSensitivity(); + void setLowPowerRX(); + void setSyncWord(uint16_t syncword); + void printModemSettings(); + void printDevice(); + uint32_t getFreqInt(); //this reads the SX126x registers to get the current frequency + uint8_t getLoRaSF(); + + uint8_t getLoRaCodingRate(); + uint8_t getOptimisation(); + + uint16_t getSyncWord(); + uint8_t getInvertIQ(); + uint16_t getPreamble(); + void printOperatingSettings(); + uint8_t getHeaderMode(); + uint8_t getLNAgain(); + void printRegisters(uint16_t Start, uint16_t End); + void printASCIIPacket(uint8_t *buff, uint8_t tsize); + uint8_t transmit(uint8_t *txbuffer, uint8_t size, uint32_t txtimeout, int8_t txpower, uint8_t wait); + void setTxParams(int8_t TXpower, uint8_t RampTime); + void setTx(uint32_t timeout); + void clearIrqStatus( uint16_t irq ); + uint16_t readIrqStatus(); + uint16_t CRCCCITT(uint8_t *buffer, uint8_t size, uint16_t start); + uint8_t receive(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait); + uint8_t readPacketRSSI(); + uint8_t readPacketSNR(); + uint8_t readRXPacketL(); + void setRx(uint32_t timeout); + + void printIrqStatus(); + void rxEnable(); + void txEnable(); + bool config(); + +/*************************************************************************** +//Start direct access SX buffer routines +***************************************************************************/ + + void startWriteSXBuffer(uint8_t ptr); + uint8_t endWriteSXBuffer(); + void startReadSXBuffer(uint8_t ptr); + uint8_t endReadSXBuffer(); + + void writeUint8(uint8_t x); + uint8_t readUint8(); + + void writeInt8(int8_t x); + int8_t readInt8(); + + void writeInt16(int16_t x); + int16_t readInt16(); + + void writeUint16(uint16_t x); + uint16_t readUint16(); + + void writeInt32(int32_t x); + int32_t readInt32(); + + void writeUint32(uint32_t x); + uint32_t readUint32(); + + void writeFloat(float x); + float readFloat(); + + uint8_t transmitSXBuffer(uint8_t startaddr, uint8_t length, uint32_t txtimeout, int8_t txpower, uint8_t wait); + void writeBuffer(uint8_t *txbuffer, uint8_t size); + uint8_t receiveSXBuffer(uint8_t startaddr, uint32_t rxtimeout, uint8_t wait); + uint8_t readBuffer(uint8_t *rxbuffer); + void setupDirect(uint32_t frequency, int32_t offset); + void toneFM(uint16_t frequency, uint32_t length, uint32_t deviation, float adjust, uint8_t txpower); + void setTXDirect(); + uint8_t getByteSXBuffer(uint8_t addr); + void printSXBufferHEX(uint8_t start, uint8_t end); + int32_t getFrequencyErrorHz(); + int32_t getFrequencyErrorRegValue(); + void printHEXByte(uint8_t temp); + uint8_t transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t txtimeout, int8_t txpower, uint8_t wait); + uint8_t readRXPacketType(); + uint8_t readRXDestination(); + uint8_t readRXSource(); + uint8_t receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait); + void clearDeviceErrors(); + void printDeviceErrors(); + void printHEXPacket(uint8_t *buffer, uint8_t size); + void printHEXByte0x(uint8_t temp); + uint8_t readsavedModParam1(); //spreading factor + uint8_t readsavedModParam2(); //bandwidth + uint8_t readsavedModParam3(); //code rate + uint8_t readsavedModParam4(); //optimisation + uint8_t readsavedPower(); + uint8_t getPacketMode(); + uint8_t readsavedPacketParam1(); //preamble + uint8_t readsavedPacketParam2(); //header type + uint8_t readsavedPacketParam3(); //packet length + uint8_t readsavedPacketParam4(); //CRC + uint8_t readsavedPacketParam5(); //IQ + uint8_t getOpmode(); + uint8_t getCRCMode(); + void fillSXBuffer(uint8_t startaddress, uint8_t size, uint8_t character); + uint8_t readPacket(uint8_t *rxbuffer, uint8_t size); + void writeByteSXBuffer(uint8_t addr, uint8_t regdata); + void printSXBufferASCII(uint8_t start, uint8_t end); + void startFSKRTTY(uint32_t freqshift, uint8_t pips, uint16_t pipPeriodmS, uint16_t pipDelaymS, uint16_t leadinmS); + void transmitFSKRTTY(uint8_t chartosend, uint8_t databits, uint8_t stopbits, uint8_t parity, uint16_t baudPerioduS, int8_t pin); + void transmitFSKRTTY(uint8_t chartosend, uint16_t baudPerioduS, int8_t pin); + void printRTTYregisters(); + void endFSKRTTY(); + void getRfFrequencyRegisters(uint8_t *buff); + void setRfFrequencyDirect(uint8_t high, uint8_t midhigh, uint8_t midlow, uint8_t low); + +/*************************************************************************** +//End direct access SX buffer routines +***************************************************************************/ + + uint16_t CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue); + void setSleep(uint8_t sleepconfig); + void wake(); + + private: + + int8_t _NSS, _NRESET, _RFBUSY, _DIO1, _DIO2, _DIO3, _SW; + int8_t _RXEN, _TXEN; + uint8_t _RXPacketL; //length of packet received + uint8_t _RXPacketType; //type number of received packet + uint8_t _RXDestination; //destination address of received packet + uint8_t _RXSource; //source address of received packet + int8_t _PacketRSSI; //RSSI of received packet + int8_t _PacketSNR; //signal to noise ratio of received packet + int8_t _TXPacketL; + uint8_t _RXcount; //used to keep track of the bytes read from SX126X buffer during readFloat() etc + uint8_t _TXcount; //used to keep track of the bytes written to SX126X buffer during writeFloat() etc + uint8_t _RXBufferPointer; //pointer to first byte of packet in buffer + uint8_t _OperatingMode; //current operating mode + bool _rxtxpinmode = false; //set to true if RX and TX enable pin mode is used. + uint8_t _Device; //saved device type + uint8_t _TXDonePin; //the pin that will indicate TX done + uint8_t _RXDonePin; //the pin that will indicate RX done + + uint32_t savedFrequency; + int32_t savedOffset; + uint8_t savedPacketType; + uint8_t savedRegulatorMode; + + uint8_t savedModParam1, savedModParam2, savedModParam3, savedModParam4; + uint16_t savedPacketParam1; + uint8_t savedPacketParam2, savedPacketParam3, savedPacketParam4, savedPacketParam5; + uint16_t savedIrqMask, savedDio1Mask, savedDio2Mask, savedDio3Mask; + int8_t savedTXPower; + + uint32_t savedFrequencyReg; + uint8_t _freqregH, _freqregMH, _freqregML,_freqregL; //the registers values for the set frequency + uint8_t _ShiftfreqregH, _ShiftfreqregMH, _ShiftfreqregML, _ShiftfreqregL; //register values for shifted frequency, used in FSK + +}; +#endif + + + + diff --git a/lib/SX12XX-LoRa/src/SX126XLT_Definitions.h b/lib/SX12XX-LoRa/src/SX126XLT_Definitions.h new file mode 100644 index 0000000..a5f2b1c --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX126XLT_Definitions.h @@ -0,0 +1,305 @@ +/* + Copyright 2019 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + 17/12/19 +*/ + + +#define XTAL_FREQ 32000000 +#define FREQ_DIV 33554432 +#define FREQ_STEP 0.95367431640625 +#define FREQ_ERR 0.47683715820312 +#define FREQ_ERROR_CORRECTION 1.55 //this was measured on SX1280 for bandwidth of 400khz + +#define AUTO_RX_TX_OFFSET 2 + +#define CRC_IBM_SEED 0xFFFF +#define CRC_CCITT_SEED 0x1D0F +#define CRC_POLYNOMIAL_IBM 0x8005 +#define CRC_POLYNOMIAL_CCITT 0x1021 + +//Registers - Used, tested +#define REG_LR_PAYLOADLENGTH 0x0702 +#define REG_IQ_POLARITY_SETUP 0x0736 +#define REG_LR_SYNCWORD 0x0740 +#define REG_RX_GAIN 0x08AC +#define REG_TX_MODULATION 0x0889 +#define REG_RFFrequency31_24 0x088B +#define REG_RFFrequency23_16 0x088C +#define REG_RFFrequency15_8 0x088D +#define REG_RFFrequency7_0 0x088E + +//Registers - Not used, not tested +#define REG_LR_WHITSEEDBASEADDR_MSB 0x06B8 +#define REG_LR_WHITSEEDBASEADDR_LSB 0x06B9 +#define REG_LR_CRCSEEDBASEADDR 0x06BC +#define REG_LR_CRCPOLYBASEADDR 0x06BE +#define REG_LR_PACKETPARAMS 0x0704 +#define REG_LR_SYNCWORDBASEADDRESS 0x06C0 + +#define REG_FREQUENCY_ERRORBASEADDR 0x076B +#define RANDOM_NUMBER_GENERATORBASEADDR 0x0819 +#define REG_OCP 0x08E7 +#define REG_XTA_TRIM 0x0911 + + +#define LORA_MAC_PRIVATE_SYNCWORD 0x1424 +#define LORA_MAC_PUBLIC_SYNCWORD 0x3444 + +#define PRINT_LOW_REGISTER 0x680 +#define PRINT_HIGH_REGISTER 0x920 + + +#define POWER_SAVE_GAIN 0x94 +#define BOOSTED_GAIN 0x96 + + +//radio operatine modes +#define MODE_SLEEP 0x07 +#define MODE_STDBY_RC 0x00 //Device running on RC13M, set STDBY_RC mode +#define MODE_STDBY_XOSC 0x01 //Device running on XTAL 32MHz, set STDBY_XOSC mode +#define MODE_FS 0x02 // The radio is in frequency synthesis mode +#define MODE_TX 0x03 //TX mode +#define MODE_RX 0x04 //RX mode +#define MODE_RX_DC 0x05 //RX duty cycle mode +#define MODE_CAD 0x06 //RX CAD mode + + +//Sleep Mode Definition +#define COLD_START 0x00 +#define WARM_START 0x04 +#define RTC_TIMEOUT_DISABLE 0x00 +#define RTC_TIMEOUT_ENABLE 0x01 + +#define USE_LDO 0x00 //default +#define USE_DCDC 0x01 + +#define PACKET_TYPE_GFSK 0x00 +#define PACKET_TYPE_LORA 0x01 +#define PACKET_TYPE_NONE 0x0F + + +#define RADIO_RAMP_10_US 0x00 +#define RADIO_RAMP_20_US 0x01 +#define RADIO_RAMP_40_US 0x02 +#define RADIO_RAMP_80_US 0x03 +#define RADIO_RAMP_200_US 0x04 +#define RADIO_RAMP_800_US 0x05 +#define RADIO_RAMP_1700_US 0x06 +#define RADIO_RAMP_3400_US 0x07 + +#define LORA_CAD_01_SYMBOL 0x00 +#define LORA_CAD_02_SYMBOL 0x01 +#define LORA_CAD_04_SYMBOL 0x02 +#define LORA_CAD_08_SYMBOL 0x03 +#define LORA_CAD_16_SYMBOL 0x04 + +#define LORA_CAD_ONLY 0x00 +#define LORA_CAD_RX 0x01 +#define LORA_CAD_LBT 0x10 + +#define LORA_SF5 0x05 +#define LORA_SF6 0x06 +#define LORA_SF7 0x07 +#define LORA_SF8 0x08 +#define LORA_SF9 0x09 +#define LORA_SF10 0x0A +#define LORA_SF11 0x0B +#define LORA_SF12 0x0C + +#define LORA_BW_500 6 //actual 500000hz +#define LORA_BW_250 5 //actual 250000hz +#define LORA_BW_125 4 //actual 125000hz +#define LORA_BW_062 3 //actual 62500hz +#define LORA_BW_041 10 //actual 41670hz +#define LORA_BW_031 2 //actual 31250hz +#define LORA_BW_020 9 //actual 20830hz +#define LORA_BW_015 1 //actual 15630hz +#define LORA_BW_010 8 //actual 10420hz +#define LORA_BW_007 0 //actual 7810hz + +#define LORA_CR_4_5 0x01 +#define LORA_CR_4_6 0x02 +#define LORA_CR_4_7 0x03 +#define LORA_CR_4_8 0x04 + +#define WAIT_RX 0x01 +#define WAIT_TX 0x01 +#define NO_WAIT 0x00 + +#define RADIO_PREAMBLE_DETECTOR_OFF 0x00 //!< Preamble detection length off +#define RADIO_PREAMBLE_DETECTOR_08_BITS 0x04 //!< Preamble detection length 8 bits +#define RADIO_PREAMBLE_DETECTOR_16_BITS 0x05 //!< Preamble detection length 16 bits +#define RADIO_PREAMBLE_DETECTOR_24_BITS 0x06 //!< Preamble detection length 24 bits +#define RADIO_PREAMBLE_DETECTOR_32_BITS 0x07 //!< Preamble detection length 32 bit + +#define RADIO_ADDRESSCOMP_FILT_OFF 0x00 //!< No correlator turned on i.e. do not search for SyncWord +#define RADIO_ADDRESSCOMP_FILT_NODE 0x01 +#define RADIO_ADDRESSCOMP_FILT_NODE_BROAD 0x02 + +#define RADIO_PACKET_FIXED_LENGTH 0x00 //!< The packet is known on both sides no header included in the packet +#define RADIO_PACKET_VARIABLE_LENGTH 0x01 //!< The packet is on variable size header included + +#define RADIO_CRC_OFF 0x01 //!< No CRC in use +#define RADIO_CRC_1_BYTES 0x00 +#define RADIO_CRC_2_BYTES 0x02 +#define RADIO_CRC_1_BYTES_INV 0x04 +#define RADIO_CRC_2_BYTES_INV 0x06 +#define RADIO_CRC_2_BYTES_IBM 0xF1 +#define RADIO_CRC_2_BYTES_CCIT 0xF2 + +#define RADIO_DC_FREE_OFF 0x00 +#define RADIO_DC_FREEWHITENING 0x01 + +#define LORA_PACKET_VARIABLE_LENGTH 0x00 //!< The packet is on variable size header included +#define LORA_PACKET_FIXED_LENGTH 0x01 //!< The packet is known on both sides no header included in the packet +#define LORA_PACKET_EXPLICIT LORA_PACKET_VARIABLE_LENGTH +#define LORA_PACKET_IMPLICIT LORA_PACKET_FIXED_LENGTH + + +#define LORA_CRC_ON 0x01 //!< CRC activated +#define LORA_CRC_OFF 0x00 //!< CRC not used + +#define LORA_IQ_NORMAL 0x00 +#define LORA_IQ_INVERTED 0x01 + +#define TCXO_CTRL_1_6V 0x00 +#define TCXO_CTRL_1_7V 0x01 +#define TCXO_CTRL_1_8V 0x02 +#define TCXO_CTRL_2_2V 0x03 +#define TCXO_CTRL_2_4V 0x04 +#define TCXO_CTRL_2_7V 0x05 +#define TCXO_CTRL_3_0V 0x06 +#define TCXO_CTRL_3_3V 0x07 + +#define IRQ_RADIO_NONE 0x0000 +#define IRQ_TX_DONE 0x0001 +#define IRQ_RX_DONE 0x0002 +#define IRQ_PREAMBLE_DETECTED 0x0004 +#define IRQ_SYNCWORD_VALID 0x0008 +#define IRQ_HEADER_VALID 0x0010 +#define IRQ_HEADER_ERROR 0x0020 +#define IRQ_CRC_ERROR 0x0040 +#define IRQ_CAD_DONE 0x0080 +#define IRQ_CAD_ACTIVITY_DETECTED 0x0100 +#define IRQ_RX_TX_TIMEOUT 0x0200 +#define IRQ_TX_TIMEOUT 0x0200 +#define IRQ_RX_TIMEOUT 0x0200 +#define IRQ_RADIO_ALL 0xFFFF + +#define RADIO_GET_STATUS 0xC0 +#define RADIO_WRITE_REGISTER 0x0D +#define RADIO_READ_REGISTER 0x1D +#define RADIO_WRITE_BUFFER 0x0E +#define RADIO_READ_BUFFER 0x1E +#define RADIO_SET_SLEEP 0x84 +#define RADIO_SET_STANDBY 0x80 +#define RADIO_SET_FS 0xC1 +#define RADIO_SET_TX 0x83 +#define RADIO_SET_RX 0x82 +#define RADIO_SET_RXDUTYCYCLE 0x94 +#define RADIO_SET_CAD 0xC5 +#define RADIO_SET_TXCONTINUOUSWAVE 0xD1 +#define RADIO_SET_TXCONTINUOUSPREAMBLE 0xD2 +#define RADIO_SET_PACKETTYPE 0x8A +#define RADIO_GET_PACKETTYPE 0x11 +#define RADIO_SET_RFFREQUENCY 0x86 +#define RADIO_SET_TXPARAMS 0x8E +#define RADIO_SET_PACONFIG 0x95 +#define RADIO_SET_CADPARAMS 0x88 +#define RADIO_SET_BUFFERBASEADDRESS 0x8F +#define RADIO_SET_MODULATIONPARAMS 0x8B +#define RADIO_SET_PACKETPARAMS 0x8C +#define RADIO_GET_RXBUFFERSTATUS 0x13 +#define RADIO_GET_PACKETSTATUS 0x14 +#define RADIO_GET_RSSIINST 0x15 +#define RADIO_GET_STATS 0x10 +#define RADIO_RESET_STATS 0x00 +#define RADIO_CFG_DIOIRQ 0x08 +#define RADIO_GET_IRQSTATUS 0x12 +#define RADIO_CLR_IRQSTATUS 0x02 +#define RADIO_CALIBRATE 0x89 +#define RADIO_CALIBRATEIMAGE 0x98 +#define RADIO_SET_REGULATORMODE 0x96 +#define RADIO_GET_ERROR 0x17 +#define RADIO_CLEAR_ERRORS 0x07 +#define RADIO_SET_TCXOMODE 0x97 +#define RADIO_SET_TXFALLBACKMODE 0x93 +#define RADIO_SET_RFSWITCHMODE 0x9D +#define RADIO_SET_STOPRXTIMERONPREAMBLE 0x9F +#define RADIO_SET_LORASYMBTIMEOUT 0xA0 + + +//Table 13-2 SX126X Sleep modes +#define CONFIGURATION_RETENTION 0x04 +#define RTC_TIMEOUT_ENABLE 0x01 + + +#define LDRO_OFF 0x00 +#define LDRO_ON 0x01 +#define LDRO_AUTO 0x02 //when used causes LDRO to be automatically calculated + +#define DEVICE_SX1261 0x01 +#define DEVICE_SX1262 0x00 +#define DEVICE_SX1268 0x02 + +#define PAAUTO 0xFF +#define HPMAXAUTO 0xFF + +#ifndef RAMP_TIME +#define RAMP_TIME RADIO_RAMP_40_US +#endif + +#define RC64KEnable 0x01 //calibrate RC64K clock +#define RC13MEnable 0x02 //calibrate RC13M clock +#define PLLEnable 0x04 //calibrate PLL +#define ADCPulseEnable 0x08 //calibrate ADC Pulse +#define ADCBulkNEnable 0x10 //calibrate ADC bulkN +#define ADCBulkPEnable 0x20 //calibrate ADC bulkP +#define ImgEnable 0x40 //calibrate image +#define ALLDevices 0x7F //calibrate all devices + +#define RC64K_CALIB_ERR 0x0001 +#define RC13M_CALIB_ERR 0x0002 +#define PLL_CALIB_ERR 0x0004 +#define ADC_CALIB_ERR 0x0008 +#define IMG_CALIB_ERR 0x0010 +#define XOSC_START_ERR 0x0020 +#define PLL_LOCK_ERR 0x0040 +#define RFU 0x0080 +#define PA_RAMP_ERR 0x0100 + + +//SPI settings +#define LTspeedMaximum 8000000 +#define LTdataOrder MSBFIRST +#define LTdataMode SPI_MODE0 + +//FSKRTTY Settings +#define ParityNone 0 +#define ParityOdd 1 +#define ParityEven 2 +#define ParityZero 0xF0 +#define ParityOne 0xF1 + +#define ToneMinuS 52 //timed constant for ATmega328P at 8Mhz with FM Tone delayus at 0, period for half loop + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/lib/SX12XX-LoRa/src/SX127XLT.cpp b/lib/SX12XX-LoRa/src/SX127XLT.cpp new file mode 100644 index 0000000..6de9cad --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX127XLT.cpp @@ -0,0 +1,4272 @@ +/* + Copyright 2019 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 17/12/19 + New version 23/12/20 +*/ + +/* + Parts of code Copyright (c) 2013, SEMTECH S.A. + See LICENSE.TXT file included in the library +*/ + +#include +#include + +#define LTUNUSED(v) (void) (v) //add LTUNUSED(variable); in functions to avoid compiler warnings +#define USE_SPI_TRANSACTION //this is the standard behaviour of library, use SPI Transaction switching + +//#define SX127XDEBUG1 //enable level 1 debug messages +//#define SX127XDEBUG2 //enable level 2 debug messages +//#define SX127XDEBUG3 //enable level 3 debug messages +//#define DEBUGPHANTOM //used to set bebuging for Phantom packets +//#define SX127XDEBUGPINS //enable pin allocation debug messages +//#define DEBUGFSKRTTY //enable for FSKRTTY debugging +//#define SX127XDEBUGRELIABLE +//#define PACONFIGDEBUG +//#define APPLYERRATANOTE_2_3 //if enabled the changes suggested in SX1276_77_8_ErrataNote_1_1 are applied + + +SX127XLT::SX127XLT() +{ + +} + +/* Formats for :begin + 1 original > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device); + 2 Simplified > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, uint8_t device); + 3 Bare minimum, no NRESET or DIO0 pins > begin(int8_t pinNSS, uint8_t device); +*/ + + +bool SX127XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device) +{ + //format 1 pins, assign the all available pins +#ifdef SX127XDEBUG1 + Serial.println(F("1 begin() ")); +#endif + + //assign the passed pins to the class private variabled + _NSS = pinNSS; + _NRESET = pinNRESET; + _DIO0 = pinDIO0; + _DIO1 = pinDIO1; + _DIO2 = pinDIO2; + _Device = device; //device type needs to be assigned before reset + _TXDonePin = pinDIO0; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO0; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + + if (_DIO0 >= 0) + { + pinMode( _DIO0, INPUT); + } + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + if (_DIO2 >= 0) + { + pinMode( _DIO2, INPUT); + } + + resetDevice(); + +#ifdef SX127XDEBUGPINS + Serial.println(F("1 begin()")); + Serial.println(F("SX127XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("DIO0 ")); + Serial.println(_DIO0); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); +#endif + + if (checkDevice()) +{ + return true; +} + +return false; +} + + + +bool SX127XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, uint8_t device) +{ + //format 2 pins, simplified +#ifdef SX127XDEBUG1 + Serial.println(F("2 begin() ")); +#endif + + //assign the passed pins to the class private variabled + _NSS = pinNSS; + _NRESET = pinNRESET; + _DIO0 = pinDIO0; + _DIO1 = -1; //pin not used + _DIO2 = -1; //pin not used + _Device = device; //device type needs to be assigned before reset + _TXDonePin = pinDIO0; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO0; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, HIGH); + + if (_DIO0 >= 0) + { + pinMode( _DIO0, INPUT); + } + + resetDevice(); + + +#ifdef SX127XDEBUGPINS + Serial.println(F("format 2 begin() ")); + Serial.println(F("SX127XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("DIO0 ")); + Serial.println(_DIO0); +#endif + + if (checkDevice()) +{ + return true; +} + +return false; +} + + +bool SX127XLT::begin(int8_t pinNSS, uint8_t device) +{ + //format 3 pins, assign the all available pins +#ifdef SX127XDEBUG1 + Serial.println(F("3 begin() ")); +#endif + + //assign the passed pins to the class private variabled + _NSS = pinNSS; + _Device = device; //device type needs to be assigned before reset + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + + +#ifdef SX127XDEBUGPINS + Serial.println(F("2 begin()")); + Serial.println(F("SX127XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); +#endif + + if (checkDevice()) +{ + return true; +} + +return false; +} + + +void SX127XLT::resetDevice() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("resetDevice() ")); +#endif + + if (_Device == DEVICE_SX1272) + { + digitalWrite(_NRESET, HIGH); + delay(2); + digitalWrite(_NRESET, LOW); + delay(20); + } + else + { + digitalWrite(_NRESET, LOW); + delay(2); + digitalWrite(_NRESET, HIGH); + delay(20); + } +} + + +void SX127XLT::setMode(uint8_t modeconfig) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setMode() ")); +#endif + + uint8_t regdata; + + regdata = modeconfig + _PACKET_TYPE; + writeRegister(REG_OPMODE, regdata); +} + + +void SX127XLT::setSleep(uint8_t sleepconfig) +{ + //settings passed via sleepconfig are ignored, feature retained for compatibility with SX128x,SX126x + +#ifdef SX127XDEBUG1 + Serial.println(F("setSleep() ")); +#endif + + LTUNUSED(sleepconfig); + + uint8_t regdata; + + regdata = readRegister(REG_OPMODE); + writeRegister(REG_OPMODE, (regdata & 0xF8)); //clear bits 0,1,2 to set sleepmode + delay(1); //allow time for shutdown +} + + +bool SX127XLT::checkDevice() +{ + //check there is a device out there, writes a register and reads back + +#ifdef SX127XDEBUG1 + Serial.println(F("checkDevice() ")); +#endif + + uint8_t Regdata1, Regdata2; + Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting + writeRegister(REG_FRMID, (Regdata1 + 1)); + Regdata2 = readRegister(REG_FRMID); //read changed value back + writeRegister(REG_FRMID, Regdata1); //restore register to original value + + if (Regdata2 == (Regdata1 + 1)) + { + return true; + } + else + { + return false; + } +} + + +void SX127XLT::wake() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("wake() ")); +#endif + uint8_t regdata; + + regdata = readRegister(REG_OPMODE); + writeRegister(REG_OPMODE, (regdata | 0x01)); //set bit 0 to goto stdby mode +} + + +void SX127XLT::calibrateImage(uint8_t null) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("calibrateImage() ")); +#endif + + LTUNUSED(null); + + uint8_t regdata, savedmode; + savedmode = readRegister(REG_OPMODE); + writeRegister(REG_OPMODE, 0x00); //sleep + writeRegister(REG_OPMODE, 0x00); //sleep + writeRegister(REG_OPMODE, 0x01); //standby FSK mode + regdata = (readRegister(REG_IMAGECAL) | 0x40); + writeRegister(REG_IMAGECAL, regdata); //start calibration + delay(15); //calibration time 10mS + writeRegister(REG_OPMODE, 0x00); //sleep + writeRegister(REG_OPMODE, savedmode & 0xFE); + writeRegister(REG_OPMODE, savedmode); +} + + +void SX127XLT::printRegister(uint8_t reg) +{ +uint8_t regdata; + + Serial.print(F("Register 0x")); + + if (reg < 0x10) + { + Serial.print(F("0")); + } + + Serial.print(reg,HEX); + regdata = readRegister(reg); + Serial.print(F(" 0x")); + + if (regdata < 0x10) + { + Serial.print(F("0")); + } + + Serial.print(regdata,HEX); +} + + +uint16_t SX127XLT::CRCCCITT(uint8_t *buffer, uint16_t size, uint16_t startvalue) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("CRCCCITT() ")); +#endif + + uint16_t index, libraryCRC; + uint8_t j; + + libraryCRC = startvalue; //start value for CRC16 + + for (index = 0; index < size; index++) + { + libraryCRC ^= (((uint16_t)buffer[index]) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + + return libraryCRC; +} + + +uint16_t SX127XLT::CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue) +{ + //genrates a CRC of an area of the internal SX buffer + +#ifdef SX127XDEBUG1 + Serial.println(F("CRCCCITTSX() ")); +#endif + + + uint16_t index, libraryCRC; + uint8_t j; + + libraryCRC = startvalue; //start value for CRC16 + + startReadSXBuffer(startadd); //begin the buffer read + + for (index = startadd; index <= endadd; index++) + { + libraryCRC ^= (((uint16_t) readUint8() ) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + + endReadSXBuffer(); //end the buffer read + + return libraryCRC; +} + + +void SX127XLT::setDevice(uint8_t type) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setDevice() ")); +#endif + + _Device = type; +} + + +void SX127XLT::printDevice() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printDevice() ")); +#endif + + switch (_Device) + { + case DEVICE_SX1272_PABOOST: + Serial.print(F("SX1272_PABOOST")); + break; + + case DEVICE_SX1276_PABOOST: + Serial.print(F("SX1276_PABOOST")); + break; + + case DEVICE_SX1277_PABOOST: + Serial.print(F("SX1277_PABOOST")); + break; + + case DEVICE_SX1278_PABOOST: + Serial.print(F("SX1278_PABOOST")); + break; + + case DEVICE_SX1279_PABOOST: + Serial.print(F("SX1279_PABOOST")); + break; + + case DEVICE_SX1276_RFO: + Serial.print(F("SX1276_RFO")); + break; + + case DEVICE_SX1277_RFO: + Serial.print(F("SX1277_RFO")); + break; + + case DEVICE_SX1278_RFO: + Serial.print(F("SX1278_RFO")); + break; + + case DEVICE_SX1279_RFO: + Serial.print(F("SX1279_RFO")); + break; + + default: + Serial.print(F("Unknown Device")); + } +} + + +uint8_t SX127XLT::getOperatingMode() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getOperatingMode() ")); +#endif + + return readRegister(REG_OPMODE); +} + + +bool SX127XLT::isReceiveDone() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("isReceiveDone()")); +#endif + + return digitalRead(_RXDonePin); +} + + +bool SX127XLT::isTransmitDone() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("isTransmitDone() ")); +#endif + + return digitalRead(_TXDonePin); +} + + +void SX127XLT::writeRegister(uint8_t address, uint8_t value) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeRegister() ")); +#endif + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(address | 0x80); //mask address for write + SPI.transfer(value); //write the byte + digitalWrite(_NSS, HIGH); //set NSS high + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +#ifdef SX127XDEBUG2 + Serial.print(F("Write register ")); + printHEXByte0x(address); + Serial.print(F(" ")); + printHEXByte0x(value); + Serial.println(); + Serial.flush(); +#endif +} + + +uint8_t SX127XLT::readRegister(uint8_t address) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readRegister() ")); +#endif + + uint8_t regdata; + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(address & 0x7F); //mask address for read + regdata = SPI.transfer(0); //read the byte + digitalWrite(_NSS, HIGH); //set NSS high + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +#ifdef SX127XDEBUG2 + Serial.print(F("Read register ")); + printHEXByte0x(address); + Serial.print(F(" ")); + printHEXByte0x(regdata); + Serial.println(); + Serial.flush(); +#endif + + return regdata; +} + + +void SX127XLT::printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of SX127x registers to serial monitor + +#ifdef SX127XDEBUG + Serial.println(F("printRegisters() ")); +#endif + + 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(); + } +} + + +void SX127XLT::printOperatingMode() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printOperatingMode() ")); +#endif + + uint8_t regdata; + + regdata = getOpmode(); + + switch (regdata) + { + case 0: + Serial.print(F("SLEEP")); + break; + + case 1: + Serial.print(F("STDBY")); + break; + + case 2: + Serial.print(F("FSTX")); + break; + + case 3: + Serial.print(F("TX")); + break; + + case 4: + Serial.print(F("FSRX")); + break; + + case 5: + Serial.print(F("RXCONTINUOUS")); + break; + + case 6: + Serial.print(F("RXSINGLE")); + break; + + case 7: + Serial.print(F("CAD")); + break; + + default: + Serial.print(F("NOIDEA")); + break; + } +} + + +void SX127XLT::printOperatingSettings() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printOperatingSettings() ")); +#endif + + printDevice(); + Serial.print(F(",")); + + printOperatingMode(); + + Serial.print(F(",Version_")); + Serial.print(getVersion(), HEX); + + Serial.print(F(",PacketMode_")); + + if (getPacketMode()) + { + Serial.print(F("LoRa")); + } + else + { + Serial.print(F("FSK")); + } + + if (getHeaderMode()) + { + Serial.print(F(",Implicit")); + } + else + { + Serial.print(F(",Explicit")); + } + + Serial.print(F(",CRC_")); + if (getCRCMode()) + { + Serial.print(F("On")); + } + else + { + Serial.print(F("Off")); + } + + + Serial.print(F(",AGCauto_")); + if (getAGC()) + { + Serial.print(F("On")); + } + else + { + Serial.print(F("Off")); + } + + Serial.print(F(",LNAgain_")); + Serial.print(getLNAgain()); + + if (!bitRead(_Device,4)) //if bit 4 of _Device is 0 then either RFO LF_ANT or HF_ANT pin used for RF output + { + Serial.print(F(",LNAboostHF_")); + if (getLNAboostHF()) + { + Serial.print(F("On")); + } + else + { + Serial.print(F("Off")); + } + + Serial.print(F(",LNAboostLF_")); + if (getLNAboostLF()) + { + Serial.print(F("Reserved")); + } + else + { + Serial.print(F("Default")); + } + } +} + + +void SX127XLT::setTxParams(int8_t txPower, uint8_t rampTime) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setTxParams() ")); +#endif + uint8_t MaxPower, OutputPower, OcpTrim, boostval; + + if (_Device & 0x10) + { + //start setTxParams() for PABOOST + + #ifdef PACONFIGDEBUG + Serial.print(F(" PABOOST Device ")); + #endif + + boostval = PABOOSTON; + MaxPower = MAXPOWER17dBm; + + if (txPower > 20) //upper power limit for + { + txPower = 20; + } + + if (txPower < 2) + { + txPower = 2; + } + + if (txPower > 17) + { + writeRegister(REG_PADAC, 0x87); //Reg 0x4D this is same for SX1272 and SX1278 + OutputPower = txPower - 5; //power range is 15dBm, max is now 20dBm min is 5dBm + } + else + { + writeRegister(REG_PADAC, 0x84); //Reg 0x4D this is same for SX1272 and SX1278 + OutputPower = txPower - 2; //power range is 15dBm, max is 17dBm min is 2dBm + } + + if (_Device == DEVICE_SX1272_PABOOST) //power calculation for SX1272 is the same for < 17dbm and > 17dBm + { + OutputPower = txPower - 2; + } + + //end setTxParams() for PABOOST + } + else + { + //start setTxParams() for RFO + + #ifdef PACONFIGDEBUG + Serial.print(F(" RFO Device ")); + #endif + + boostval = PABOOSTOFF; + MaxPower = MAXPOWER14dBm; + + if (txPower > 14) //14dBm is upper power limit for RFO + { + txPower = 14; + } + + if (txPower < 0) + { + txPower = 0; + } + + OutputPower = txPower + 1; //power range is 15dBm, max is 14dBm min is 0dBm + writeRegister(REG_PADAC, 0x84); //must turn off high power setting for RFO mode + + //end setTxParams() for RFO + } + + //common routines for PABOOST and RFO + OcpTrim = OCP_TRIM_110MA; //value for OcpTrim 11dBm to 16dBm + + if (txPower >= 17) + { + OcpTrim = OCP_TRIM_150MA; + } + + if (txPower <= 10) + { + OcpTrim = OCP_TRIM_80MA; + } + + writeRegister(REG_PARAMP, rampTime); + writeRegister(REG_OCP, (OcpTrim+0x20)); + writeRegister(REG_PACONFIG, (boostval + MaxPower + OutputPower)); //MaxPower does not care for SX1272 + +#ifdef PACONFIGDEBUG + Serial.print(F("txPower,")); + Serial.print(txPower); + Serial.print(F(",REG_PACONFIG,")); + Serial.print(readRegister(REG_PACONFIG),HEX); + Serial.print(F(",PABOOST,")); + + if (readRegister(REG_PACONFIG) & 0x80) + { + Serial.print(F("ON,")); + } + else + { + Serial.print(F("OFF,")); + } + + Serial.print(F("MaxPower,")); + Serial.print(MaxPower,HEX); + Serial.print(F(",OutputPower,")); + Serial.print(OutputPower,HEX); + Serial.print(F(",")); + printOCPTRIM(); + #endif +} + + +void SX127XLT::printOCPTRIM() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printOCPTRIM() ")); +#endif + +uint8_t regdata; +regdata = readRegister(REG_OCP); + +Serial.print(F("REG_OCP,")); +Serial.print(regdata,HEX); +Serial.print(F(",")); + +if (!(regdata & 0x20)) +{ +Serial.print(F("OCP_TRIM_OFF ")); +return; +} + +//OCP must be on, so print trim value + +regdata = regdata & 0x1F; //mask off trim value + +switch (regdata) +{ +case OCP_TRIM_45MA: + Serial.print(F("OCP_TRIM_45MA ")); + break; + +case OCP_TRIM_80MA: + Serial.print(F("OCP_TRIM_80MA ")); + break; + +case OCP_TRIM_100MA: + Serial.print(F("OCP_TRIM_100MA ")); + break; + +case OCP_TRIM_110MA: + Serial.print(F("OCP_TRIM_110MA ")); + break; + +case OCP_TRIM_120MA: + Serial.print(F("OCP_TRIM_120MA ")); + break; + +case OCP_TRIM_130MA: + Serial.print(F("OCP_TRIM_130MA ")); + break; + +case OCP_TRIM_140MA: + Serial.print(F("OCP_TRIM_140MA ")); + break; + +case OCP_TRIM_150MA: + Serial.print(F("OCP_TRIM_150MA ")); + break; +} + +return; +} + + +void SX127XLT::setPacketParams(uint16_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5) +{ + //format is PreambleLength, Fixed\Variable length packets, Packetlength, CRC mode, IQ mode + +#ifdef SX127XDEBUG1 + Serial.println(F("SetPacketParams() ")); +#endif + + uint8_t preambleMSB, preambleLSB, regdata; + + + //******************************************************* + //These changes are the same for SX1272 and SX127X + //PreambleLength reg 0x20, 0x21 + preambleMSB = packetParam1 >> 8; + preambleLSB = packetParam1 & 0xFF; + writeRegister(REG_PREAMBLEMSB, preambleMSB); + writeRegister(REG_PREAMBLELSB, preambleLSB); + + //TX Packetlength reg 0x22 + writeRegister(REG_PAYLOADLENGTH, packetParam3); //when in implicit mode, this is used as receive length also + + //IQ mode reg 0x33 and 0x3B + if (packetParam5 == LORA_IQ_INVERTED) + { + writeRegister(REG_INVERTIQ, 0x66); + writeRegister(REG_INVERTIQ2, 0x19); + } + + if (packetParam5 == LORA_IQ_NORMAL) + { + writeRegister(REG_INVERTIQ, 0x27); + writeRegister(REG_INVERTIQ2, 0x1d); + } + + //regdata = ( (readRegister(REG_INVERTIQ)) & 0xBE ); //mask off invertIQ bit 6 and bit 0 + //writeRegister(REG_INVERTIQ, (regdata + packetParam5)); + //******************************************************* + + + //CRC mode + _UseCRC = packetParam4; //save CRC use status + + if (_Device != DEVICE_SX1272) + { + //for all devices apart from SX1272 + //Fixed\Variable length packets + regdata = ( (readRegister(REG_MODEMCONFIG1)) & (~READ_IMPLCIT_AND_X)); //mask off bit 0 + writeRegister(REG_MODEMCONFIG1, (regdata + packetParam2)); //write out with bit 0 set appropriatly + + //CRC on payload + regdata = ( (readRegister(REG_MODEMCONFIG2)) & (~READ_HASCRC_AND_X)); //mask off all bits bar CRC on - bit 2 + writeRegister(REG_MODEMCONFIG2, (regdata + (packetParam4 << 2))); //write out with CRC bit 2 set appropriatly + } + else + { + //for SX1272 + //Fixed\Variable length packets + regdata = ( (readRegister(REG_MODEMCONFIG1)) & (~READ_IMPLCIT_AND_2)); //mask off bit 2 + writeRegister(REG_MODEMCONFIG1, (regdata + (packetParam2 << 2))); //write out with bit 2 set appropriatly + + //CRC on payload + regdata = ( (readRegister(REG_MODEMCONFIG1)) & (~READ_HASCRC_AND_2)); //mask of all bits bar CRC on - bit 1 + writeRegister(REG_MODEMCONFIG1, (regdata + (packetParam4 << 1))); //write out with CRC bit 1 set appropriatly + } +} + + +void SX127XLT::setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4) +{ + //order is SpreadingFactor, Bandwidth, CodeRate, Optimisation + +#ifdef SX127XDEBUG1 + Serial.println(F("setModulationParams() ")); +#endif + + uint8_t regdata, bw; + + //Spreading factor - same for SX1272 and SX127X - reg 0x1D + regdata = (readRegister(REG_MODEMCONFIG2) & (~READ_SF_AND_X)); + writeRegister(REG_MODEMCONFIG2, (regdata + (modParam1 << 4))); + + if (_Device != DEVICE_SX1272) + { + //for all devices apart from SX1272 + + //bandwidth + regdata = (readRegister(REG_MODEMCONFIG1) & (~READ_BW_AND_X)); + writeRegister(REG_MODEMCONFIG1, (regdata + modParam2)); + + //Coding rate + regdata = (readRegister(REG_MODEMCONFIG1) & (~READ_CR_AND_X)); + writeRegister(REG_MODEMCONFIG1, (regdata + (modParam3))); + + //Optimisation + if (modParam4 == LDRO_AUTO) + { + modParam4 = returnOptimisation(modParam2, modParam1); + } + + regdata = (readRegister(REG_MODEMCONFIG3) & (~READ_LDRO_AND_X)); + writeRegister(REG_MODEMCONFIG3, (regdata + (modParam4 << 3))); + + } + else + { + + //for SX1272 + regdata = (readRegister(REG_MODEMCONFIG1) & (~READ_BW_AND_2)); //value will be LORA_BW_500 128, LORA_BW_250 64, LORA_BW_125 0 + + switch (modParam2) + { + case LORA_BW_125: + bw = 0x00; + break; + + case LORA_BW_500: + bw = 0x80; + break; + + case LORA_BW_250: + bw = 0x40; + break; + + default: + bw = 0x00; //defaults to LORA_BW_125 + } + + writeRegister(REG_MODEMCONFIG1, (regdata + bw)); + + //Coding rate + regdata = (readRegister(REG_MODEMCONFIG1) & (~READ_CR_AND_2)); + writeRegister(REG_MODEMCONFIG1, (regdata + (modParam3 << 2))); + + //Optimisation + if (modParam4 == LDRO_AUTO) + { + modParam4 = returnOptimisation(modParam2, modParam1); + } + + regdata = (readRegister(REG_MODEMCONFIG1) & (~READ_LDRO_AND_2)); + writeRegister(REG_MODEMCONFIG1, (regdata + modParam4)); + + } + + #ifdef APPLYERRATANOTE_2_3 + //optimisations called by SX1276_77_8_ErrataNote_1_1 + + //ERRATA 2.3 - Receiver Spurious Reception of a LoRa Signal + if( modParam2 < LORA_BW_500 ) + { + writeRegister( REG_DETECTOPTIMIZE, readRegister(REG_DETECTOPTIMIZE) & 0x7F ); + writeRegister( REG_LRTEST30, 0x00 ); + + switch(modParam2) + { + case LORA_BW_007: // 7.8 kHz + writeRegister(REG_LRTEST2F,0x48); + _savedOffset = _savedOffset + 7800; + break; + case LORA_BW_010: // 10.4 kHz + writeRegister(REG_LRTEST2F,0x44); + _savedOffset = _savedOffset + 10400; + break; + case LORA_BW_015: // 15.6 kHz + writeRegister(REG_LRTEST2F,0x44); + _savedOffset = _savedOffset + 15600; + break; + case LORA_BW_020: // 20.8 kHz + writeRegister(REG_LRTEST2F,0x44); + _savedOffset = _savedOffset + 20800; + break; + case LORA_BW_031: // 31.2 kHz + writeRegister(REG_LRTEST2F,0x44); + _savedOffset = _savedOffset + 31200; + break; + case LORA_BW_041: // 41.4 kHz + writeRegister(REG_LRTEST2F, 0x44 ); + _savedOffset = _savedOffset + 41400; + break; + case LORA_BW_062: // 62.5 kHz + writeRegister(REG_LRTEST2F,0x40); + break; + case LORA_BW_125: // 125 kHz + writeRegister(REG_LRTEST2F,0x40); + break; + case LORA_BW_250: // 250 kHz + writeRegister(REG_LRTEST2F,0x40); + break; + } + } + else + { + writeRegister(REG_DETECTOPTIMIZE, readRegister(REG_DETECTOPTIMIZE ) | 0x80 ); + } + + + setRfFrequency(_savedFrequency,_savedOffset); //apply the updated frequency +#endif + + //ERRATA 2.1 - SX1276_77_8_ErrataNote_1_1 + if( ( modParam2 == LORA_BW_500 ) && ( _savedFrequency >= 862000000 ) ) + { + //ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth >= 862Mhz + writeRegister(REG_HIGHBWOPTIMIZE1,0x02); + writeRegister(REG_HIGHBWOPTIMIZE2,0x64); + } + else if( modParam2 == LORA_BW_500 ) + { + //ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth 410Mhz to 525Mhz + writeRegister(REG_HIGHBWOPTIMIZE1,0x02); + writeRegister(REG_HIGHBWOPTIMIZE2,0x7F); + } + else + { + // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth + writeRegister(REG_HIGHBWOPTIMIZE1,0x03); + } + + +//Datasheet SX1276-7-8-9_May_2020, page 115, REG_DETECTOPTIMIZE = 0x31, REG_LRDETECTIONTHRESHOLD = 0x37 + if( modParam1 == LORA_SF6 ) + { + writeRegister(REG_DETECTOPTIMIZE, ( readRegister( REG_DETECTOPTIMIZE ) & 0xF8 ) | 0x05 ); + writeRegister(REG_DETECTIONTHRESHOLD, 0x0C); + } + else + { + writeRegister( REG_DETECTOPTIMIZE, ( readRegister( REG_DETECTOPTIMIZE ) & 0xF8 ) | 0x03 ); + writeRegister( REG_DETECTIONTHRESHOLD, 0x0A ); + } +} + + +void SX127XLT::setRfFrequency(uint64_t freq64, int32_t offset) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setRfFrequency() ")); +#endif + + _savedFrequency = freq64; + _savedOffset = offset; + + freq64 = freq64 + offset; + freq64 = ((uint64_t)freq64 << 19) / 32000000; + _freqregH = freq64 >> 16; + _freqregM = freq64 >> 8; + _freqregL = freq64; + + writeRegister(REG_FRMSB, _freqregH); + writeRegister(REG_FRMID, _freqregM); + writeRegister(REG_FRLSB, _freqregL); +} + + +uint32_t SX127XLT::getFreqInt() +{ + //get the current set LoRa device frequency, return as long integer +#ifdef SX127XDEBUG1 + Serial.println(F("getFreqInt() ")); +#endif + + uint8_t Msb, Mid, Lsb; + uint32_t uinttemp; + float floattemp; + Msb = readRegister(REG_FRMSB); + Mid = readRegister(REG_FRMID); + Lsb = readRegister(REG_FRLSB); + floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb); + floattemp = ((floattemp * 61.03515625) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +int32_t SX127XLT::getFrequencyErrorRegValue() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getFrequencyErrorRegValue() ")); +#endif + + int32_t FrequencyError; + uint32_t msb, mid, lsb; + uint32_t allreg; + + setMode(MODE_STDBY_RC); + + msb = readRegister(REG_FEIMSB); + mid = readRegister(REG_FEIMID); + lsb = readRegister(REG_FEILSB); + +#ifdef SX127XDEBUG1 + Serial.println(); + Serial.print(F("Registers ")); + Serial.print(msb, HEX); + Serial.print(F(" ")); + Serial.print(mid, HEX); + Serial.print(F(" ")); + Serial.println(lsb, HEX); +#endif + + allreg = (uint32_t) ( msb << 16 ) | ( mid << 8 ) | lsb; + + if (allreg & 0x80000) + { + FrequencyError = (0xFFFFF - allreg) * -1; + } + else + { + FrequencyError = allreg; + } + + return FrequencyError; +} + + +int32_t SX127XLT::getFrequencyErrorHz() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getFrequencyErrorHz() ")); +#endif + + uint16_t msb, mid, lsb; + int16_t freqerr; + uint8_t bw; + float bwconst; + + msb = readRegister(REG_FEIMSB); + mid = readRegister(REG_FEIMID); + lsb = readRegister(REG_FEILSB); + + if (_Device != DEVICE_SX1272) + { + //for all devices apart from SX1272 + bw = (readRegister(REG_MODEMCONFIG1)) & (0xF0); + + switch (bw) + { + case LORA_BW_125: //ordered with most commonly used first + bwconst = 2.097; + break; + + case LORA_BW_062: + bwconst = 1.049; + break; + + case LORA_BW_041: + bwconst = 0.6996; + break; + + case LORA_BW_007: + bwconst = 0.1309; + break; + + case LORA_BW_010: + bwconst = 0.1745; + break; + + case LORA_BW_015: + bwconst = 0.2617; + break; + + case LORA_BW_020: + bwconst = 0.3490; + break; + + case LORA_BW_031: + bwconst = 0.5234; + break; + + case LORA_BW_250: + bwconst = 4.194; + break; + + case LORA_BW_500: + bwconst = 8.389; + break; + + default: + bwconst = 0x00; + } + } + else + { + //for the SX1272 + bw = (readRegister(REG_MODEMCONFIG1)) & (0xF0); + + switch (bw) + { + case 0: //this is LORA_BW_125 + bwconst = 2.097; + break; + + case 64: //this is LORA_BW_250 + bwconst = 4.194; + break; + + case 128: //this is LORA_BW_250 + bwconst = 8.389; + break; + + default: + bwconst = 0x00; + } + } + + freqerr = msb << 12; //shift lower 4 bits of msb into high 4 bits of freqerr + mid = (mid << 8) + lsb; + mid = (mid >> 4); + freqerr = freqerr + mid; + + freqerr = (int16_t) (freqerr * bwconst); + + return freqerr; +} + + +void SX127XLT::setTx(uint32_t timeout) +{ + //There is no TX timeout function for SX127X, the value passed is ignored + +#ifdef SX127XDEBUG1 + Serial.println(F("setTx() ")); +#endif + + LTUNUSED(timeout); //unused TX timeout passed for compatibility with SX126x, SX128x + + clearIrqStatus(IRQ_RADIO_ALL); + + /* This function not used on current SX127x + if (_rxtxpinmode) + { + rxEnable(); + } + */ + + writeRegister(REG_OPMODE, (MODE_TX + 0x88)); //TX on LoRa mode +} + + +void SX127XLT::setRx(uint32_t timeout) +{ + //no timeout in this routine, left in for compatibility +#ifdef SX127XDEBUG1 + Serial.println(F("setRx()")); +#endif + + LTUNUSED(timeout); + + clearIrqStatus(IRQ_RADIO_ALL); + + /* This function not used on current SX127x + if (_rxtxpinmode) + { + rxEnable(); + } + */ + + writeRegister(REG_OPMODE, (MODE_RXCONTINUOUS + 0x80)); //RX on LoRa mode +} + + +bool SX127XLT::readTXIRQ() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readTXIRQ()")); +#endif + + uint16_t IRQreg; + IRQreg = readIrqStatus(); + + if (IRQreg & IRQ_TX_DONE) + { + return true; + } + else + { + return false; + } +} + + +bool SX127XLT::readRXIRQ() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readRXIRQ() ")); +#endif + + uint16_t IRQreg; + IRQreg = readIrqStatus(); + + if (IRQreg & IRQ_RX_DONE) + { + return true; + } + else + { + return false; + } +} + + +void SX127XLT::setLowPowerReceive() +{ + //set min LNA gain, AGC off +#ifdef SX127XDEBUG1 + Serial.println(F("setLowPowerReceive() ")); +#endif + uint8_t regdata; + + regdata = readRegister(REG_MODEMCONFIG3); + bitClear(regdata,2); //set bit 2 to 0 turns off AGC + writeRegister(REG_MODEMCONFIG3, regdata ); //write data back + + writeRegister(REG_LNA, 0xC0 ); //Minimum gain for PA_BOOST and default for RFO_HF default LNA current +} + + +void SX127XLT::setHighSensitivity() +{ + //set max LNA gain and Boosted LNA for HF mode + +#ifdef SX127XDEBUG1 + Serial.println(F("setHighSensitivity() ")); +#endif + + writeRegister(REG_LNA, 0x23 ); //MAX gain for PA_BOOST and for RFO_HF set 150% LNA current. + } + + +void SX127XLT::setRXGain(uint8_t config) +{ + //set RX power saving mode + +#ifdef SX127XDEBUG1 + Serial.println(F("setRXGain() ")); +#endif + + uint8_t regdata; + + if (_Device != DEVICE_SX1272) + { + //for all devices apart from SX1272 + regdata = readRegister(REG_MODEMCONFIG3); + writeRegister(REG_MODEMCONFIG3, (regdata & (~READ_AGCAUTO_AND_X))); //clear bit AgcAutoOn (2) to ensure RegLNA is controlling gain + writeRegister(REG_LNA, config); + } + else + { + regdata = readRegister(REG_MODEMCONFIG2); + writeRegister(REG_MODEMCONFIG2, (regdata & (~READ_AGCAUTO_AND_2))); //clear bit AgcAutoOn (2) to ensure RegLNA is controlling gain + writeRegister(REG_LNA, config); + } +} + + +uint8_t SX127XLT::getAGC() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getAGC() ")); +#endif + + uint8_t regdata; + + if (_Device != DEVICE_SX1272) + { + regdata = readRegister(REG_MODEMCONFIG3); + regdata = (regdata & READ_AGCAUTO_AND_X); + } + else + { + regdata = readRegister(REG_MODEMCONFIG2); + regdata = (regdata & READ_AGCAUTO_AND_2); + } + + return (regdata >> 2); +} + + +uint8_t SX127XLT::getLNAgain() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getLNAgain() ")); +#endif + + uint8_t regdata; + regdata = readRegister(REG_LNA); + regdata = (regdata & READ_LNAGAIN_AND_X); + return (regdata >> 5); +} + + +uint8_t SX127XLT::getCRCMode() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getCRCMode() ")); +#endif + + uint8_t regdata; + + regdata = readRegister(REG_MODEMCONFIG2); + + if (_Device != DEVICE_SX1272) + { + regdata = readRegister(REG_MODEMCONFIG2); + regdata = ((regdata & READ_HASCRC_AND_X) >> 2); + } + else + { + regdata = readRegister(REG_MODEMCONFIG1); + regdata = ((regdata & READ_HASCRC_AND_2) >> 1); + } + + return regdata; +} + + +uint8_t SX127XLT::getHeaderMode() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getHeaderMode() ")); +#endif + + uint8_t regdata; + + regdata = readRegister(REG_MODEMCONFIG1); + + if (_Device != DEVICE_SX1272) + { + regdata = (regdata & READ_IMPLCIT_AND_X); + } + else + { + regdata = ((regdata & READ_IMPLCIT_AND_2) >> 2); + } + + return regdata; +} + + +uint8_t SX127XLT::getLNAboostLF() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getLNAboostLFLF() ")); +#endif + + uint8_t regdata; + + regdata = readRegister(REG_LNA); + + if (_Device != DEVICE_SX1272) + { + regdata = (regdata & READ_LNABOOSTLF_AND_X); + } + else + { + regdata = (regdata & READ_LNABOOSTLF_AND_2); + } + + return (regdata >> 3); +} + + +uint8_t SX127XLT::getLNAboostHF() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getLNAboostHF() ")); +#endif + + uint8_t regdata; + + regdata = readRegister(REG_LNA); + + if (_Device != DEVICE_SX1272) + { + regdata = (regdata & READ_LNABOOSTHF_AND_X); + } + else + { + regdata = (regdata & READ_LNABOOSTHF_AND_2); + } + + return regdata; +} + + +uint8_t SX127XLT::getOpmode() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getOpmode()")); +#endif + + uint8_t regdata; + + regdata = (readRegister(REG_OPMODE) & READ_OPMODE_AND_X); + + return regdata; +} + + +uint8_t SX127XLT::getPacketMode() +{ + //its either LoRa or FSK + +#ifdef SX127XDEBUG1 + Serial.println(F("getPacketMode() ")); +#endif + + uint8_t regdata; + + regdata = (readRegister(REG_OPMODE) & READ_RANGEMODE_AND_X); + + return (regdata >> 7); +} + + +uint8_t SX127XLT::readRXPacketL() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readRXPacketL() ")); +#endif + + _RXPacketL = readRegister(REG_RXNBBYTES); + return _RXPacketL; +} + + + +uint8_t SX127XLT::readTXPacketL() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readTXPacketL() ")); +#endif + + return _TXPacketL; +} + + +int16_t SX127XLT::readPacketRSSI() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readPacketRSSI() ")); +#endif + + //actual read SNR register values normally seen in practice are from 0 to 48 (0dB to +12dB) + //and 167 to 255 (-22dB to 0dB) + + int16_t _PacketRSSI; //RSSI of received packet + int8_t SNRregdata; + + if (_savedFrequency < 779000000) //779Mhz is lower frequency limit for SX1279 on band1 (HF Port) + { + _PacketRSSI = -164 + readRegister(REG_PKTRSSIVALUE); + } + else + { + _PacketRSSI = -157 + readRegister(REG_PKTRSSIVALUE); + } + + SNRregdata = readRegister(REG_PKTSNRVALUE); + + if (SNRregdata < 0) //check for negative SNR value + { + //Serial.print(F(" (-SNR) ")); + _PacketRSSI = (_PacketRSSI + (SNRregdata >> 2)); //add datasheet fiddle factor + } + + return _PacketRSSI; +} + + +int16_t SX127XLT::readCurrentRSSI() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readCurrentRSSI() ")); +#endif + + return readRegister(REG_CURRENTRSSIVALUE); +} + + +int8_t SX127XLT::readPacketSNR() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readPacketSNR() ")); +#endif + + uint8_t regdata; + int8_t _PacketSNR; + + regdata = readRegister(REG_PKTSNRVALUE); + + if (regdata > 127) + { + _PacketSNR = ((255 - regdata) / 4) * (-1); + } + else + { + _PacketSNR = regdata / 4; + } + + return _PacketSNR; +} + + +bool SX127XLT::readPacketCRCError() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readPacketCRCError() ")); +#endif + + uint16_t IRQreg; + IRQreg = readIrqStatus(); + + if (IRQreg & IRQ_CRC_ERROR) + { + return true; + } + else + { + return false; + } +} + + +bool SX127XLT::readPacketHeaderValid() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readPacketHeaderValid() ")); +#endif + + uint16_t IRQreg; + IRQreg = readIrqStatus(); + + if (IRQreg & IRQ_HEADER_VALID) + { + return true; + } + else + { + return false; + } +} + + +uint8_t SX127XLT::packetOK() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("packetOK() ")); +#endif + + bool packetHasCRC; + + packetHasCRC = (readRegister(REG_HOPCHANNEL) & 0x40); //read the packet has CRC bit in RegHopChannel + +#ifdef DEBUGPHANTOM + Serial.print(F("PacketHasCRC = ")); + Serial.println(packetHasCRC); + Serial.print(F("_UseCRC = ")); + Serial.println(_UseCRC); +#endif + + if ( !packetHasCRC && _UseCRC ) + { + _IRQmsb = _IRQmsb + IRQ_NO_PACKET_CRC; //flag the phantom packet + return 0; + } + + if ( readIrqStatus() != (IRQ_RX_DONE + IRQ_HEADER_VALID) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + return 1; //packet is OK +} + + +uint8_t SX127XLT::readRXPacketType() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readRXPacketType() ")); +#endif + + return _RXPacketType; +} + + +uint8_t SX127XLT::readRXDestination() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readRXDestination() ")); +#endif + return _RXDestination; +} + + +uint8_t SX127XLT::readRXSource() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readRXSource() ")); +#endif + + return _RXSource; +} + + +void SX127XLT::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setBufferBaseAddress() ")); +#endif + + writeRegister(REG_FIFOTXBASEADDR, txBaseAddress); + writeRegister(REG_FIFORXBASEADDR, rxBaseAddress); +} + + +void SX127XLT::setPacketType(uint8_t packettype ) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setPacketType() ")); +#endif + uint8_t regdata; + + regdata = (readRegister(REG_OPMODE) & 0x7F); //save all register bits bar the LoRa\FSK bit 7 + + if (packettype == PACKET_TYPE_LORA) + { + _PACKET_TYPE = PACKET_TYPE_LORA; + writeRegister(REG_OPMODE, 0x80); //REG_OPMODE, need to set to sleep mode before configure for LoRa mode + writeRegister(REG_OPMODE, (regdata + 0x80)); //back to original standby mode with LoRa set + } + else + { + _PACKET_TYPE = PACKET_TYPE_GFSK; + writeRegister(REG_OPMODE, 0x00); //REG_OPMODE, need to set to sleep mode before configure for FSK + writeRegister(REG_OPMODE, regdata); //back to original standby mode with FSK set + } +} + + +void SX127XLT::clearIrqStatus(uint16_t irqMask) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("clearIrqStatus() ")); +#endif + + uint8_t masklsb; + uint16_t maskmsb; + _IRQmsb = _IRQmsb & 0xFF00; //make sure _IRQmsb does not have LSB bits set. + masklsb = (irqMask & 0xFF); + maskmsb = (irqMask & 0xFF00); + writeRegister(REG_IRQFLAGS, masklsb); //clear standard IRQs + _IRQmsb = (_IRQmsb & (~maskmsb)); //only want top bits set. +} + + +uint16_t SX127XLT::readIrqStatus() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readIrqStatus()")); +#endif + + bool packetHasCRC; + uint8_t regdata; + regdata = readRegister(REG_IRQFLAGS); + + packetHasCRC = (readRegister(REG_HOPCHANNEL) & 0x40); //read the packet has CRC bit in RegHopChannel + + +#ifdef DEBUGPHANTOM + Serial.print(F("PacketHasCRC = ")); + Serial.println(packetHasCRC); + Serial.print(F("_UseCRC = ")); + Serial.println(_UseCRC); +#endif + + if (bitRead(regdata,6)) //check if its a packet receive (IRQ_RX_DONE set) + { + if (!packetHasCRC && _UseCRC) //check if packet header indicates no CRC on packet, byt use CRC set + { + bitSet(_IRQmsb, 10); //flag the phantom packet, set bit 10 + } + } + return (regdata + _IRQmsb); +} + + +void SX127XLT::setDioIrqParams(uint16_t irqMask, uint16_t dio0Mask, uint16_t dio1Mask, uint16_t dio2Mask) +{ + //note the irqmask contains the bit values of the interrupts that are allowed, so for all interrupts value is 0xFFFF + +#ifdef SX127XDEBUG1 + Serial.println(F("setDioIrqParams() ")); +#endif + + uint8_t mask0, mask1, mask2; + + LTUNUSED(dio2Mask); //variable left in call for compatibility with other libraries + + + switch (dio0Mask) + { + case IRQ_RX_DONE: + mask0 = 0; + break; + + case IRQ_TX_DONE: + mask0 = 0x40; + break; + + case IRQ_CAD_DONE: + mask0 = 0x80; + break; + + default: + mask0 = 0x0C; + } + + switch (dio1Mask) //for compatibility with other libraries IRQ_RX_TIMEOUT = IRQ_RX_TX_TIMEOUT + { + case IRQ_RX_TIMEOUT: + mask1 = 0; + break; + + case IRQ_FSHS_CHANGE_CHANNEL: + mask1 = 0x10; + break; + + case IRQ_CAD_ACTIVITY_DETECTED: + mask1 = 0x20; + break; + + default: + mask1 = 0x30; + } + + mask2 = 0x00; //is always IRQ_FSHS_CHANGE_CHANNEL + + writeRegister(REG_IRQFLAGSMASK, ~irqMask); + writeRegister(REG_DIOMAPPING1, (mask0 + mask1 + mask2)); +} + + +void SX127XLT::printIrqStatus() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printIrqStatus() ")); +#endif + + uint8_t _IrqStatus; + _IrqStatus = readIrqStatus(); + + //0x01 + if (_IrqStatus & IRQ_CAD_ACTIVITY_DETECTED) + { + Serial.print(F(",IRQ_CAD_ACTIVITY_DETECTED")); + } + + //0x02 + if (_IrqStatus & IRQ_FSHS_CHANGE_CHANNEL) + { + Serial.print(F(",IRQ_FSHS_CHANGE_CHANNEL")); + } + + //0x04 + if (_IrqStatus & IRQ_CAD_DONE) + { + Serial.print(F(",IRQ_CAD_DONE")); + } + + //0x08 + if (_IrqStatus & IRQ_TX_DONE) + { + Serial.print(F(",IRQ_TX_DONE")); + } + + //0x10 + if (_IrqStatus & IRQ_HEADER_VALID) + { + Serial.print(F(",IRQ_HEADER_VALID")); + } + + //0x20 + if (_IrqStatus & IRQ_CRC_ERROR) + { + Serial.print(F(",IRQ_CRC_ERROR")); + } + + //0x40 + if (_IrqStatus & IRQ_RX_DONE) + { + Serial.print(F(",IRQ_RX_DONE")); + } + + //0x80 + if (_IrqStatus & IRQ_RX_TIMEOUT ) + { + Serial.print(F(",IRQ_RX_TIMEOUT ")); + } + + if (_IRQmsb & IRQ_TX_TIMEOUT ) + { + Serial.print(F(",TX_TIMEOUT")); + } + + if (_IRQmsb & IRQ_RX_TIMEOUT ) + { + Serial.print(F(",RX_TIMEOUT")); + } + + if (_IRQmsb & IRQ_NO_PACKET_CRC ) + { + Serial.print(F(",NO_PACKET_CRC")); + } +} + + +void SX127XLT::printASCIIPacket(uint8_t *buffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printASCIIPacket() ")); +#endif + + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } +} + + +void SX127XLT::printHEXPacket(uint8_t *buffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printHEXPacket() ")); +#endif + + uint8_t index; + + for (index = 0; index < size; index++) + { + printHEXByte(buffer[index]); + Serial.print(F(" ")); + } +} + + +void SX127XLT::printASCIIorHEX(uint8_t temp) +{ + //prints as ASCII if within range, otherwise as HEX. +#ifdef SX127XDEBUG1 + Serial.println(F("printASCIIorHEX() ")); +#endif + + if ((temp < 0x10) || (temp > 0x7E)) + { + Serial.print(F(" (")); + printHEXByte(temp); + Serial.print(F(") ")); + } + else + { + Serial.write(temp); + } +} + + +void SX127XLT::printHEXByte(uint8_t temp) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printHEXByte() ")); +#endif + + if (temp < 0x10) + { + Serial.print(F("0")); + } + Serial.print(temp, HEX); +} + + +void SX127XLT::printHEXByte0x(uint8_t temp) +{ + //print a byte, adding 0x + +#ifdef SX127XDEBUG1 + Serial.println(F("printHEXByte0x()")); +#endif + + Serial.print(F("0x")); + if (temp < 0x10) + { + Serial.print(F("0")); + } + Serial.print(temp, HEX); +} + + +bool SX127XLT::isRXdone() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("isRXdone() ")); +#endif + + return digitalRead(_DIO0); +} + +bool SX127XLT::isTXdone() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("isTXdone()")); +#endif + + return digitalRead(_DIO0); +} + + +bool SX127XLT::isRXdoneIRQ() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("isRXdoneIRQ() ")); +#endif + + return (readRegister(REG_IRQFLAGS) & IRQ_RX_DONE); +} + + +bool SX127XLT::isTXdoneIRQ() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("isTXdoneIRQ() ")); +#endif + + return (readRegister(REG_IRQFLAGS) & IRQ_TX_DONE); +} + + +void SX127XLT::setTXDonePin(uint8_t pin) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setTXDonePin() ")); +#endif + + _TXDonePin = pin; +} + + +void SX127XLT:: setRXDonePin(uint8_t pin) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setRXDonePin() ")); +#endif + + _RXDonePin = pin; +} + + +uint8_t SX127XLT::receive(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait ) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("receive()")); +#endif + + uint16_t index; + uint32_t startmS; + uint8_t regdata; + + setMode(MODE_STDBY_RC); + regdata = readRegister(REG_FIFORXBASEADDR); //retrieve the RXbase address pointer + writeRegister(REG_FIFOADDRPTR, regdata); //and save in FIFO access ptr + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_HEADER_VALID), 0, 0); //set for IRQ on RX done + setRx(0); //no actual RX timeout in this function + + if (!wait) + { + return 0; //not wait requested so no packet length to pass + } + + if (rxtimeout == 0) + { + while (!digitalRead(_RXDonePin)); //Wait for DIO0 to go high, no timeout, RX DONE + } + else + { + //change to allow for millis() rollover + //code was endtimeoutmS = millis() + rxtimeout; while (!digitalRead(_RXDonePin) && (millis() < endtimeoutmS)); + startmS = millis(); + while (!digitalRead(_RXDonePin) && ((uint32_t) (millis() - startmS) < rxtimeout)); + } + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + if (!digitalRead(_RXDonePin)) //check if DIO still low, is so must be RX timeout + { + _IRQmsb = IRQ_RX_TIMEOUT; + return 0; + } + + + if ( readIrqStatus() != (IRQ_RX_DONE + IRQ_HEADER_VALID) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + _RXPacketL = readRegister(REG_RXNBBYTES); + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space in passed buffer + } + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + + for (index = 0; index < _RXPacketL; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX127XLT::receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("receiveAddressed() ")); +#endif + + uint16_t index; + uint32_t startmS; + uint8_t regdata; + + setMode(MODE_STDBY_RC); + regdata = readRegister(REG_FIFORXBASEADDR); //retrieve the RXbase address pointer + writeRegister(REG_FIFOADDRPTR, regdata); //and save in FIFO access ptr + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_HEADER_VALID), 0, 0); //set for IRQ on RX done + setRx(0); //no actual RX timeout in this function + + if (!wait) + { + return 0; + } + + if (rxtimeout == 0) + { + while (!digitalRead(_RXDonePin)); //Wait for DIO0 to go high, no timeout, RX DONE + } + else + { + startmS = millis(); + while (!digitalRead(_RXDonePin) && ((uint32_t) (millis() - startmS) < rxtimeout)); + } + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + if (!digitalRead(_RXDonePin)) //check if not DIO still low, is so must be RX timeout + { + _IRQmsb = IRQ_RX_TIMEOUT; + return 0; + } + + if ( readIrqStatus() != (IRQ_RX_DONE + IRQ_HEADER_VALID) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + _RXPacketL = readRegister(REG_RXNBBYTES); + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space in passed buffer + } + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + + _RXPacketType = SPI.transfer(0); + _RXDestination = SPI.transfer(0); + _RXSource = SPI.transfer(0); + + for (index = 0; index < _RXPacketL; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX127XLT::readPacket(uint8_t *rxbuffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readPacket() ")); +#endif + + uint8_t index, regdata; + + if ( readIrqStatus() != (IRQ_RX_DONE + IRQ_HEADER_VALID) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + setMode(MODE_STDBY_RC); + regdata = readRegister(REG_FIFORXBASEADDR); //retrieve the RXbase address pointer + writeRegister(REG_FIFOADDRPTR, regdata); //and save in FIFO access ptr + + _RXPacketL = readRegister(REG_RXNBBYTES); + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + + for (index = 0; index < _RXPacketL; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX127XLT::readPacketAddressed(uint8_t *rxbuffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readPacketAddressed() ")); +#endif + + uint8_t index, regdata; + + setMode(MODE_STDBY_RC); + regdata = readRegister(REG_FIFORXBASEADDR); //retrieve the RXbase address pointer + writeRegister(REG_FIFOADDRPTR, regdata); //and save in FIFO access ptr + + _RXPacketL = readRegister(REG_RXNBBYTES); + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + _RXPacketType = SPI.transfer(0); + _RXDestination = SPI.transfer(0); + _RXSource = SPI.transfer(0); + + for (index = 0; index < _RXPacketL; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX127XLT::transmit(uint8_t *txbuffer, uint8_t size, uint32_t txtimeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("transmit()")); +#endif + + uint8_t index, ptr; + uint8_t bufferdata; + uint32_t startmS; + + if (size == 0) + { + return false; + } + + setMode(MODE_STDBY_RC); + ptr = readRegister(REG_FIFOTXBASEADDR); //retrieve the TXbase address pointer + writeRegister(REG_FIFOADDRPTR, ptr); //and save in FIFO access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(WREG_FIFO); + + for (index = 0; index < size; index++) + { + bufferdata = txbuffer[index]; + SPI.transfer(bufferdata); + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + _TXPacketL = size; + writeRegister(REG_PAYLOADLENGTH, _TXPacketL); + + setTxParams(txpower, RADIO_RAMP_DEFAULT); //TX power and ramp time + + setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done on first DIO pin + setTx(0); //TX timeout is not handled in setTX() + + if (!wait) + { + return _TXPacketL; + } + + if (txtimeout == 0) + { + while (!digitalRead(_TXDonePin)); //Wait for pin to go high, TX finished + } + else + { + startmS = millis(); + while (!digitalRead(_TXDonePin) && ((uint32_t) (millis() - startmS) < txtimeout)); + } + + setMode(MODE_STDBY_RC); //ensure we leave function with TX off + + if (!digitalRead(_TXDonePin)) + { + _IRQmsb = IRQ_TX_TIMEOUT; + return 0; + } + + return _TXPacketL; //no timeout, so TXdone must have been set +} + + +uint8_t SX127XLT::transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t txtimeout, int8_t txpower, uint8_t wait ) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("transmitAddressed() ")); +#endif + + uint8_t index, ptr; + uint8_t bufferdata; + uint32_t startmS; + + if (size == 0) + { + return false; + } + + setMode(MODE_STDBY_RC); + ptr = readRegister(REG_FIFOTXBASEADDR); //retrieve the TXbase address pointer + writeRegister(REG_FIFOADDRPTR, ptr); //and save in FIFO access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(WREG_FIFO); + SPI.transfer(txpackettype); //Write the packet type + SPI.transfer(txdestination); //Destination node + SPI.transfer(txsource); //Source node + _TXPacketL = 3 + size; //we have added 3 header bytes to size + + for (index = 0; index < size; index++) + { + bufferdata = txbuffer[index]; + SPI.transfer(bufferdata); + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + writeRegister(REG_PAYLOADLENGTH, _TXPacketL); + + setTxParams(txpower, RADIO_RAMP_DEFAULT); //TX power and ramp time + + setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done + setTx(0); //TX timeout is not handled in setTX() + + if (!wait) + { + return _TXPacketL; + } + + if (txtimeout == 0) + { + while (!digitalRead(_TXDonePin)); //Wait for DIO0 to go high, TX finished + } + else + { + startmS = millis(); + while (!digitalRead(_TXDonePin) && ((uint32_t) (millis() - startmS) < txtimeout)); + } + + setMode(MODE_STDBY_RC); //ensure we leave function with TX off + + if (!digitalRead(_TXDonePin)) //its a timeout if _TXDonepin still high + { + _IRQmsb = IRQ_TX_TIMEOUT; + return 0; + } + + return _TXPacketL; //no timeout, so TXdone must have been set +} + + +void SX127XLT::setupLoRa(uint32_t Frequency, int32_t Offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setupLoRa() ")); +#endif + + setMode(MODE_STDBY_RC); //go into standby mode to configure device + setPacketType(PACKET_TYPE_LORA); //use LoRa packets + setRfFrequency(Frequency, Offset); //set the operating frequncy + calibrateImage(0); //run calibration after setting frequency + setModulationParams(modParam1, modParam2, modParam3, modParam4); + setBufferBaseAddress(0x00, 0x00); //set bases addresses for TX and RX packets in SX buffer + setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set the packet options + setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword to use, 0x12 for standard private, 0x34 for public (LORAWAN) + setHighSensitivity(); +} + + +uint8_t SX127XLT::getLoRaSF() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getLoRaSF() ")); +#endif + + uint8_t regdata; + regdata = readRegister(REG_MODEMCONFIG2); + regdata = ((regdata & READ_SF_AND_X) >> 4); //SX1272 and SX1276 store SF in same place + + return regdata; +} + + +uint8_t SX127XLT::getLoRaCodingRate() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getLoRaCodingRate() ")); +#endif + + uint8_t regdata; + regdata = readRegister(REG_MODEMCONFIG1); + + if (_Device != DEVICE_SX1272) + { + //for all devices apart from SX1272 + regdata = (((regdata & READ_CR_AND_X) >> 1) + 4); + } + else + { + regdata = (((regdata & READ_CR_AND_2) >> 3) + 4); + } + + return regdata; +} + + +uint8_t SX127XLT::getOptimisation() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getOptimisation() ")); +#endif + + uint8_t regdata; + + if (_Device != DEVICE_SX1272) + { + //for all devices apart from SX1272 + regdata = readRegister(REG_MODEMCONFIG3); + regdata = ((regdata & READ_LDRO_AND_X) >> 3); + } + else + { + regdata = readRegister(REG_MODEMCONFIG1); + regdata = (regdata & READ_LDRO_AND_2); + } + + return regdata; +} + + +uint8_t SX127XLT::getSyncWord() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getSyncWord() ")); +#endif + + return readRegister(REG_SYNCWORD); +} + + +uint8_t SX127XLT::getInvertIQ() +{ + //IQ mode reg 0x33 + +#ifdef SX127XDEBUG1 + Serial.println(F("getInvertIQ() ")); +#endif + + uint8_t regdata; + regdata = ( (readRegister(REG_INVERTIQ)) & 0x40 ); + return regdata; +} + + +uint8_t SX127XLT::getVersion() +{ + //IQ mode reg 0x33 + +#ifdef SX127XDEBUG1 + Serial.println(F("getVersion() ")); +#endif + + return readRegister(REG_VERSION); +} + + +uint16_t SX127XLT::getPreamble() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getPreamble() ")); +#endif + + uint16_t regdata; + regdata = ( (readRegister(REG_PREAMBLEMSB) << 8) + readRegister(REG_PREAMBLELSB) ); + return regdata; +} + + +uint32_t SX127XLT::returnBandwidth(byte BWregvalue) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("returnBandwidth() ")); +#endif + + if (_Device == DEVICE_SX1272) + { + switch (BWregvalue) + { + case 0: + return 125000; + + case 64: + return 250000; + + case 128: + return 500000; + + default: + return 0xFF; //so that a bandwidth invalid entry can be identified ? + } + } + else + { + + switch (BWregvalue) + { + case 0: + return 7800; + + case 16: + return 10400; + + case 32: + return 15600; + + case 48: + return 20800; + + case 64: + return 31200; + + case 80: + return 41700; + + case 96: + return 62500; + + case 112: + return 125000; + + case 128: + return 250000; + + case 144: + return 500000; + + default: + return 0xFF; //so that a bandwidth invalid entry can be identified ? + } + } +} + + +uint8_t SX127XLT::returnOptimisation(uint8_t Bandwidth, uint8_t SpreadingFactor) +{ + //from the passed bandwidth (bandwidth) and spreading factor this routine + //calculates whether low data rate optimisation should be on or off + +#ifdef SX127XDEBUG1 + Serial.println(F("returnOptimisation() ")); +#endif + + uint32_t tempBandwidth; + float symbolTime; + tempBandwidth = returnBandwidth(Bandwidth); + symbolTime = calcSymbolTime(tempBandwidth, SpreadingFactor); + +#ifdef SX127XDEBUG1 + Serial.print(F("Symbol Time ")); + Serial.print(symbolTime, 3); + Serial.println(F("mS")); +#endif + + if (symbolTime > 16) + { +#ifdef SX127XDEBUG1 + Serial.println(F("LDR Opt on")); +#endif + return LDRO_ON; + } + else + { +#ifdef SX127XDEBUG1 + Serial.println(F("LDR Opt off")); +#endif + return LDRO_OFF; + } +} + + +float SX127XLT::calcSymbolTime(float Bandwidth, uint8_t SpreadingFactor) +{ + //calculates symbol time from passed bandwidth (lbandwidth) and Spreading factor (lSF)and returns in mS + +#ifdef SX127XDEBUG1 + Serial.println(F("calcSymbolTime() ")); +#endif + + float symbolTimemS; + symbolTimemS = (Bandwidth / pow(2, SpreadingFactor)); + symbolTimemS = (1000 / symbolTimemS); + return symbolTimemS; +} + + +void SX127XLT::printModemSettings() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printModemSettings()")); +#endif + + uint8_t regdata; + + printDevice(); + Serial.print(F(",")); + Serial.print(getFreqInt()); + Serial.print(F("hz,SF")); + Serial.print(getLoRaSF()); + Serial.print(F(",BW")); + + + if (_Device == DEVICE_SX1272) + { + regdata = (readRegister(REG_MODEMCONFIG1) & READ_BW_AND_2); + } + else + { + regdata = (readRegister(REG_MODEMCONFIG1) & READ_BW_AND_X); + } + + Serial.print(returnBandwidth(regdata)); + Serial.print(F(",CR4:")); + Serial.print(getLoRaCodingRate()); + Serial.print(F(",LDRO_")); + + if (getOptimisation()) + { + Serial.print(F("On")); + } + else + { + Serial.print(F("Off")); + } + + Serial.print(F(",SyncWord_0x")); + Serial.print(getSyncWord(), HEX); + if (getInvertIQ() == LORA_IQ_INVERTED) + { + Serial.print(F(",IQInverted")); + } + else + { + Serial.print(F(",IQNormal")); + } + Serial.print(F(",Preamble_")); + Serial.print(getPreamble()); +} + + +void SX127XLT::setSyncWord(uint8_t syncword) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setSyncWord() ")); +#endif + + writeRegister(REG_SYNCWORD, syncword); +} + + +uint8_t SX127XLT::receiveSXBuffer(uint8_t startaddr, uint32_t rxtimeout, uint8_t wait ) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("receiveSXBuffer()")); +#endif + + uint32_t startmS; + + setMode(MODE_STDBY_RC); + writeRegister(REG_FIFORXBASEADDR, startaddr); //set start address of RX packet in buffer + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_HEADER_VALID), 0, 0); //set for IRQ on RX done + setRx(0); //no actual RX timeout in this function + + if (!wait) + { + return 0; + } + + if (rxtimeout == 0) + { + while (!digitalRead(_RXDonePin)); //Wait for DIO0 to go high, no timeout, RX DONE + } + else + { + startmS = millis(); + while (!digitalRead(_RXDonePin) && ((uint32_t) (millis() - startmS) < rxtimeout)); + } + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + if (!digitalRead(_RXDonePin)) //check if not DIO still low, is so must be RX timeout + { + _IRQmsb = IRQ_RX_TIMEOUT; + return 0; + } + + if ( readIrqStatus() != (IRQ_RX_DONE + IRQ_HEADER_VALID) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + _RXPacketL = readRegister(REG_RXNBBYTES); + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + + +uint8_t SX127XLT::transmitSXBuffer(uint8_t startaddr, uint8_t length, uint32_t txtimeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("transmitSXBuffer() ")); +#endif + + uint32_t startmS; + + setMode(MODE_STDBY_RC); + + writeRegister(REG_FIFOTXBASEADDR, startaddr); //set start address of packet in buffer + writeRegister(REG_PAYLOADLENGTH, length); + + setTxParams(txpower, RADIO_RAMP_DEFAULT); //TX power and ramp time + + setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done + setTx(0); //TX timeout is not handled in setTX() + + if (!wait) + { + return length; + } + + if (txtimeout == 0) + { + while (!digitalRead(_TXDonePin)); //Wait for DIO0 to go high, TX finished + } + else + { + startmS = millis(); + while (!digitalRead(_TXDonePin) && ((uint32_t) (millis() - startmS) < txtimeout)); + } + + setMode(MODE_STDBY_RC); //ensure we leave function with TX off + + + if (!digitalRead(_TXDonePin)) //if _TXDonePin still high then TX timeout + { + _IRQmsb = IRQ_TX_TIMEOUT; + + return 0; + } + + return length; //no timeout, so TXdone must have been set +} + + + +void SX127XLT::printSXBufferHEX(uint8_t start, uint8_t end) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printSXBufferHEX() ")); +#endif + + uint8_t index, regdata; + + setMode(MODE_STDBY_RC); + writeRegister(REG_FIFOADDRPTR, start); //set FIFO access ptr to start + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + + for (index = start; index <= end; index++) + { + regdata = SPI.transfer(0); + printHEXByte(regdata); + Serial.print(F(" ")); + + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +void SX127XLT::printSXBufferASCII(uint8_t start, uint8_t end) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("printSXBufferASCII() ")); +#endif + + uint8_t index, regdata; + setMode(MODE_STDBY_RC); + + writeRegister(REG_FIFOADDRPTR, start); //and save in FIFO access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + + for (index = start; index <= end; index++) + { + regdata = SPI.transfer(0); + Serial.write(regdata); + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif +} + + +void SX127XLT::fillSXBuffer(uint8_t startaddress, uint8_t size, uint8_t character) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("fillSXBuffer() ")); +#endif + uint8_t index; + + setMode(MODE_STDBY_RC); + writeRegister(REG_FIFOADDRPTR, startaddress); //and save in FIFO access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst write + SPI.transfer(WREG_FIFO); + + for (index = 0; index < size; index++) + { + SPI.transfer(character); + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif +} + + +uint8_t SX127XLT::getByteSXBuffer(uint8_t addr) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getByteSXBuffer() ")); +#endif + + uint8_t regdata; + setMode(MODE_STDBY_RC); //this is needed to ensure we can read from buffer OK. + + writeRegister(REG_FIFOADDRPTR, addr); //set FIFO access ptr to location + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + regdata = SPI.transfer(0); + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return regdata; +} + + +void SX127XLT::writeByteSXBuffer(uint8_t addr, uint8_t regdata) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeByteSXBuffer() ")); +#endif + + setMode(MODE_STDBY_RC); //this is needed to ensure we can write to buffer OK. + + writeRegister(REG_FIFOADDRPTR, addr); //set FIFO access ptr to location + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(WREG_FIFO); + SPI.transfer(regdata); + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif +} + + +void SX127XLT::startWriteSXBuffer(uint8_t ptr) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("startWriteSXBuffer() ")); +#endif + + setMode(MODE_STDBY_RC); + + _TXPacketL = 0; //this variable used to keep track of bytes written + writeRegister(REG_FIFOADDRPTR, ptr); //set buffer access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(WREG_FIFO); +} + + +uint8_t SX127XLT::endWriteSXBuffer() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("endWriteSXBuffer() ")); +#endif + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _TXPacketL; +} + + +void SX127XLT::startReadSXBuffer(uint8_t ptr) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("startReadSXBuffer() ")); +#endif + + setMode(MODE_STDBY_RC); + _RXPacketL = 0; + writeRegister(REG_FIFOADDRPTR, ptr); //set buffer access ptr + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(REG_FIFO); + + //next line would be data = SPI.transfer(0); + //SPI interface ready for byte to read from +} + + +uint8_t SX127XLT::endReadSXBuffer() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("endReadSXBuffer() ")); +#endif + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; +} + + +void SX127XLT::writeUint8(uint8_t x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeUint8() ")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + + +uint8_t SX127XLT::readUint8() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readUint8() ")); +#endif + + uint8_t x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX127XLT::writeInt8(int8_t x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeInt8() ")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + + +int8_t SX127XLT::readInt8() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readInt8() ")); +#endif + + int8_t x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX127XLT::writeChar(char x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeChar() ")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + + +char SX127XLT::readChar() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readChar() ")); +#endif + + char x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX127XLT::writeUint16(uint16_t x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeUint16() ")); +#endif + + SPI.transfer(lowByte(x)); + SPI.transfer(highByte(x)); + + _TXPacketL = _TXPacketL + 2; //increment count of bytes written +} + + +uint16_t SX127XLT::readUint16() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeUint16() ")); +#endif + + uint8_t lowbyte, highbyte; + + lowbyte = SPI.transfer(0); + highbyte = SPI.transfer(0); + + _RXPacketL = _RXPacketL + 2; //increment count of bytes read + return ((highbyte << 8) + lowbyte); +} + + +void SX127XLT::writeInt16(int16_t x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeInt16() ")); +#endif + + SPI.transfer(lowByte(x)); + SPI.transfer(highByte(x)); + + _TXPacketL = _TXPacketL + 2; //increment count of bytes written +} + + +int16_t SX127XLT::readInt16() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readInt16() ")); +#endif + + uint8_t lowbyte, highbyte; + + lowbyte = SPI.transfer(0); + highbyte = SPI.transfer(0); + + _RXPacketL = _RXPacketL + 2; //increment count of bytes read + return ((highbyte << 8) + lowbyte); +} + + +void SX127XLT::writeUint32(uint32_t x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeUint32() ")); +#endif + + uint8_t i, j; + + union + { + uint8_t b[4]; + uint32_t f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +uint32_t SX127XLT::readUint32() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readUint32() ")); +#endif + + uint8_t i, j; + + union + { + uint8_t b[4]; + uint32_t f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX127XLT::writeInt32(int32_t x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeInt32() ")); +#endif + + uint8_t i, j; + + union + { + uint8_t b[4]; + int32_t f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +int32_t SX127XLT::readInt32() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readInt32() ")); +#endif + + uint8_t i, j; + + union + { + uint8_t b[4]; + int32_t f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX127XLT::writeFloat(float x) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeFloat() ")); +#endif + + uint8_t i, j; + + union + { + uint8_t b[4]; + float f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +float SX127XLT::readFloat() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readFloat() ")); +#endif + + uint8_t i, j; + + union + { + uint8_t b[4]; + float f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX127XLT::writeBuffer(uint8_t *txbuffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeBuffer() ")); +#endif + + uint8_t index, regdata; + + _TXPacketL = _TXPacketL + size; //these are the number of bytes that will be added + + size--; //loose one byte from size, the last byte written MUST be a 0 + + for (index = 0; index < size; index++) + { + regdata = txbuffer[index]; + SPI.transfer(regdata); + } + + SPI.transfer(0); //this ensures last byte of buffer writen really is a null (0) +} + + + +void SX127XLT::writeBufferChar(char *txbuffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeBufferChar() ")); +#endif + + uint8_t index, regdata; + + _TXPacketL = _TXPacketL + size; //these are the number of bytes that will be added + + size--; //loose one byte from size, the last byte written MUST be a 0 + + for (index = 0; index < size; index++) + { + regdata = txbuffer[index]; + SPI.transfer(regdata); + } + + SPI.transfer(0); //this ensures last byte of buffer writen really is a null (0) +} + + + +void SX127XLT::writeBufferChar(char *txbuffer) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeBufferChar() ")); +#endif + + uint8_t index = 0, regdata; + + do + { + regdata = txbuffer[index]; //read data from txbuffer + SPI.transfer(regdata); //write to device buffer + index++; + } while (regdata != 0); //keep reading until we have reached the null (0) at the buffer end or exceeded size of buffer allowed + + _TXPacketL = _TXPacketL + index; //increment count of bytes written + + SPI.transfer(0); //this ensures last byte of buffer writen really is a null (0) +} + + + +uint8_t SX127XLT::readBuffer(uint8_t *rxbuffer) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readBuffer(")); +#endif + + uint8_t index = 0, regdata; + + do + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; //fill the rxbuffer. + index++; + } while (regdata != 0); //keep reading until we have reached the null (0) at the buffer end or exceeded size of buffer allowed + + _RXPacketL = _RXPacketL + index; //increment count of bytes read + + return index; //return the actual size of the buffer, when the null (0) detected +} + + +uint8_t SX127XLT::readBuffer(uint8_t *rxbuffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readBuffer() ")); +#endif + + uint8_t index, regdata; + + for (index = 0; index <= size; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; //fill the rxbuffer. + } + + _RXPacketL = _RXPacketL + size; //increment count of bytes read + + return size; //return the actual size of the buffer +} + + + +uint8_t SX127XLT::readBufferChar(char *rxbuffer) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readBufferChar() ")); +#endif + + uint8_t index = 0, regdata; + + do + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; //fill the buffer. + index++; + } while (regdata != 0); //keep reading until we have reached the null (0) at the buffer end + + _RXPacketL = _RXPacketL + index; //increment count of bytes read + + return index; //return the actual size of the buffer, when the null (0) detected +} + + +void SX127XLT::rxtxInit(int8_t pinRXEN, int8_t pinTXEN) +{ + //not used on current SX127x modules + +#ifdef SX127XDEBUG1 + Serial.println(F("rxtxInit() ")); +#endif + + _RXEN = pinRXEN; + _TXEN = pinTXEN; + + pinMode(pinRXEN, OUTPUT); + digitalWrite(pinRXEN, LOW); //pins needed for RX\TX switching + pinMode(pinTXEN, OUTPUT); + digitalWrite(pinTXEN, LOW); //pins needed for RX\TX switching +} + + +void SX127XLT::rxEnable() +{ + //not used on current SX127x modules + +#ifdef SX127XDEBUG1 + Serial.println(F("rxEnable() ")); +#endif + + digitalWrite(_RXEN, HIGH); + digitalWrite(_TXEN, LOW); +} + + +void SX127XLT::txEnable() +{ + //not used on current SX127x modules + +#ifdef SX127XDEBUG1 + Serial.println(F("txEnable() ")); +#endif + + digitalWrite(_RXEN, LOW); + digitalWrite(_TXEN, HIGH); +} + + +void SX127XLT::setTXDirect() +{ + //turns on transmitter, in direct mode for FSK and audio power level is from 2 to 17 +#ifdef SX127XDEBUG1 + Serial.println(F("setTXDirect()")); +#endif + writeRegister(REG_OPMODE, 0x0B); //TX on direct mode, low frequency mode +} + + +void SX127XLT::toneFM(uint16_t frequency, uint32_t length, uint32_t deviation, float adjust, int8_t txpower) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("toneFM() ")); +#endif + + uint16_t index; + uint32_t ToneDelayus; + uint32_t registershift; + uint32_t freqreg; + uint32_t shiftedfreqregH, shiftedfreqregL; + uint32_t loopcount; + uint8_t freqregH, freqregM, freqregL; + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(REG_FRMSB & 0x7F); //mask address for read + freqregH = SPI.transfer(0); + freqregM = SPI.transfer(0); + freqregL = SPI.transfer(0); + digitalWrite(_NSS, HIGH); //set NSS high + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + freqreg = ( ( (uint32_t) freqregH << 16 ) | ( (uint32_t) freqregM << 8 ) | ( freqregL ) ); + + registershift = deviation / FREQ_STEP; + shiftedfreqregH = freqreg + registershift; + shiftedfreqregL = freqreg - registershift; + + uint8_t ShiftH = shiftedfreqregH >> 16; + uint8_t ShiftM = shiftedfreqregH >> 8; + uint8_t ShiftL = shiftedfreqregH; + uint8_t NoShiftH = shiftedfreqregL >> 16; + uint8_t NoShiftM = shiftedfreqregL >> 8; + uint8_t NoShiftL = shiftedfreqregL; + + ToneDelayus = ((500000 / frequency)); + loopcount = (length * 500) / (ToneDelayus); + ToneDelayus = ToneDelayus * adjust; + +#ifdef SX127XDEBUG3 + Serial.print(F("frequency ")); + Serial.println(frequency); + Serial.print(F("length ")); + Serial.println(length); + + Serial.print(F("freqreg ")); + Serial.println(freqreg, HEX); + Serial.print(F("registershift ")); + Serial.println(registershift); + shiftedfreqregH = freqreg + (registershift / 2); + shiftedfreqregL = freqreg - (registershift / 2); + Serial.print(F("shiftedfreqregH ")); + Serial.println(shiftedfreqregH, HEX); + Serial.print(F("shiftedfreqregL ")); + Serial.println(shiftedfreqregL, HEX); + + Serial.print(F("ShiftedHigh,")); + Serial.print(ShiftH, HEX); + Serial.print(F(",")); + Serial.print(ShiftM, HEX); + Serial.print(F(",")); + Serial.println(ShiftL, HEX); + + Serial.print(F("ShiftedLow,")); + Serial.print(NoShiftH, HEX); + Serial.print(F(",")); + Serial.print(NoShiftM, HEX); + Serial.print(F(",")); + Serial.println(NoShiftL, HEX); + Serial.print(F("ToneDelayus,")); + Serial.println(ToneDelayus); + Serial.print(F("loopcount,")); + Serial.println(loopcount); + Serial.println(); + Serial.println(); +#endif + + writeRegister(REG_PLLHOP, 0xAD); //set fast hop mode, needed for fast changes of frequency + + setTxParams(txpower, RADIO_RAMP_DEFAULT); + setTXDirect(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + for (index = 1; index <= loopcount; index++) + { + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(0x86); //address for write to REG_FRMSB + SPI.transfer(ShiftH); + SPI.transfer(ShiftM); + SPI.transfer(ShiftL); + digitalWrite(_NSS, HIGH); //set NSS high + + delayMicroseconds(ToneDelayus); + + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(0x86); //address for write to REG_FRMSB + SPI.transfer(NoShiftH); + SPI.transfer(NoShiftM); + SPI.transfer(NoShiftL); + digitalWrite(_NSS, HIGH); //set NSS high + + delayMicroseconds(ToneDelayus); + } + //now set the frequency registers back to centre + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(0x86); //address for write to REG_FRMSB + SPI.transfer(freqregH); + SPI.transfer(freqregM); + SPI.transfer(freqregL); + digitalWrite(_NSS, HIGH); //set NSS high + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + writeRegister(REG_PLLHOP, 0x2D); //restore PLLHOP register value + setMode(MODE_STDBY_RC); //turns off carrier +} + + +void SX127XLT::setupDirect(uint32_t frequency, int32_t offset) +{ + //setup LoRa device for direct modulation mode +#ifdef SX127XDEBUG1 + Serial.println(F("setupDirect() ")); +#endif + _PACKET_TYPE = PACKET_TYPE_GFSK; //need to swap packet type + setMode(MODE_SLEEP); //can only swap to direct mode in sleepmode + setMode(MODE_SLEEP); //can only swap to direct mode in sleepmode + setMode(MODE_STDBY_RC); + writeRegister(REG_DETECTOPTIMIZE, 0x00); //set continuous mode + setRfFrequency(frequency, offset); //set the operating frequncy + calibrateImage(0); //run calibration after setting frequency + writeRegister(REG_FDEVLSB, 0); //We are generating a tone by frequency shift so set deviation to 0 +} + + +int8_t SX127XLT::getDeviceTemperature() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("getDeviceTemperature()")); +#endif + + int8_t temperature; + uint8_t regdata; + + regdata = readRegister(REG_IMAGECAL & 0xFE); + + writeRegister(REG_IMAGECAL, 0x00); //register back to power up default + + writeRegister(REG_OPMODE, 0x00); //goto sleep + writeRegister(REG_OPMODE, 0x00); //make sure switch to FSK mode + writeRegister(REG_OPMODE, 0x01); //go into FSK standby + delay(5); //wait for oscillator startup + writeRegister(REG_OPMODE, 0x04); //put device in FSK RX synth mode + + writeRegister(REG_IMAGECAL, 0x00); //set TempMonitorOff = 0 + delay(1); //wait at least 140uS + writeRegister(REG_IMAGECAL, 0x01); //set TempMonitorOff = 1 + setMode(MODE_STDBY_RC); //go back to standby + + writeRegister(REG_IMAGECAL, (regdata + 1)); //register back to previous setting, with TempMonitorOff set + + temperature = readRegister(REG_TEMP); + + if (temperature & 0x80 ) //The sign bit is 1 + { + temperature = ( ( ~temperature + 1 ) & 0xFF ); //Invert and divide by 4 + } + else + { + temperature = ( temperature & 0xFF ); //Divide by 4 + } + + writeRegister(REG_OPMODE, MODE_STDBY); + + return temperature; +} + + +void SX127XLT::fskCarrierOn(int8_t txpower) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("fskCarrierOn() ")); +#endif + + writeRegister(REG_PLLHOP, 0xAD); //set fast hop mode, needed for fast changes of frequency + setTxParams(txpower, RADIO_RAMP_DEFAULT); + setTXDirect(); +} + + +void SX127XLT::fskCarrierOff() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("fskCarrierOff() ")); +#endif + + setMode(MODE_STDBY_RC); //turns off carrier +} + + +void SX127XLT::setRfFrequencyDirect(uint8_t high, uint8_t mid, uint8_t low) +{ + +#ifdef SX127XDEBUG1 + Serial.println(F("setRfFrequencyDirect() ")); +#endif + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(0x86); //address for write to REG_FRMSB + SPI.transfer(high); + SPI.transfer(mid); + SPI.transfer(low); + digitalWrite(_NSS, HIGH); //set NSS high + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif +} + + +void SX127XLT::getRfFrequencyRegisters(uint8_t *buff) +{ + //returns the register values for the current set frequency + +#ifdef SX127XDEBUG1 + Serial.println(F("getRfFrequencyRegisters() ")); +#endif + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //set NSS low + SPI.transfer(REG_FRMSB & 0x7F); //mask address for read + buff[0] = SPI.transfer(0); //read the byte into buffer + buff[1] = SPI.transfer(0); //read the byte into buffer + buff[2] = SPI.transfer(0); //read the byte into buffer + digitalWrite(_NSS, HIGH); //set NSS high + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif +} + + +void SX127XLT::startFSKRTTY(uint32_t freqshift, uint8_t pips, uint16_t pipPeriodmS, uint16_t pipDelaymS, uint16_t leadinmS) +{ + +#ifdef SX127XDEBUG1 + Serial.println(F("startFSKRTTY() ")); +#endif + + uint8_t freqShiftRegs[3]; //to hold returned registers for shifted frequency + uint32_t setCentreFrequency; //the configured centre frequency + uint8_t index; + uint32_t startmS; + setCentreFrequency = _savedFrequency; //to avoid using the savedFrequency + + writeRegister(REG_PLLHOP, 0xAD); //set fast hop mode, needed for fast changes of frequency + + setRfFrequency((_savedFrequency + freqshift), _savedOffset); //temporaily set the RF frequency + getRfFrequencyRegisters(freqShiftRegs); //fill first 3 bytes with current frequency registers + setRfFrequency(setCentreFrequency, _savedOffset); //reset the base frequency registers + + _ShiftfreqregH = freqShiftRegs[0]; + _ShiftfreqregM = freqShiftRegs[1]; + _ShiftfreqregL = freqShiftRegs[2]; + + writeRegister(REG_PLLHOP, 0xAD); //set fast hop mode, needed for fast changes of frequency + setTxParams(10, RADIO_RAMP_DEFAULT); + + for (index = 1; index <= pips; index++) + { + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency + setTXDirect(); //turn on carrier + delay(pipPeriodmS); + setMode(MODE_STDBY_RC); //turns off carrier + delay(pipDelaymS); + } + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency + startmS = millis(); + setTXDirect(); //turn on carrier + while (((uint32_t) (millis() - startmS) < leadinmS)); +} + + +void SX127XLT::transmitFSKRTTY(uint8_t chartosend, uint8_t databits, uint8_t stopbits, uint8_t parity, uint16_t baudPerioduS, int8_t pin) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("transmitFSKRTTY() ")); +#endif + + uint8_t numbits; + uint32_t startuS; + uint8_t bitcount = 0; //set when a bit is 1 + + startuS = micros(); + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency (low) + + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + + for (numbits = 1; numbits <= databits; numbits++) //send bits, LSB first + { + + startuS = micros(); + if ((chartosend & 0x01) != 0) //test for bit set, a 1 + { + bitcount++; + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency for a 1 + } + else + { + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency for a 0 + } + chartosend = (chartosend >> 1); //get the next bit + + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + } + + startuS = micros(); + switch (parity) + { + case ParityNone: + break; + + case ParityZero: + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency for a 0 + + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + break; + + case ParityOne: + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency for a 1 + + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + break; + + case ParityOdd: + if (bitRead(bitcount, 0)) //test odd bit count, i.e. when bit 0 = 1 + { + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency for a 1 + } + else + { + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency for a 0 + } + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + break; + + case ParityEven: + if (bitRead(bitcount, 0)) //test odd bit count, i.e. when bit 0 = 1 + { + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency for a 0 + } + else + { + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency for a 1 + } + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + break; + + default: + break; + } + + startuS = micros(); + + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency + + while ( (uint32_t) (micros() - startuS) < (baudPerioduS * stopbits)); +} + + +void SX127XLT::transmitFSKRTTY(uint8_t chartosend, uint16_t baudPerioduS, int8_t pin) +{ + //This overloaded version of transmitFSKRTTY() defaults to 1 start bit, 7 data bits, no parity and 2 stop bits. + +#ifdef SX127XDEBUG1 + Serial.println(F("transmitFSKRTTY() ")); +#endif + + uint8_t numbits; + uint32_t startuS; + + //startbit + + startuS = micros(); + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency (low) + + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + + for (numbits = 1; numbits <= 7; numbits++) //send bits, LSB first + { + startuS = micros(); + if ((chartosend & 0x01) != 0) //test for bit set, a 1 + { + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency for a 1 + } + else + { + if (pin >= 0) + { + digitalWrite(pin, LOW); + } + setRfFrequencyDirect(_freqregH, _freqregM, _freqregL); //set carrier frequency for a 0 + } + chartosend = (chartosend >> 1); //get the next bit + while (((uint32_t) (micros() - startuS) < baudPerioduS)); + } + + //stop bits + + startuS = micros(); + + if (pin >= 0) + { + digitalWrite(pin, HIGH); + } + + setRfFrequencyDirect(_ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL); //set carrier frequency + + while ((uint32_t) (micros() - startuS) < (baudPerioduS * 2)); +} + + +void SX127XLT::printRTTYregisters() +{ + +#ifdef SX127XDEBUG1 + Serial.println(F("printRTTYregisters() ")); +#endif + + Serial.print(F("NoShift Registers ")); + Serial.print(_freqregH, HEX); + Serial.print(F(" ")); + Serial.print(_freqregM, HEX); + Serial.print(F(" ")); + Serial.println(_freqregL, HEX); + + Serial.print(F("Shifted Registers ")); + Serial.print(_ShiftfreqregH, HEX); + Serial.print(F(" ")); + Serial.print(_ShiftfreqregM, HEX); + Serial.print(F(" ")); + Serial.println(_ShiftfreqregL, HEX); +} + + +void SX127XLT::endFSKRTTY() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("endFSKRTTY() ")); +#endif + + setMode(MODE_STDBY_RC); +} + + +void SX127XLT::doAFC() +{ + #ifdef SX127XDEBUG1 + Serial.println(F("doAFC() ")); + #endif + + _savedOffset = _savedOffset - getFrequencyErrorHz(); + setRfFrequency(_savedFrequency, _savedOffset); //adjust the operating frequency for AFC +} + + +void SX127XLT::doAFCPPM() +{ + #ifdef SX127XDEBUG1 + Serial.println(F("doAFCPPM() ")); + #endif + + int32_t frequencyerror; + float Ferr_ppm; //ppm error + int8_t PPM_offset; + + frequencyerror = getFrequencyErrorHz(); + _savedOffset = _savedOffset - frequencyerror; + setRfFrequency(_savedFrequency, _savedOffset); //adjust the operating frequency for AFC + + //now deal with the PPM correction + Ferr_ppm = frequencyerror / (_savedFrequency/1E6); + PPM_offset = 0.95 * Ferr_ppm; + writeRegister(REG_PPMCORRECTION,PPM_offset); //write PPM adjust value to device register +} + + +uint8_t SX127XLT::getPPM() +{ + #ifdef SX127XDEBUG1 + Serial.println(F("getPPM() ")); + #endif + + return readRegister(REG_PPMCORRECTION); +} + + +int32_t SX127XLT::getOffset() +{ + #ifdef SX127XDEBUG1 + Serial.println(F("getOffset() ")); + #endif + return _savedOffset; +} + + +uint8_t SX127XLT::readBufferbytes(uint8_t *buffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("readBufferbytes() ")); +#endif + + uint8_t ptr = 0, regdata, index; + + for (index = 1; index <= size; index++) + { + regdata = SPI.transfer(0); + buffer[ptr] = regdata; //fill the buffer. + ptr++; + } + + _RXPacketL = _RXPacketL + size; //increment count of bytes read and written to buffer + + return index; //return the actual size of the buffer +} + + +uint8_t SX127XLT::writeBufferbytes(uint8_t *buffer, uint8_t size) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeBufferbytes() ")); +#endif + + uint8_t regdata, index; + + for (index = 0; index < size; index++) + { + regdata = buffer[index]; + SPI.transfer(regdata); + } + + _TXPacketL = _TXPacketL + size; //increment count of bytes read and written to buffer + + return index; //return the actual size of the buffer +} + + + +void SX127XLT::setDevicePABOOST() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("writeBufferbytes() ")); +#endif + +bitSet(_Device, 4); //set bit 4 of _Device type which defines device as using PABoost RF output +} + + +void SX127XLT::setDeviceRFO() +{ +#ifdef SX127XDEBUG1 + Serial.println(F("setDeviceRFO() ")); +#endif + +bitClear(_Device, 4); //clear bit 4 of _Device type which defines device as using RFO RF output +} + + + + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ diff --git a/lib/SX12XX-LoRa/src/SX127XLT.h b/lib/SX12XX-LoRa/src/SX127XLT.h new file mode 100644 index 0000000..e42a0ee --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX127XLT.h @@ -0,0 +1,263 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 17/12/19 + New version 23/12/20 +*/ + + +#ifndef SX127XLT_h +#define SX127XLT_h + +#include +#include + + +class SX127XLT +{ + + public: + + SX127XLT(); + + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device); + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, uint8_t device); + bool begin(int8_t pinNSS, uint8_t device); + void resetDevice(); + void setMode(uint8_t modeconfig); + void setSleep(uint8_t sleepconfig); + bool checkDevice(); + void wake(); + void calibrateImage(uint8_t null); + uint16_t CRCCCITT(uint8_t *buffer, uint16_t size, uint16_t startvalue); + uint16_t CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue); + + void setDevice(uint8_t type); + void printDevice(); + uint8_t getOperatingMode(); + bool isReceiveDone(); + bool isTransmitDone(); + + void writeRegister( uint8_t address, uint8_t value ); + uint8_t readRegister( uint8_t address ); + void printRegisters(uint16_t start, uint16_t end); + void printRegister(uint8_t reg); + void printOperatingMode(); + void printOperatingSettings(); + + void setTxParams(int8_t txPower, uint8_t rampTime); + void setPacketParams(uint16_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5); + void setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4); + void setRfFrequency(uint64_t freq64, int32_t offset); + uint32_t getFreqInt(); + int32_t getFrequencyErrorRegValue(); + int32_t getFrequencyErrorHz(); + + void setTx(uint32_t timeout); + void setRx(uint32_t timeout); + bool readTXIRQ(); + bool readRXIRQ(); + + + void setLowPowerReceive(); + void setHighSensitivity(); + void setRXGain(uint8_t config); + + uint8_t getAGC(); + uint8_t getLNAgain(); + uint8_t getCRCMode(); + uint8_t getHeaderMode(); + uint8_t getLNAboostHF(); + uint8_t getLNAboostLF(); + uint8_t getOpmode(); + uint8_t getPacketMode(); + + uint8_t readRXPacketL(); + uint8_t readTXPacketL(); + int16_t readPacketRSSI(); + int16_t readCurrentRSSI(); + int8_t readPacketSNR(); + bool readPacketCRCError(); + bool readPacketHeaderValid(); + uint8_t packetOK(); + uint8_t readRXPacketType(); + uint8_t readRXDestination(); + uint8_t readRXSource(); + + void setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress); + void setPacketType(uint8_t PacketType); + + void clearIrqStatus( uint16_t irqMask ); + uint16_t readIrqStatus(); + void setDioIrqParams(uint16_t irqMask, uint16_t dio0Mask, uint16_t dio1Mask, uint16_t dio2Mask ); + void printIrqStatus(); + + + void printASCIIPacket(uint8_t *buff, uint8_t tsize); + void printHEXPacket(uint8_t *buff, uint8_t tsize); + void printASCIIorHEX(uint8_t temp); + void printHEXByte(uint8_t temp); + void printHEXByte0x(uint8_t temp); + + bool isRXdone(); + bool isTXdone(); + bool isRXdoneIRQ(); + bool isTXdoneIRQ(); + void setTXDonePin(uint8_t pin); + void setRXDonePin(uint8_t pin); + + //******************************************************************************* + //Packet Read and Write Routines + //******************************************************************************* + + uint8_t receive(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait); + uint8_t receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint32_t rxtimeout, uint8_t wait); + uint8_t readPacket(uint8_t *rxbuffer, uint8_t size); + uint8_t readPacketAddressed(uint8_t *rxbuffer, uint8_t size); + + uint8_t transmit(uint8_t *txbuffer, uint8_t size, uint32_t txtimeout, int8_t txPower, uint8_t wait); + uint8_t transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t txtimeout, int8_t txpower, uint8_t wait); + + //******************************************************************************* + //LoRa specific routines + //******************************************************************************* + + void setupLoRa(uint32_t Frequency, int32_t Offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint8_t modParam4); + + uint8_t getLoRaSF(); + uint8_t getLoRaCodingRate(); + uint8_t getOptimisation(); + uint8_t getSyncWord(); + uint8_t getInvertIQ(); + uint8_t getVersion(); + uint16_t getPreamble(); + + uint32_t returnBandwidth(uint8_t BWregvalue); + uint8_t returnOptimisation(uint8_t SpreadingFactor, uint8_t Bandwidth); + float calcSymbolTime(float Bandwidth, uint8_t SpreadingFactor); + void printModemSettings(); + void setSyncWord(uint8_t syncword); + void setTXDirect(); + void setupDirect(uint32_t frequency, int32_t offset); + void toneFM(uint16_t frequency, uint32_t length, uint32_t deviation, float adjust, int8_t txpower); + int8_t getDeviceTemperature(); + void fskCarrierOn(int8_t txpower); + void fskCarrierOff(); + void setRfFrequencyDirect(uint8_t high, uint8_t mid, uint8_t low); + void getRfFrequencyRegisters(uint8_t *buff); + void startFSKRTTY(uint32_t freqshift, uint8_t pips, uint16_t pipDelaymS, uint16_t pipPeriodmS, uint16_t leadinmS); + void transmitFSKRTTY(uint8_t chartosend, uint8_t databits, uint8_t stopbits, uint8_t parity, uint16_t baudPerioduS, int8_t pin); + void transmitFSKRTTY(uint8_t chartosend, uint16_t baudPerioduS, int8_t pin); + void printRTTYregisters(); + void endFSKRTTY(); + void doAFC(); + void doAFCPPM(); + uint8_t getPPM(); + int32_t getOffset(); + void printOCPTRIM(); + uint8_t readBufferbytes(uint8_t *rxbuffer, uint8_t size); + uint8_t writeBufferbytes(uint8_t *txbuffer, uint8_t size); + void setDevicePABOOST(); + void setDeviceRFO(); + + //******************************************************************************* + //Read Write SX12xxx Buffer commands, this is the buffer internal to the SX12xxxx + //******************************************************************************* + + uint8_t receiveSXBuffer(uint8_t startaddr, uint32_t rxtimeout, uint8_t wait); + uint8_t transmitSXBuffer(uint8_t startaddr, uint8_t length, uint32_t txtimeout, int8_t txpower, uint8_t wait); + + void printSXBufferHEX(uint8_t start, uint8_t end); + void printSXBufferASCII(uint8_t start, uint8_t end); + void fillSXBuffer(uint8_t startaddress, uint8_t size, uint8_t character); + uint8_t getByteSXBuffer(uint8_t addr); + void writeByteSXBuffer(uint8_t addr, uint8_t regdata); + + void startWriteSXBuffer(uint8_t ptr); + uint8_t endWriteSXBuffer(); + void startReadSXBuffer(uint8_t ptr); + uint8_t endReadSXBuffer(); + + void writeUint8(uint8_t x); + uint8_t readUint8(); + + void writeInt8(int8_t x); + int8_t readInt8(); + + void writeChar(char x); + char readChar(); + + void writeUint16(uint16_t x); + uint16_t readUint16(); + + void writeInt16(int16_t x); + int16_t readInt16(); + + void writeUint32(uint32_t x); + uint32_t readUint32(); + + void writeInt32(int32_t x); + int32_t readInt32(); + + void writeFloat(float x); + float readFloat(); + + void writeBuffer(uint8_t *txbuffer, uint8_t size); + void writeBufferChar(char *txbuffer, uint8_t size); + void writeBufferChar(char *txbuffer); + uint8_t readBuffer(uint8_t *rxbuffer); + uint8_t readBuffer(uint8_t *rxbuffer, uint8_t size); + uint8_t readBufferChar(char *rxbuffer); + + //******************************************************************************* + //RX\TX Enable routines - Not yet tested as of 02/12/19 + //******************************************************************************* + + void rxtxInit(int8_t pinRXEN, int8_t pinTXEN); //not used on current SX127x modules + void rxEnable(); //not used on current SX127x modules + void txEnable(); //not used on current SX127x modules + + //******************************************************************************* + //Library variables + //******************************************************************************* + + private: + + int8_t _NSS, _NRESET, _DIO0, _DIO1, _DIO2; + uint8_t _RXPacketL; //length of packet received + uint8_t _RXPacketType; //type number of received packet + uint8_t _RXDestination; //destination address of received packet + uint8_t _RXSource; //source address of received packet + uint8_t _TXPacketL; //length of transmitted packet + uint16_t _IRQmsb; //for setting additional flags + uint8_t _Device; //saved device type + int8_t _TXDonePin; //the pin that will indicate TX done + int8_t _RXDonePin; //the pin that will indicate RX done + uint8_t _UseCRC; //when packet parameters are set this flag is set if CRC on packets in use + int8_t _RXEN, _TXEN; //for modules that have RX TX pin switching + uint8_t _PACKET_TYPE; //used to save the set packet type + uint8_t _freqregH, _freqregM, _freqregL; //the registers values for the set frequency + uint8_t _ShiftfreqregH, _ShiftfreqregM, _ShiftfreqregL; //register values for shifted frequency, used in FSK RTTY etc + uint32_t _savedFrequency; //when setRfFrequency() is used the set frequency is saved + int32_t _savedOffset; //when setRfFrequency() is used the set offset is saved +}; +#endif + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ diff --git a/lib/SX12XX-LoRa/src/SX127XLT_Definitions.h b/lib/SX12XX-LoRa/src/SX127XLT_Definitions.h new file mode 100644 index 0000000..24720b0 --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX127XLT_Definitions.h @@ -0,0 +1,314 @@ +/* + Copyright 2019 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 17/12/19 +*/ + +#define LORA_MAC_PRIVATE_SYNCWORD 0x12 +#define LORA_MAC_PUBLIC_SYNCWORD 0x34 + +//radio operatine modes - see RegOpMode in register map +#define MODE_SLEEP 0x00 +#define MODE_STDBY 0x01 +#define MODE_STDBY_RC 0x01 + +#define MODE_FSTX 0x02 //Frequency synthesis TX mode +#define MODE_TX 0x03 //TX mode +#define MODE_FSRX 0x04 //Frequency synthesis RX mode +#define MODE_RXCONTINUOUS 0x05 //RX continuous mode +#define MODE_RXSINGLE 0x06 //RX single mode + +#define MODE_CAD 0xFF //RX CAD mode + +#define POWERSAVE 0xC0 //select minimum LNA gain +#define BOOSTED 0x38 //mode for booted, max LNA gain + +#define LNAGAING1 0x20 //maximum LNA gain +#define LNAGAING2 0x40 +#define LNAGAING3 0x60 +#define LNAGAING4 0x80 +#define LNAGAING5 0xA0 +#define LNAGAING6 0xC0 //minimum LNA gain + +#define PACKET_TYPE_GFSK 0x00 //regopmode setting for FSK and direct mode +#define PACKET_TYPE_LORA 0x80 //regopmode setting for LoRa +#define PACKET_TYPE_NONE 0x0F + + +#define RADIO_RAMP_10_US 0x0F +#define RADIO_RAMP_12_US 0x0E +#define RADIO_RAMP_15_US 0x0D +#define RADIO_RAMP_20_US 0x0C +#define RADIO_RAMP_25_US 0x0B +#define RADIO_RAMP_31_US 0x0A +#define RADIO_RAMP_40_US 0x09 +#define RADIO_RAMP_50_US 0x08 +#define RADIO_RAMP_62_US 0x07 +#define RADIO_RAMP_100_US 0x06 +#define RADIO_RAMP_125_US 0x05 +#define RADIO_RAMP_250_US 0x04 +#define RADIO_RAMP_500_US 0x03 +#define RADIO_RAMP_1000_US 0x02 +#define RADIO_RAMP_2000_US 0x01 +#define RADIO_RAMP_3400_US 0x00 +#define RADIO_RAMP_DEFAULT 0x09 + +#define OCP_TRIM_ON 0x20 +#define OCP_TRIM_OFF 0x00 +#define OCP_TRIM_45MA 0x00 +#define OCP_TRIM_80MA 0x07 +#define OCP_TRIM_100MA 0x0B +#define OCP_TRIM_110MA 0x0D +#define OCP_TRIM_120MA 0x0F +#define OCP_TRIM_130MA 0x10 +#define OCP_TRIM_140MA 0x11 +#define OCP_TRIM_150MA 0x12 + +//Constant names for bandwidth settings +#define LORA_BW_500 144 //actual 500000hz +#define LORA_BW_250 128 //actual 250000hz +#define LORA_BW_125 112 //actual 125000hz +#define LORA_BW_062 96 //actual 62500hz +#define LORA_BW_041 80 //actual 41670hz +#define LORA_BW_031 64 //actual 31250hz +#define LORA_BW_020 48 //actual 20830hz +#define LORA_BW_015 32 //actual 15630hz +#define LORA_BW_010 16 //actual 10420hz +#define LORA_BW_007 0 //actual 7810hz + + +//for SX127x +#define LORA_SF6 0x06 +#define LORA_SF7 0x07 +#define LORA_SF8 0x08 +#define LORA_SF9 0x09 +#define LORA_SF10 0x0A +#define LORA_SF11 0x0B +#define LORA_SF12 0x0C + + +#define LORA_CR_4_5 0x02 +#define LORA_CR_4_6 0x04 +#define LORA_CR_4_7 0x06 +#define LORA_CR_4_8 0x08 + +#define LDRO_OFF 0x00 +#define LDRO_ON 0x01 +#define LDRO_AUTO 0x02 //when set causes LDRO to be automatically calculated + +#define WAIT_RX 0x01 +#define WAIT_TX 0x01 +#define NO_WAIT 0x00 + +#define FREQ_STEP 61.03515625 + +//These are the &/AND values for reading a parameter from a register. +//For example the Bandwidth on a SX1278 is stored in bits 7-4 and those bits are +//in effect numbers from 0 to 9, where 0 = 7800hz and 9 = 500000hz. Thus to read +//the bandwidth value you need to &/AND the contents of the register with a value +//The registers and values are different for SX1272 and the rest, so they are identified +//by _2 and _X respectivly. To read all the bits of a register, appart from the setting +//use the &/AND value with all bits inverted. + +#define READ_BW_AND_2 0xC0 //register 0x1D +#define READ_BW_AND_X 0xF0 //register 0x1D + +#define READ_CR_AND_2 0x38 //register 0x1D +#define READ_CR_AND_X 0x0E //register 0x1D + +#define READ_SF_AND_2 0xF0 //register 0x1E +#define READ_SF_AND_X 0xF0 //register 0x1E + +#define READ_HASCRC_AND_2 0x02 //register 0x1D +#define READ_HASCRC_AND_X 0x04 //register 0x1E + +#define READ_LDRO_AND_2 0x01 //register 0x1D +#define READ_LDRO_AND_X 0x08 //register 0x26 + +#define READ_AGCAUTO_AND_2 0x04 //register 0x1E +#define READ_AGCAUTO_AND_X 0x04 //register 0x26 + +#define READ_IMPLCIT_AND_2 0x04 //register 0x1D +#define READ_IMPLCIT_AND_X 0x01 //register 0x1D + +#define READ_LNAGAIN_AND_2 0xE0 //register 0x0C +#define READ_LNAGAIN_AND_X 0xE0 //register 0x0C + +#define READ_LNABOOSTHF_AND_2 0x03 //register 0x0C +#define READ_LNABOOSTHF_AND_X 0x03 //register 0x0C + +#define READ_LNABOOSTLF_AND_2 0x18 //register 0x0C +#define READ_LNABOOSTLF_AND_X 0x18 //register 0x0C + +#define READ_OPMODE_AND_2 0x18 //register 0x01 +#define READ_OPMODE_AND_X 0x18 //register 0x01 + +#define READ_RANGEMODE_AND_2 0x80 //register 0x01 +#define READ_RANGEMODE_AND_X 0x80 //register 0x01 + + + +#define LORA_PACKET_VARIABLE_LENGTH 0x00 +#define LORA_PACKET_FIXED_LENGTH 0x01 +#define LORA_PACKET_EXPLICIT LORA_PACKET_VARIABLE_LENGTH +#define LORA_PACKET_IMPLICIT LORA_PACKET_FIXED_LENGTH + +//for SX127x +#define LORA_CRC_ON 0x01 //Packet CRC is activated +#define LORA_CRC_OFF 0x00 //Packet CRC not used + +#define LORA_IQ_NORMAL 0x00 +#define LORA_IQ_INVERTED 0x40 + + +//For SX127x - mapping of these IRQs to the SX126x and SX128x style is not easy +//the values have been fixed to these following DIOs. For instance IRQ_RX_DONE, +//IRQ_TX_DONE and IRQ_CAD_DONE can only be mapped to DIO0. +//For most applications only DIO0, DIO1 and DIO2 are connected. + +#define IRQ_RADIO_NONE 0x00 +#define IRQ_CAD_ACTIVITY_DETECTED 0x01 //active on DIO1 +#define IRQ_FSHS_CHANGE_CHANNEL 0x02 //active on DIO2 +#define IRQ_CAD_DONE 0x04 //active on DIO0 +#define IRQ_TX_DONE 0x08 //active on DIO0 +#define IRQ_HEADER_VALID 0x10 //read from IRQ register only +#define IRQ_CRC_ERROR 0x20 //read from IRQ register only +#define IRQ_RX_DONE 0x40 //active on DIO0 +#define IRQ_RADIO_ALL 0xFFFF + +#define IRQ_TX_TIMEOUT 0x0100 //so that readIrqstatus can return additional detections +#define IRQ_RX_TIMEOUT 0x0200 //so that readIrqstatus can return additional detections +#define IRQ_NO_PACKET_CRC 0x0400 //so that readIrqstatus can return additional detections + + +#define CONFIGURATION_RETENTION 0x04 //these have no effect in SX127x, kept for compatibility +#define RTC_TIMEOUT_ENABLE 0x01 + + +//SX127x Register names +const uint8_t REG_FIFO = 0x00; +const uint8_t WREG_FIFO = 0x80; //this is the write address for the FIFO +const uint8_t REG_OPMODE = 0x01; +const uint8_t REG_FDEVLSB = 0x05; +const uint8_t REG_FRMSB = 0x06; +const uint8_t REG_FRMID = 0x07; +const uint8_t REG_FRLSB = 0x08; +const uint8_t REG_PACONFIG = 0x09; +const uint8_t REG_PARAMP = 0x0A; +const uint8_t REG_OCP = 0x0B; +const uint8_t REG_LNA = 0x0C; +const uint8_t REG_FIFOADDRPTR = 0x0D; +const uint8_t REG_FIFOTXBASEADDR = 0x0E; +const uint8_t REG_FIFORXBASEADDR = 0x0F; +const uint8_t REG_FIFORXCURRENTADDR = 0x10; +const uint8_t REG_IRQFLAGSMASK = 0x11; +const uint8_t REG_IRQFLAGS = 0x12; +const uint8_t REG_RXNBBYTES = 0x13; +const uint8_t REG_RXHEADERCNTVALUEMSB = 0x14; +const uint8_t REG_RXHEADERCNTVALUELSB = 0x15; +const uint8_t REG_RXPACKETCNTVALUEMSB = 0x16; +const uint8_t REG_RXPACKETCNTVALUELSB = 0x17; +const uint8_t REG_PKTSNRVALUE = 0x19; +const uint8_t REG_PKTRSSIVALUE = 0x1A; +const uint8_t REG_RSSIVALUE = 0x1B; +const uint8_t REG_CURRENTRSSIVALUE = 0x1B; +const uint8_t REG_HOPCHANNEL = 0x1C; +const uint8_t REG_MODEMCONFIG1 = 0x1D; +const uint8_t REG_MODEMCONFIG2 = 0x1E; +const uint8_t REG_SYMBTIMEOUTLSB = 0x1F; +const uint8_t REG_PREAMBLEMSB = 0x20; +const uint8_t REG_PREAMBLELSB = 0x21; +const uint8_t REG_PAYLOADLENGTH = 0x22; +const uint8_t REG_FIFORXBYTEADDR = 0x25; +const uint8_t REG_MODEMCONFIG3 = 0x26; +const uint8_t REG_PPMCORRECTION = 0x27; +const uint8_t REG_FEIMSB = 0x28; +const uint8_t REG_FEIMID = 0x29; +const uint8_t REG_FEILSB = 0x2A; +const uint8_t REG_LRRSSIWIDEBAND = 0x2C; +const uint8_t REG_LRTEST2F = 0x2F; +const uint8_t REG_LRTEST30 = 0x30; +const uint8_t REG_DETECTOPTIMIZE = 0x31; +const uint8_t REG_INVERTIQ = 0x33; +const uint8_t REG_LRTEST36 = 0x36; +const uint8_t REG_HIGHBWOPTIMIZE1 = 0x36; +const uint8_t REG_LRDETECTIONTHRESHOLD = 0x37; +const uint8_t REG_DETECTIONTHRESHOLD = 0x37; +const uint8_t REG_SYNCWORD = 0x39; +const uint8_t REG_LRTEST3A = 0x3A; +const uint8_t REG_HIGHBWOPTIMIZE2 = 0x3A; +const uint8_t REG_IMAGECAL = 0x3B; +const uint8_t REG_INVERTIQ2 = 0x3B; +const uint8_t REG_TEMP = 0x3C; +const uint8_t REG_DIOMAPPING1 = 0x40; +const uint8_t REG_DIOMAPPING2 = 0x41; +const uint8_t REG_VERSION = 0x42; +const uint8_t REG_PLLHOP = 0x44; +const uint8_t REG_PADAC = 0x4D; + + +#define PRINT_LOW_REGISTER 0x00 +#define PRINT_HIGH_REGISTER 0x4F + +#define DEVICE_SX1272 0x10 //for modules that use the PA_BOOST pin for RF output +#define DEVICE_SX1276 0x11 //bit 4 set indicates PA_BOOST in use +#define DEVICE_SX1277 0x12 +#define DEVICE_SX1278 0x13 +#define DEVICE_SX1279 0x14 + + +#define DEVICE_SX1272_PABOOST 0x10 //for modules that use the RF_BOOST pin for RF output +#define DEVICE_SX1276_PABOOST 0x11 //bit 4 set indicates PA_BOOST in use +#define DEVICE_SX1277_PABOOST 0x12 +#define DEVICE_SX1278_PABOOST 0x13 +#define DEVICE_SX1279_PABOOST 0x14 + +//no support for SX1272 modules using RFO output, dont have one to test +#define DEVICE_SX1276_RFO 0x01 //for modules that use the RFO LF_ANT or HF_ANT pin for RF output +#define DEVICE_SX1277_RFO 0x02 //bit 4 clear indicates RFO in use +#define DEVICE_SX1278_RFO 0x03 +#define DEVICE_SX1279_RFO 0x04 + + +//power settings +#define MAXPOWER11dBm 0x00 //REG_PACONFIG = x000xxxx +#define MAXPOWER14dBm 0x50 //REG_PACONFIG = x101xxxx +#define MAXPOWER17dBm 0x70 //REG_PACONFIG = x111xxxx +#define PABOOSTON 0x80 +#define PABOOSTOFF 0x00 + + + +//SPI settings +#define LTspeedMaximum 8000000 +#define LTdataOrder MSBFIRST +#define LTdataMode SPI_MODE0 + +#define Deviation5khz 0x52 + + +//FSKRTTY Settings +#define ParityNone 0 +#define ParityOdd 1 +#define ParityEven 2 +#define ParityZero 0xF0 +#define ParityOne 0xF1 + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ diff --git a/lib/SX12XX-LoRa/src/SX128XLT.cpp b/lib/SX12XX-LoRa/src/SX128XLT.cpp new file mode 100644 index 0000000..1b81d32 --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX128XLT.cpp @@ -0,0 +1,2759 @@ +/* + Copyright 2019 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + 06/02/20 +*/ + +/* +Parts of code Copyright (c) 2013, SEMTECH S.A. +See LICENSE.TXT file included in the library +*/ + +#include +#include + +#define LTUNUSED(v) (void) (v) //add LTUNUSED(variable); to avoid compiler warnings +#define USE_SPI_TRANSACTION + +//#define SX128XDEBUG //enable debug messages +//#define RANGINGDEBUG //enable debug messages for ranging +//#define SX128XDEBUGRXTX //enable debug messages for RX TX switching +//#define SX128XDEBUGPINS //enable pin allocation debug messages + +SX128XLT::SX128XLT() +{ +} + +/* Formats for :begin +1 All pins > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, uint8_t device) +2 NiceRF > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device) +3 Ebyte > begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device); +*/ + + +bool SX128XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, uint8_t device) +{ + + //format 1 pins, assign all available pins + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = pinDIO2; + _DIO3 = pinDIO3; + _RXEN = pinRXEN; + _TXEN = pinTXEN; + _Device = device; + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + + +#ifdef SX128XDEBUGPINS + Serial.println(F("begin()")); + Serial.println(F("SX128XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TX_EN ")); + Serial.println(_TXEN); +#endif + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + if (_DIO2 >= 0) + { + pinMode( _DIO2, INPUT); + } + + if (_DIO3 >= 0) + { + pinMode( _DIO3, INPUT); + } + + if ((_RXEN >= 0) && (_TXEN >= 0)) + { + #ifdef SX128XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching enabled")); + #endif + pinMode(_RXEN, OUTPUT); + pinMode(_TXEN, OUTPUT); + _rxtxpinmode = true; + } + else + { + #ifdef SX128XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching disabled")); + #endif + _rxtxpinmode = false; + } + + resetDevice(); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool SX128XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device) +{ + //format 2 pins for NiceRF, NSS, NRESET, RFBUSY, DIO1 + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = -1; + _DIO3 = -1; + _RXEN = -1; //not defined, so mark as unused + _TXEN = -1; //not defined, so mark as unused + _Device = device; + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + +#ifdef SX128XDEBUGPINS + Serial.println(F("format 2 NiceRF begin()")); + Serial.println(F("SX128XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TX_EN ")); + Serial.println(_TXEN); +#endif + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + #ifdef SX128XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching disabled")); + #endif + + _rxtxpinmode = false; + + resetDevice(); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +bool SX128XLT::begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device) +{ + //format 3 pins for Ebyte, NSS, NRESET, RFBUSY, DIO1, RX_EN, TX_EN + _NSS = pinNSS; + _NRESET = pinNRESET; + _RFBUSY = pinRFBUSY; + _DIO1 = pinDIO1; + _DIO2 = -1; + _DIO3 = -1; + _RXEN = pinRXEN; + _TXEN = pinTXEN; + _Device = device; + _TXDonePin = pinDIO1; //this is defalt pin for sensing TX done + _RXDonePin = pinDIO1; //this is defalt pin for sensing RX done + + pinMode(_NSS, OUTPUT); + digitalWrite(_NSS, HIGH); + pinMode(_NRESET, OUTPUT); + digitalWrite(_NRESET, LOW); + pinMode(_RFBUSY, INPUT); + +#ifdef SX128XDEBUGPINS + Serial.println(F("format 3 Ebyte begin()")); + Serial.println(F("SX128XLT constructor instantiated successfully")); + Serial.print(F("NSS ")); + Serial.println(_NSS); + Serial.print(F("NRESET ")); + Serial.println(_NRESET); + Serial.print(F("RFBUSY ")); + Serial.println(_RFBUSY); + Serial.print(F("DIO1 ")); + Serial.println(_DIO1); + Serial.print(F("DIO2 ")); + Serial.println(_DIO2); + Serial.print(F("DIO3 ")); + Serial.println(_DIO3); + Serial.print(F("RX_EN ")); + Serial.println(_RXEN); + Serial.print(F("TX_EN ")); + Serial.println(_TXEN); +#endif + + if (_DIO1 >= 0) + { + pinMode( _DIO1, INPUT); + } + + if ((_RXEN >= 0) && (_TXEN >= 0)) + { + #ifdef SX128XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching enabled")); + #endif + pinMode(_RXEN, OUTPUT); + pinMode(_TXEN, OUTPUT); + _rxtxpinmode = true; + } + else + { + #ifdef SX128XDEBUGPINS + Serial.println(F("RX_EN & TX_EN switching disabled")); + #endif + _rxtxpinmode = false; + } + + resetDevice(); + + if (checkDevice()) + { + return true; + } + + return false; +} + + +void SX128XLT::rxEnable() +{ + //Enable RX mode on device such as Ebyte E28-2G4M20S which have RX and TX enable pins + #ifdef SX128XDEBUGRXTX + Serial.println(F("rxEnable()")); + #endif + + digitalWrite(_RXEN, HIGH); + digitalWrite(_TXEN, LOW); +} + + +void SX128XLT::txEnable() +{ + //Enable RX mode on device such as Ebyte E28-2G4M20S which have RX and TX enable pins +#ifdef SX128XDEBUGRXTX + Serial.println(F("txEnable()")); +#endif + + digitalWrite(_RXEN, LOW); + digitalWrite(_TXEN, HIGH); +} + + + +void SX128XLT::checkBusy() +{ +#ifdef SX128XDEBUG + //Serial.println(F("checkBusy()")); +#endif + + uint8_t busy_timeout_cnt; + busy_timeout_cnt = 0; + + while (digitalRead(_RFBUSY)) + { + delay(1); + busy_timeout_cnt++; + + if (busy_timeout_cnt > 10) //wait 5mS for busy to complete + { + Serial.println(F("ERROR - Busy Timeout!")); + resetDevice(); + setMode(MODE_STDBY_RC); + config(); //re-run saved config + break; + } + } +} + + +bool SX128XLT::config() +{ +#ifdef SX128XDEBUG + Serial.println(F("config()")); +#endif + + resetDevice(); + setMode(MODE_STDBY_RC); + setRegulatorMode(savedRegulatorMode); + setPacketType(savedPacketType); + setRfFrequency(savedFrequency, savedOffset); + setModulationParams(savedModParam1, savedModParam2, savedModParam3); + setPacketParams(savedPacketParam1, savedPacketParam2, savedPacketParam3, savedPacketParam4, savedPacketParam5, savedPacketParam6, savedPacketParam7); + setDioIrqParams(savedIrqMask, savedDio1Mask, savedDio2Mask, savedDio3Mask); //set for IRQ on RX done on DIO1 + return true; +} + + +void SX128XLT::readRegisters(uint16_t address, uint8_t *buffer, uint16_t size) +{ +#ifdef SX128XDEBUG + //Serial.println(F("readRegisters()")); +#endif + + uint16_t index; + uint8_t addr_l, addr_h; + + addr_h = address >> 8; + addr_l = address & 0x00FF; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + 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); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +uint8_t SX128XLT::readRegister(uint16_t address) +{ +#ifdef SX128XDEBUG + //Serial.println(F("readRegister()")); +#endif + + uint8_t data; + + readRegisters(address, &data, 1); + return data; +} + + +void SX128XLT::writeRegisters(uint16_t address, uint8_t *buffer, uint16_t size) +{ +#ifdef SX128XDEBUG + //Serial.println(F("writeRegisters()")); +#endif + uint8_t addr_l, addr_h; + uint8_t i; + + addr_l = address & 0xff; + addr_h = address >> 8; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + 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); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + //checkBusy(); +} + + +void SX128XLT::writeRegister(uint16_t address, uint8_t value) +{ +#ifdef SX128XDEBUG + //Serial.println(F("writeRegister()")); +#endif + + writeRegisters( address, &value, 1 ); +} + + +void SX128XLT::writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size) +{ +#ifdef SX128XDEBUG + //Serial.print(F("writeCommand() ")); + //Serial.println(Opcode, HEX); +#endif + + uint8_t index; + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(Opcode); + + for (index = 0; index < size; index++) + { + SPI.transfer(buffer[index]); + } + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + if (Opcode != RADIO_SET_SLEEP) + { + checkBusy(); + } +} + + +void SX128XLT::readCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size) +{ +#ifdef SX128XDEBUG + //Serial.println(F("readCommand()")); +#endif + + uint8_t i; + checkBusy(); + + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(Opcode); + SPI.transfer(0xFF); + + for ( i = 0; i < size; i++ ) + { + *(buffer + i) = SPI.transfer(0xFF); + } + digitalWrite(_NSS, HIGH); + + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + //checkBusy(); +} + + +void SX128XLT::resetDevice() +{ +#ifdef SX128XDEBUG + Serial.println(F("resetDevice()")); +#endif + + //timings taken from Semtech library + delay(20); + digitalWrite(_NRESET, LOW); + delay(50); + digitalWrite(_NRESET, HIGH); + delay(20); +} + + +bool SX128XLT::checkDevice() +{ + //check there is a device out there, writes a register and reads back +#ifdef SX128XDEBUG + Serial.println(F("checkDevice()")); +#endif + + uint8_t Regdata1, Regdata2; + Regdata1 = readRegister(0x0908); //low byte of frequency setting + writeRegister(0x0908, (Regdata1 + 1)); + Regdata2 = readRegister(0x0908); //read changed value back + writeRegister(0x0908, Regdata1); //restore register to original value + + if (Regdata2 == (Regdata1 + 1)) + { + return true; + } + else + { + return false; + } +} + + +void SX128XLT::setupLoRa(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3) +{ +#ifdef SX128XDEBUG + Serial.println(F("setupLoRa()")); +#endif + + setMode(MODE_STDBY_RC); + setRegulatorMode(USE_LDO); + setPacketType(PACKET_TYPE_LORA); + setRfFrequency(frequency, offset); + setBufferBaseAddress(0, 0); + setModulationParams(modParam1, modParam2, modParam3); + setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); +} + + +void SX128XLT::setMode(uint8_t modeconfig) +{ +#ifdef SX128XDEBUG + Serial.println(F("setMode()")); +#endif + + uint8_t Opcode = 0x80; + + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + + digitalWrite(_NSS, LOW); + SPI.transfer(Opcode); + SPI.transfer(modeconfig); + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + _OperatingMode = modeconfig; + +} + +void SX128XLT::setRegulatorMode(uint8_t mode) +{ +#ifdef SX128XDEBUG + Serial.println(F("setRegulatorMode()")); +#endif + + savedRegulatorMode = mode; + + writeCommand(RADIO_SET_REGULATORMODE, &mode, 1); +} + +void SX128XLT::setPacketType(uint8_t packettype ) +{ +#ifdef SX128XDEBUG + Serial.println(F("setPacketType()")); +#endif + savedPacketType = packettype; + + writeCommand(RADIO_SET_PACKETTYPE, &packettype, 1); +} + + +void SX128XLT::setRfFrequency(uint32_t frequency, int32_t offset) +{ +#ifdef SX128XDEBUG + Serial.println(F("setRfFrequency()")); +#endif + + savedFrequency = frequency; + savedOffset = offset; + + frequency = frequency + offset; + uint8_t buffer[3]; + uint32_t freqtemp = 0; + freqtemp = ( uint32_t )( (double) frequency / (double)FREQ_STEP); + buffer[0] = ( uint8_t )( ( freqtemp >> 16 ) & 0xFF ); + buffer[1] = ( uint8_t )( ( freqtemp >> 8 ) & 0xFF ); + buffer[2] = ( uint8_t )( freqtemp & 0xFF ); + writeCommand(RADIO_SET_RFFREQUENCY, buffer, 3); +} + +void SX128XLT::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) +{ +#ifdef SX128XDEBUG + Serial.println(F("setBufferBaseAddress()")); +#endif + + uint8_t buffer[2]; + + buffer[0] = txBaseAddress; + buffer[1] = rxBaseAddress; + writeCommand(RADIO_SET_BUFFERBASEADDRESS, buffer, 2); +} + + +void SX128XLT::setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3) +{ +//sequence is spreading factor, bandwidth, coding rate. + +#ifdef SX128XDEBUG + Serial.println(F("setModulationParams()")); +#endif + + uint8_t buffer[3]; + + savedModParam1 = modParam1; + savedModParam2 = modParam2; + savedModParam3 = modParam3; + + buffer[0] = modParam1; + buffer[1] = modParam2; + buffer[2] = modParam3; + + writeCommand(RADIO_SET_MODULATIONPARAMS, buffer, 3); +} + + +void SX128XLT::setPacketParams(uint8_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5, uint8_t packetParam6, uint8_t packetParam7) +{ +//for LoRa order is PreambleLength, HeaderType, PayloadLength, CRC, InvertIQ/chirp invert, not used, not used +//for FLRC order is PreambleLength, SyncWordLength, SyncWordMatch, HeaderType, PayloadLength, CrcLength, Whitening + +#ifdef SX128XDEBUG + Serial.println(F("SetPacketParams()")); +#endif + + savedPacketParam1 = packetParam1; + savedPacketParam2 = packetParam2; + savedPacketParam3 = packetParam3; + savedPacketParam4 = packetParam4; + savedPacketParam5 = packetParam5; + savedPacketParam6 = packetParam6; + savedPacketParam7 = packetParam7; + + uint8_t buffer[7]; + buffer[0] = packetParam1; + buffer[1] = packetParam2; + buffer[2] = packetParam3; + buffer[3] = packetParam4; + buffer[4] = packetParam5; + buffer[5] = packetParam6; + buffer[6] = packetParam7; + writeCommand(RADIO_SET_PACKETPARAMS, buffer, 7); + +} + + +void SX128XLT::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ) +{ +#ifdef SX128XDEBUG + Serial.println(F("setDioIrqParams()")); +#endif + + savedIrqMask = irqMask; + savedDio1Mask = dio1Mask; + savedDio2Mask = dio2Mask; + savedDio3Mask = dio3Mask; + + uint8_t buffer[8]; + + buffer[0] = (uint8_t) (irqMask >> 8); + buffer[1] = (uint8_t) (irqMask & 0xFF); + buffer[2] = (uint8_t) (dio1Mask >> 8); + buffer[3] = (uint8_t) (dio1Mask & 0xFF); + buffer[4] = (uint8_t) (dio2Mask >> 8); + buffer[5] = (uint8_t) (dio2Mask & 0xFF); + buffer[6] = (uint8_t) (dio3Mask >> 8); + buffer[7] = (uint8_t) (dio3Mask & 0xFF); + writeCommand(RADIO_SET_DIOIRQPARAMS, buffer, 8); +} + + +void SX128XLT::setHighSensitivity() +{ + //set bits 7,6 of REG_LNA_REGIME +#ifdef SX128XDEBUG + Serial.println(F("setHighSensitivity()")); +#endif + + writeRegister(REG_LNA_REGIME, (readRegister(REG_LNA_REGIME) | 0xC0)); +} + +void SX128XLT::setLowPowerRX() +{ + //clear bits 7,6 of REG_LNA_REGIME +#ifdef SX128XDEBUG + Serial.println(F("setLowPowerRX()")); +#endif + + writeRegister(REG_LNA_REGIME, (readRegister(REG_LNA_REGIME) & 0x3F)); +} + + +void SX128XLT::printModemSettings() +{ +#ifdef SX128XDEBUG + Serial.println(F("printModemSettings()")); +#endif + + printDevice(); + Serial.print(F(",")); + Serial.print(getFreqInt()); + Serial.print(F("hz")); + + if (savedPacketType == PACKET_TYPE_LORA) + { + Serial.print(F(",SF")); + Serial.print(getLoRaSF()); + Serial.print(F(",BW")); + Serial.print(returnBandwidth(savedModParam2)); + Serial.print(F(",CR4:")); + Serial.print((getLoRaCodingRate() + 4)); + + if (getInvertIQ() == LORA_IQ_INVERTED) + { + Serial.print(F(",IQInverted")); + } + else + { + Serial.print(F(",IQNormal")); + } + + Serial.print(F(",Preamble_")); + Serial.print(getPreamble()); + } + + if (savedPacketType == PACKET_TYPE_FLRC) + { + if (savedPacketParam1 == 0) + { + Serial.print(F(",No_Syncword")); + } + + if (savedPacketParam1 == 4) + { + Serial.print(F(",32bit_Syncword")); + } + + + switch (savedPacketParam3) + { + case RADIO_RX_MATCH_SYNCWORD_OFF: + Serial.print(F(",SYNCWORD_OFF")); + break; + + case RADIO_RX_MATCH_SYNCWORD_1: + Serial.print(F(",SYNCWORD_1")); + break; + + case RADIO_RX_MATCH_SYNCWORD_2: + Serial.print(F(",SYNCWORD_2")); + break; + + case RADIO_RX_MATCH_SYNCWORD_1_2: + Serial.print(F(",SYNCWORD_1_2")); + break; + + case RADIO_RX_MATCH_SYNCWORD_3: + Serial.print(F(",SYNCWORD_3")); + break; + + case RADIO_RX_MATCH_SYNCWORD_1_3: + Serial.print(F(",SYNCWORD_1_3")); + break; + + case RADIO_RX_MATCH_SYNCWORD_2_3: + Serial.print(F(",SYNCWORD_2_3")); + break; + + case RADIO_RX_MATCH_SYNCWORD_1_2_3: + Serial.print(F(",SYNCWORD_1_2_3")); + break; + + default: + Serial.print(F("Unknown_SYNCWORD")); + } + + if (savedPacketParam4 == RADIO_PACKET_FIXED_LENGTH) + { + Serial.print(F(",PACKET_FIXED_LENGTH")); + } + + if (savedPacketParam4 == RADIO_PACKET_VARIABLE_LENGTH) + { + Serial.print(F(",PACKET_VARIABLE_LENGTH")); + } + + switch (savedPacketParam6) + { + case RADIO_CRC_OFF: + Serial.print(F(",CRC_OFF")); + break; + + case RADIO_CRC_1_BYTES: + Serial.print(F(",CRC_1_BYTES")); + break; + + case RADIO_CRC_2_BYTES: + Serial.print(F(",CRC_2_BYTES")); + break; + + case RADIO_CRC_3_BYTES: + Serial.print(F(",CRC_3_BYTES")); + break; + + default: + Serial.print(F(",Unknown_CRC")); + } + + if (savedPacketParam7 == RADIO_WHITENING_ON) + { + Serial.print(F(",WHITENING_ON")); + } + + if (savedPacketParam7 == RADIO_WHITENING_OFF) + { + Serial.print(F(",WHITENING_OFF")); + } + + } + +} + + +void SX128XLT::printDevice() +{ +#ifdef SX128XDEBUG + Serial.println(F("printDevice()")); +#endif + + + switch (_Device) + { + case DEVICE_SX1280: + Serial.print(F("SX1280")); + break; + + case DEVICE_SX1281: + Serial.print(F("SX1281")); + break; + + default: + Serial.print(F("Unknown Device")); + + } +} + + +uint32_t SX128XLT::getFreqInt() +{ + +#ifdef SX128XDEBUG + Serial.println(F("getFreqInt")); +#endif + + //get the current set device frequency, return as long integer + uint8_t Msb = 0; + uint8_t Mid = 0; + uint8_t Lsb = 0; + + uint32_t uinttemp; + float floattemp; + + LTUNUSED(Msb); //to prevent a compiler warning + LTUNUSED(Mid); //to prevent a compiler warning + LTUNUSED(Lsb); //to prevent a compiler warning + + if (savedPacketType == PACKET_TYPE_LORA) + { + Msb = readRegister(REG_RFFrequency23_16); + Mid = readRegister(REG_RFFrequency15_8); + Lsb = readRegister(REG_RFFrequency7_0); + } + + if (savedPacketType == PACKET_TYPE_FLRC) + { + Msb = readRegister(REG_FLRC_RFFrequency23_16); + Mid = readRegister(REG_FLRC_RFFrequency15_8); + Lsb = readRegister(REG_FLRC_RFFrequency7_0); + } + + floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb); + floattemp = ((floattemp * FREQ_STEP) / 1000000ul); + uinttemp = (uint32_t)(floattemp * 1000000); + return uinttemp; +} + + +uint8_t SX128XLT::getLoRaSF() +{ +#ifdef SX128XDEBUG + Serial.println(F("getLoRaSF()")); +#endif + return (savedModParam1 >> 4); +} + + +uint32_t SX128XLT::returnBandwidth(uint8_t data) +{ +#ifdef SX128XDEBUG + Serial.println(F("returnBandwidth()")); +#endif + + switch (data) + { + case LORA_BW_0200: + return 203125; + + case LORA_BW_0400: + return 406250; + + case LORA_BW_0800: + return 812500; + + case LORA_BW_1600: + return 1625000; + + default: + break; + } + + return 0x0; //so that a bandwidth not set can be identified +} + + +uint8_t SX128XLT::getLoRaCodingRate() +{ +#ifdef SX128XDEBUG + Serial.println(F("getLoRaCodingRate")); +#endif + + return savedModParam3; +} + + +uint8_t SX128XLT::getInvertIQ() +{ +//IQ mode reg 0x33 +#ifdef SX128XDEBUG + Serial.println(F("getInvertIQ")); +#endif + + return savedPacketParam5; +} + + +uint16_t SX128XLT::getPreamble() +{ +#ifdef SX128XDEBUG + Serial.println(F("getPreamble")); +#endif + + return savedPacketParam1; +} + +void SX128XLT::printOperatingSettings() +{ +#ifdef SX128XDEBUG + Serial.println(F("printOperatingSettings()")); +#endif + + printDevice(); + + Serial.print(F(",PacketMode_")); + + switch (savedPacketType) + { + case PACKET_TYPE_GFSK: + Serial.print(F("GFSK")); + break; + + case PACKET_TYPE_LORA: + Serial.print(F("LORA")); + break; + + case PACKET_TYPE_RANGING: + Serial.print(F("RANGING")); + break; + + case PACKET_TYPE_FLRC: + Serial.print(F("FLRC")); + break; + + + case PACKET_TYPE_BLE: + Serial.print(F("BLE")); + break; + + default: + Serial.print(F("Unknown")); + + } + + switch (savedPacketParam2) + { + case LORA_PACKET_VARIABLE_LENGTH: + Serial.print(F(",Explicit")); + break; + + case LORA_PACKET_FIXED_LENGTH: + Serial.print(F(",Implicit")); + break; + + default: + Serial.print(F(",Unknown")); + } + + Serial.print(F(",LNAgain_")); + + + if (getLNAgain() == 0xC0) + { + Serial.print(F("HighSensitivity")); + } + else + { + Serial.print(F("LowPowerRX")); + } + +} + + +uint8_t SX128XLT::getLNAgain() +{ +#ifdef SX128XDEBUG + Serial.println(F("getLNAgain")); +#endif + + return (readRegister(REG_LNA_REGIME) & 0xC0); +} + + + +void SX128XLT::printRegisters(uint16_t Start, uint16_t End) +{ + //prints the contents of SX1280 registers to serial monitor + +#ifdef SX128XDEBUG + Serial.println(F("printRegisters()")); +#endif + + 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 SX128XLT::printASCIIPacket(uint8_t *buffer, uint8_t size) +{ +#ifdef SX128XDEBUG + Serial.println(F("printASCIIPacket()")); +#endif + + uint8_t index; + + for (index = 0; index < size; index++) + { + Serial.write(buffer[index]); + } + +} + + +uint8_t SX128XLT::transmit(uint8_t *txbuffer, uint8_t size, uint16_t timeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("transmit()")); +#endif + uint8_t index; + uint8_t bufferdata; + + if (size == 0) + { + return false; + } + + setMode(MODE_STDBY_RC); + setBufferBaseAddress(0, 0); + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(0); + + for (index = 0; index < size; index++) + { + bufferdata = txbuffer[index]; + SPI.transfer(bufferdata); + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + _TXPacketL = size; + + if (savedPacketType == PACKET_TYPE_LORA) + { + writeRegister(REG_LR_PAYLOADLENGTH, _TXPacketL); //only seems to work for lora + } + else if (savedPacketType == PACKET_TYPE_FLRC) + { + setPacketParams(savedPacketParam1, savedPacketParam2, savedPacketParam3, savedPacketParam4, _TXPacketL, savedPacketParam6, savedPacketParam7); + } + + setTxParams(txpower, RAMP_TIME); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1 + setTx(timeout); //this starts the TX + + if (!wait) + { + return _TXPacketL; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RX_TX_TIMEOUT ) //check for timeout + { + return 0; + } + else + { + return _TXPacketL; + } +} + + +void SX128XLT::setTxParams(int8_t TXpower, uint8_t RampTime) +{ +#ifdef SX128XDEBUG + Serial.println(F("setTxParams()")); +#endif + + uint8_t buffer[2]; + + savedTXPower = TXpower; + + //power register is set to 0 to 31 which is -18dBm to +12dBm + buffer[0] = (TXpower + 18); + buffer[1] = (uint8_t)RampTime; + writeCommand(RADIO_SET_TXPARAMS, buffer, 2); +} + + +void SX128XLT::setTx(uint16_t timeout) +{ + +#ifdef SX128XDEBUG + Serial.println(F("setTx()")); +#endif + + if (_rxtxpinmode) + { + txEnable(); + } + + //Serial.print(F("timeout ")); + //Serial.println(timeout); + //Serial.print(F("_PERIODBASE ")); + //Serial.println(_PERIODBASE); + + uint8_t buffer[3]; + + clearIrqStatus(IRQ_RADIO_ALL); //clear all interrupt flags + buffer[0] = _PERIODBASE; + buffer[1] = ( uint8_t )( ( timeout >> 8 ) & 0x00FF ); + buffer[2] = ( uint8_t )( timeout & 0x00FF ); + writeCommand(RADIO_SET_TX, buffer, 3 ); +} + + +void SX128XLT::clearIrqStatus(uint16_t irqMask) +{ +#ifdef SX128XDEBUG + Serial.println(F("clearIrqStatus()")); +#endif + + uint8_t buffer[2]; + + buffer[0] = (uint8_t) (irqMask >> 8); + buffer[1] = (uint8_t) (irqMask & 0xFF); + writeCommand(RADIO_CLR_IRQSTATUS, buffer, 2); +} + + +uint16_t SX128XLT::readIrqStatus() +{ +#ifdef SX128XDEBUG + Serial.print(F("readIrqStatus()")); +#endif + + uint16_t temp; + uint8_t buffer[2]; + + readCommand(RADIO_GET_IRQSTATUS, buffer, 2); + temp = ((buffer[0] << 8) + buffer[1]); + return temp; +} + + +void SX128XLT::printIrqStatus() +{ +#ifdef SX128XDEBUG + Serial.println(F("printIrqStatus()")); +#endif + + uint16_t _IrqStatus; + _IrqStatus = readIrqStatus(); + + //0x0001 + if (_IrqStatus & IRQ_TX_DONE) + { + Serial.print(F(",IRQ_TX_DONE")); + } + + //0x0002 + if (_IrqStatus & IRQ_RX_DONE) + { + Serial.print(F(",IRQ_RX_DONE")); + } + + //0x0004 + if (_IrqStatus & IRQ_SYNCWORD_VALID) + { + Serial.print(F(",IRQ_SYNCWORD_VALID")); + } + + //0x0008 + if (_IrqStatus & IRQ_SYNCWORD_ERROR) + { + Serial.print(F(",IRQ_SYNCWORD_ERROR")); + } + + //0x0010 + if (_IrqStatus & IRQ_HEADER_VALID) + { + Serial.print(F(",IRQ_HEADER_VALID")); + } + + //0x0020 + if (_IrqStatus & IRQ_HEADER_ERROR) + { + Serial.print(F(",IRQ_HEADER_ERROR")); + } + + //0x0040 + if (_IrqStatus & IRQ_CRC_ERROR) + { + Serial.print(F(",IRQ_CRC_ERROR")); + } + + //0x0080 + if (_IrqStatus & IRQ_RANGING_SLAVE_RESPONSE_DONE) + { + Serial.print(F(",IRQ_RANGING_SLAVE_RESPONSE_DONE")); + } + + //0x0100 + if (_IrqStatus & IRQ_RANGING_SLAVE_REQUEST_DISCARDED) + { + Serial.print(",IRQ_RANGING_SLAVE_REQUEST_DISCARDED"); + } + + //0x0200 + if (_IrqStatus & IRQ_RANGING_MASTER_RESULT_VALID) + { + Serial.print(F(",IRQ_RANGING_MASTER_RESULT_VALID")); + } + + //0x0400 + if (_IrqStatus & IRQ_RANGING_MASTER_RESULT_TIMEOUT) + { + Serial.print(F(",IRQ_RANGING_MASTER_RESULT_TIMEOUT")); + } + + //0x0800 + if (_IrqStatus & IRQ_RANGING_SLAVE_REQUEST_VALID) + { + Serial.print(F(",IRQ_RANGING_SLAVE_REQUEST_VALID")); + } + + //0x1000 + if (_IrqStatus & IRQ_CAD_DONE) + { + Serial.print(F(",IRQ_CAD_DONE")); + } + + //0x2000 + if (_IrqStatus & IRQ_CAD_ACTIVITY_DETECTED) + { + Serial.print(F(",IRQ_CAD_ACTIVITY_DETECTED")); + } + + //0x4000 + if (_IrqStatus & IRQ_RX_TX_TIMEOUT) + { + Serial.print(F(",IRQ_RX_TX_TIMEOUT")); + } + + //0x8000 + if (_IrqStatus & IRQ_PREAMBLE_DETECTED) + { + Serial.print(F(",IRQ_PREAMBLE_DETECTED")); + } +} + + +uint16_t SX128XLT::CRCCCITT(uint8_t *buffer, uint8_t size, uint16_t start) +{ +#ifdef SX128XDEBUG + Serial.println(F("CRCCCITT()")); +#endif + + uint16_t index, libraryCRC; + uint8_t j; + + libraryCRC = start; //start value for CRC16 + + for (index = 0; index < size; index++) + { + libraryCRC ^= (((uint16_t)buffer[index]) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + + return libraryCRC; +} + + +uint8_t SX128XLT::receive(uint8_t *rxbuffer, uint8_t size, uint16_t timeout, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("receive()")); +#endif + + uint8_t index, RXstart, RXend; + uint16_t regdata; + uint8_t buffer[2]; + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on RX done or timeout + setRx(timeout); + + if (!wait) + { + return 0; //not wait requested so no packet length to pass + } + + while (!digitalRead(_RXDonePin)); //Wait for DIO1 to go high + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + regdata = readIrqStatus(); + + if ( (regdata & IRQ_HEADER_ERROR) | (regdata & IRQ_CRC_ERROR) | (regdata & IRQ_RX_TX_TIMEOUT ) ) //check if any of the preceding IRQs is set + { + return 0; //packet is errored somewhere so return 0 + } + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + + RXstart = buffer[1]; + + RXend = RXstart + _RXPacketL; + + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(RXstart); + SPI.transfer(0xFF); + + for (index = RXstart; index < RXend; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX128XLT::readPacketRSSI() +{ +#ifdef SX128XDEBUG + Serial.println(F("readPacketRSSI()")); +#endif + + uint8_t status[5]; + + readCommand(RADIO_GET_PACKETSTATUS, status, 5) ; + _PacketRSSI = -status[0] / 2; + + return _PacketRSSI; +} + + +uint8_t SX128XLT::readPacketSNR() +{ +#ifdef SX128XDEBUG + Serial.println(F("readPacketSNR()")); +#endif + + uint8_t status[5]; + + readCommand(RADIO_GET_PACKETSTATUS, status, 5) ; + + if ( status[1] < 128 ) + { + _PacketSNR = status[1] / 4 ; + } + else + { + _PacketSNR = (( status[1] - 256 ) / 4); + } + + return _PacketSNR; +} + + +uint8_t SX128XLT::readRXPacketL() +{ +#ifdef SX128XDEBUG + Serial.println(F("readRXPacketL()")); +#endif + + uint8_t buffer[2]; + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + return _RXPacketL; +} + + +void SX128XLT::setRx(uint16_t timeout) +{ +#ifdef SX128XDEBUG + Serial.println(F("setRx()")); +#endif + + if (_rxtxpinmode) + { + rxEnable(); + } + + uint8_t buffer[3]; + + clearIrqStatus(IRQ_RADIO_ALL); //clear all interrupt flags + buffer[0] = _PERIODBASE; //use pre determined period base setting + buffer[1] = ( uint8_t ) ((timeout >> 8 ) & 0x00FF); + buffer[2] = ( uint8_t ) (timeout & 0x00FF); + writeCommand(RADIO_SET_RX, buffer, 3); +} + +/*************************************************************************** +//Start direct access SX buffer routines +***************************************************************************/ + +void SX128XLT::startWriteSXBuffer(uint8_t ptr) +{ +#ifdef SX128XDEBUG + Serial.println(F("startWriteSXBuffer()")); +#endif + + _TXPacketL = 0; //this variable used to keep track of bytes written + setMode(MODE_STDBY_RC); + setBufferBaseAddress(ptr, 0); //TX,RX + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(ptr); //address in SX buffer to write to + //SPI interface ready for byte to write to buffer +} + + +uint8_t SX128XLT::endWriteSXBuffer() +{ +#ifdef SX128XDEBUG + Serial.println(F("endWriteSXBuffer()")); +#endif + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _TXPacketL; + +} + + +void SX128XLT::startReadSXBuffer(uint8_t ptr) +{ +#ifdef SX128XDEBUG + Serial.println(F("startReadSXBuffer")); +#endif + + _RXPacketL = 0; + + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); + #endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(ptr); + SPI.transfer(0xFF); + + //next line would be data = SPI.transfer(0); + //SPI interface ready for byte to read from +} + + +uint8_t SX128XLT::endReadSXBuffer() +{ +#ifdef SX128XDEBUG + Serial.println(F("endReadSXBuffer()")); +#endif + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; +} + + +void SX128XLT::writeUint8(uint8_t x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeUint8()")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + +uint8_t SX128XLT::readUint8() +{ +#ifdef SX128XDEBUG + Serial.println(F("readUint8()")); +#endif + byte x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX128XLT::writeInt8(int8_t x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeInt8()")); +#endif + + SPI.transfer(x); + + _TXPacketL++; //increment count of bytes written +} + + +int8_t SX128XLT::readInt8() +{ +#ifdef SX128XDEBUG + Serial.println(F("readInt8()")); +#endif + int8_t x; + + x = SPI.transfer(0); + + _RXPacketL++; //increment count of bytes read + return (x); +} + + +void SX128XLT::writeInt16(int16_t x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeInt16()")); +#endif + + SPI.transfer(lowByte(x)); + SPI.transfer(highByte(x)); + + _TXPacketL = _TXPacketL + 2; //increment count of bytes written +} + + +int16_t SX128XLT::readInt16() +{ +#ifdef SX128XDEBUG + Serial.println(F("readInt16()")); +#endif + byte lowbyte, highbyte; + + lowbyte = SPI.transfer(0); + highbyte = SPI.transfer(0); + + _RXPacketL = _RXPacketL + 2; //increment count of bytes read + return ((highbyte << 8) + lowbyte); +} + + +void SX128XLT::writeUint16(uint16_t x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeUint16()")); +#endif + + SPI.transfer(lowByte(x)); + SPI.transfer(highByte(x)); + + _TXPacketL = _TXPacketL + 2; //increment count of bytes written +} + + +uint16_t SX128XLT::readUint16() +{ +#ifdef SX128XDEBUG + Serial.println(F("writeUint16()")); +#endif + byte lowbyte, highbyte; + + lowbyte = SPI.transfer(0); + highbyte = SPI.transfer(0); + + _RXPacketL = _RXPacketL + 2; //increment count of bytes read + return ((highbyte << 8) + lowbyte); +} + + +void SX128XLT::writeInt32(int32_t x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeInt32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + int32_t f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +int32_t SX128XLT::readInt32() +{ +#ifdef SX128XDEBUG + Serial.println(F("readInt32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + int32_t f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX128XLT::writeUint32(uint32_t x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeUint32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + uint32_t f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +uint32_t SX128XLT::readUint32() +{ +#ifdef SX128XDEBUG + Serial.println(F("readUint32()")); +#endif + + byte i, j; + + union + { + byte b[4]; + uint32_t f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +void SX128XLT::writeFloat(float x) +{ +#ifdef SX128XDEBUG + Serial.println(F("writeFloat()")); +#endif + + byte i, j; + + union + { + byte b[4]; + float f; + } data; + data.f = x; + + for (i = 0; i < 4; i++) + { + j = data.b[i]; + SPI.transfer(j); + } + + _TXPacketL = _TXPacketL + 4; //increment count of bytes written +} + + +float SX128XLT::readFloat() +{ +#ifdef SX128XDEBUG + Serial.println(F("readFloat()")); +#endif + + byte i, j; + + union + { + byte b[4]; + float f; + } readdata; + + for (i = 0; i < 4; i++) + { + j = SPI.transfer(0); + readdata.b[i] = j; + } + _RXPacketL = _RXPacketL + 4; //increment count of bytes read + return readdata.f; +} + + +uint8_t SX128XLT::transmitSXBuffer(uint8_t startaddr, uint8_t length, uint16_t timeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("transmitSXBuffer()")); +#endif + + setBufferBaseAddress(startaddr, 0); //TX, RX + + setPacketParams(savedPacketParam1, savedPacketParam2, length, savedPacketParam4, savedPacketParam5, savedPacketParam6, savedPacketParam7); + setTxParams(txpower, RAMP_TIME); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1 + setTx(timeout); //this starts the TX + + if (!wait) + { + return _TXPacketL; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RX_TX_TIMEOUT ) //check for timeout + { + return 0; + } + else + { + return _TXPacketL; + } +} + + +void SX128XLT::writeBuffer(uint8_t *txbuffer, uint8_t size) +{ +#ifdef SX128XDEBUG1 + Serial.println(F("writeBuffer()")); +#endif + + uint8_t index, regdata; + + _TXPacketL = _TXPacketL + size; //these are the number of bytes that will be added + + size--; //loose one byte from size, the last byte written MUST be a 0 + + for (index = 0; index < size; index++) + { + regdata = txbuffer[index]; + SPI.transfer(regdata); + } + + SPI.transfer(0); //this ensures last byte of buffer written really is a null (0) + +} + + +uint8_t SX128XLT::receiveSXBuffer(uint8_t startaddr, uint16_t timeout, uint8_t wait ) +{ +#ifdef SX127XDEBUG1 + Serial.println(F("receiveSXBuffer()")); +#endif + + uint16_t regdata; + uint8_t buffer[2]; + + setMode(MODE_STDBY_RC); + + setBufferBaseAddress(0, startaddr); //order is TX RX + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on RX done or timeout + + setRx(timeout); //no actual RX timeout in this function + + if (!wait) + { + return 0; + } + + while (!digitalRead(_RXDonePin)); //Wait for DIO1 to go high + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + regdata = readIrqStatus(); + + if ( (regdata & IRQ_HEADER_ERROR) | (regdata & IRQ_CRC_ERROR) | (regdata & IRQ_RX_TX_TIMEOUT ) ) + { + return 0; //no RX done and header valid only, could be CRC error + } + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + return _RXPacketL; +} + + + +uint8_t SX128XLT::readBuffer(uint8_t *rxbuffer) +{ +#ifdef SX128XDEBUG1 + Serial.println(F("readBuffer()")); +#endif + + uint8_t index = 0, regdata; + + do //need to find the size of the buffer first + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; //fill the buffer. + index++; + } while (regdata != 0); //keep reading until we have reached the null (0) at the buffer end + //or exceeded size of buffer allowed + _RXPacketL = _RXPacketL + index; //increment count of bytes read + return index; //return the actual size of the buffer, till the null (0) detected + +} + + +void SX128XLT::setSyncWord1(uint32_t syncword) +{ +#ifdef SX128XDEBUG1 + Serial.println(F("setSyncWord1()")); +#endif + + //For FLRC packet type, the SyncWord is one byte shorter and + //the base address is shifted by one byte + writeRegister( REG_FLRCSYNCWORD1_BASEADDR, ( syncword >> 24 ) & 0x000000FF ); + writeRegister( REG_FLRCSYNCWORD1_BASEADDR + 1, ( syncword >> 16 ) & 0x000000FF ); + writeRegister( REG_FLRCSYNCWORD1_BASEADDR + 2, ( syncword >> 8 ) & 0x000000FF ); + writeRegister( REG_FLRCSYNCWORD1_BASEADDR + 3, syncword & 0x000000FF ); +} + + +/*************************************************************************** +//End direct access SX buffer routines +***************************************************************************/ + + + +//******************************************************************************* +//Start Ranging routines +//******************************************************************************* + + +void SX128XLT::setRangingSlaveAddress(uint32_t address) +{ +//sets address of ranging slave +#ifdef SX128XDEBUG + Serial.println(F("SetRangingSlaveAddress()")); +#endif + + uint8_t buffer[4]; + + buffer[0] = (address >> 24u ) & 0xFFu; + buffer[1] = (address >> 16u) & 0xFFu; + buffer[2] = (address >> 8u) & 0xFFu; + buffer[3] = (address & 0xFFu); + + writeRegisters(0x916, buffer, 4 ); +} + + +void SX128XLT::setRangingMasterAddress(uint32_t address) +{ +//sets address of ranging master +#ifdef SX128XDEBUG + Serial.println(F("SetRangingMasterAddress()")); +#endif + + uint8_t buffer[4]; + + buffer[0] = (address >> 24u ) & 0xFFu; + buffer[1] = (address >> 16u) & 0xFFu; + buffer[2] = (address >> 8u) & 0xFFu; + buffer[3] = (address & 0xFFu); + + writeRegisters(0x912, buffer, 4 ); +} + + +void SX128XLT::setRangingCalibration(uint16_t cal) +{ + #ifdef SX128XDEBUG + Serial.println(F("setRangingCalibration()")); +#endif + savedCalibration = cal; + writeRegister( REG_LR_RANGINGRERXTXDELAYCAL, ( uint8_t )( ( cal >> 8 ) & 0xFF ) ); + writeRegister( REG_LR_RANGINGRERXTXDELAYCAL + 1, ( uint8_t )( ( cal ) & 0xFF ) ); +} + + +void SX128XLT::setRangingRole(uint8_t role) +{ +#ifdef SX128XDEBUG + Serial.println(F("setRangingRole()")); +#endif + + uint8_t buffer[1]; + + buffer[0] = role; + + writeCommand(RADIO_SET_RANGING_ROLE, buffer, 1 ); +} + + +uint32_t SX128XLT::getRangingResultRegValue(uint8_t resultType) +{ + uint32_t valLsb = 0; + + setMode(MODE_STDBY_XOSC); + writeRegister( 0x97F, readRegister( 0x97F ) | ( 1 << 1 ) ); // enable LORA modem clock + writeRegister( REG_LR_RANGINGRESULTCONFIG, ( readRegister( REG_LR_RANGINGRESULTCONFIG ) & MASK_RANGINGMUXSEL ) | ( ( ( ( uint8_t )resultType ) & 0x03 ) << 4 ) ); + valLsb = ( ( (uint32_t) readRegister( REG_LR_RANGINGRESULTBASEADDR ) << 16 ) | ( (uint32_t) readRegister( REG_LR_RANGINGRESULTBASEADDR + 1 ) << 8 ) | ( readRegister( REG_LR_RANGINGRESULTBASEADDR + 2 ) ) ); + setMode(MODE_STDBY_RC); + return valLsb; +} + + +double SX128XLT::getRangingDistance(uint8_t resultType, int32_t regval, float adjust) +{ + float val = 0.0; + + if (regval >= 0x800000) //raw reg value at low distance can goto 0x800000 which is negative, set distance to zero if this happens + { + regval = 0; + } + + // Conversion from LSB to distance. For explanation on the formula, refer to Datasheet of SX1280 + + switch (resultType) + { + case RANGING_RESULT_RAW: + // Convert the ranging LSB to distance in meter. The theoretical conversion from register value to distance [m] is given by: + // distance [m] = ( complement2( register ) * 150 ) / ( 2^12 * bandwidth[MHz] ) ). The API provide BW in [Hz] so the implemented + // formula is complement2( register ) / bandwidth[Hz] * A, where A = 150 / (2^12 / 1e6) = 36621.09 + val = ( double ) regval / ( double ) returnBandwidth(savedModParam2) * 36621.09375; + break; + + case RANGING_RESULT_AVERAGED: + case RANGING_RESULT_DEBIASED: + case RANGING_RESULT_FILTERED: + Serial.print(F("??")); + val = ( double )regval * 20.0 / 100.0; + break; + default: + val = 0.0; + break; + } + + val = val * adjust; + return val; +} + + +bool SX128XLT::setupRanging(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint32_t address, uint8_t role) +{ + //sequence is frequency, offset, spreading factor, bandwidth, coding rate, calibration, role. + #ifdef SX128XDEBUG + Serial.println(F("setupRanging()")); +#endif + + setMode(MODE_STDBY_RC); + setPacketType(PACKET_TYPE_RANGING); + setModulationParams(modParam1, modParam2, modParam3); + setPacketParams(12, LORA_PACKET_VARIABLE_LENGTH, 0, LORA_CRC_ON, LORA_IQ_NORMAL, 0, 0); + setRfFrequency(frequency, offset); + setRangingSlaveAddress(address); + setRangingMasterAddress(address); + setRangingCalibration(lookupCalibrationValue(modParam1, modParam2)); + setRangingRole(role); + setHighSensitivity(); + return true; +} + + + +bool SX128XLT::transmitRanging(uint32_t address, uint16_t timeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("transmitRanging()")); +#endif + + if ((_RXEN >= 0) || (_TXEN >= 0)) + { + return false; + } + + setMode(MODE_STDBY_RC); + setRangingMasterAddress(address); + setTxParams(txpower, RADIO_RAMP_02_US); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RANGING_MASTER_RESULT_VALID + IRQ_RANGING_MASTER_RESULT_TIMEOUT), 0, 0); + setTx(timeout); //this sends the ranging packet + + if (!wait) + { + return true; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RANGING_MASTER_RESULT_VALID ) //check for timeout + { + return true; + } + else + { + return false; + } +} + + +uint8_t SX128XLT::receiveRanging(uint32_t address, uint16_t timeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("receiveRanging()")); +#endif + + setTxParams(txpower, RADIO_RAMP_02_US); + setRangingSlaveAddress(address); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RANGING_SLAVE_RESPONSE_DONE + IRQ_RANGING_SLAVE_REQUEST_DISCARDED), 0, 0); + setRx(timeout); + + if (!wait) + { + return NO_WAIT; //not wait requested so no packet length to pass + } + + while (!digitalRead(_RXDonePin)); + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + if (readIrqStatus() & IRQ_RANGING_SLAVE_REQUEST_VALID) + { + return true; + } + else + { + return false; //so we can check for packet having enough buffer space + } +} + + +uint16_t SX128XLT::lookupCalibrationValue(uint8_t spreadingfactor, uint8_t bandwidth) +{ +//this looks up the calibration value from the table in SX128XLT_Definitions.hifdef SX128XDEBUG +#ifdef SX128XDEBUG +Serial.println(F("lookupCalibrationValue()")); +#endif + + +switch (bandwidth) + { + case LORA_BW_0400: + savedCalibration = RNG_CALIB_0400[(spreadingfactor>>4)-5]; + return savedCalibration; + + case LORA_BW_0800: + savedCalibration = RNG_CALIB_0800[(spreadingfactor>>4)-5]; + return savedCalibration; + + + case LORA_BW_1600: + savedCalibration = RNG_CALIB_1600[(spreadingfactor>>4)-5]; + return savedCalibration; + + default: + return 0xFFFF; + + } + +} + + +uint16_t SX128XLT::getSetCalibrationValue() +{ +#ifdef SX128XDEBUG + Serial.println(F("getCalibrationValue()")); +#endif + +return savedCalibration;; + +} + + +//******************************************************************************* +//End Ranging routines +//******************************************************************************* + + +void SX128XLT::setSleep(uint8_t sleepconfig) +{ +#ifdef SX128XDEBUG + Serial.println(F("setSleep()")); +#endif + + setMode(MODE_STDBY_RC); + checkBusy(); + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + //need to save registers to device RAM first + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_SET_SAVECONTEXT); + digitalWrite(_NSS, HIGH); + + checkBusy(); + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_SET_SLEEP); + SPI.transfer(sleepconfig); + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + delay(1); //allow time for shutdown +} + + +uint16_t SX128XLT::CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue) +{ + //genrates a CRC of an area of the internal SX buffer + +#ifdef SX126XDEBUG1 + Serial.println(F("CRCCCITTSX()")); +#endif + + + uint16_t index, libraryCRC; + uint8_t j; + + libraryCRC = startvalue; //start value for CRC16 + + startReadSXBuffer(startadd); //begin the buffer read + + for (index = startadd; index <= endadd; index++) + { + libraryCRC ^= (((uint16_t) readUint8() ) << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + } + + endReadSXBuffer(); //end the buffer read + + return libraryCRC; +} + + + +uint8_t SX128XLT::getByteSXBuffer(uint8_t addr) +{ +#ifdef SX128XDEBUG1 + Serial.println(F("getByteSXBuffer()")); +#endif + + uint8_t regdata; + setMode(MODE_STDBY_RC); //this is needed to ensure we can read from buffer OK. + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(addr); + SPI.transfer(0xFF); + regdata = SPI.transfer(0); + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return regdata; +} + + +void SX128XLT::printSXBufferHEX(uint8_t start, uint8_t end) +{ +#ifdef SX128XDEBUG + Serial.println(F("printSXBufferHEX()")); +#endif + + uint8_t index, regdata; + + setMode(MODE_STDBY_RC); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(start); + SPI.transfer(0xFF); + + for (index = start; index <= end; index++) + { + regdata = SPI.transfer(0); + printHEXByte(regdata); + Serial.print(F(" ")); + + } + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + +} + + +void SX128XLT::printHEXByte(uint8_t temp) +{ + if (temp < 0x10) + { + Serial.print(F("0")); + } + Serial.print(temp, HEX); +} + + +void SX128XLT::wake() +{ +#ifdef SX128XDEBUG + Serial.println(F("wake()")); +#endif + +digitalWrite(_NSS, LOW); +delay(1); +digitalWrite(_NSS, HIGH); +delay(1); +} + + +int32_t SX128XLT::getFrequencyErrorRegValue() +{ + #ifdef SX128XDEBUG + Serial.println(F("getFrequencyErrorRegValue()")); +#endif + + int32_t FrequencyError; + uint32_t regmsb, regmid, reglsb, allreg; + + setMode(MODE_STDBY_XOSC); + + regmsb = readRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB ); + regmsb = regmsb & 0x0F; //clear bit 20 which is always set + + regmid = readRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 1 ); + + reglsb = readRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 2 ); + setMode(MODE_STDBY_RC); + + #ifdef LORADEBUG + Serial.println(); + Serial.print(F("Registers ")); + Serial.print(regmsb,HEX); + Serial.print(F(" ")); + Serial.print(regmid,HEX); + Serial.print(F(" ")); + Serial.println(reglsb,HEX); + #endif + + allreg = (uint32_t) ( regmsb << 16 ) | ( regmid << 8 ) | reglsb; + + if (allreg & 0x80000) + { + FrequencyError = (0xFFFFF - allreg) * -1; + } + else + { + FrequencyError = allreg; + } + + return FrequencyError; +} + + +int32_t SX128XLT::getFrequencyErrorHz() +{ + #ifdef SX128XDEBUG + Serial.println(F("getFrequencyErrorHz()")); +#endif + + int32_t error, regvalue; + uint32_t bandwidth; + float divider; + + bandwidth = returnBandwidth(savedModParam2); //gets the last configured bandwidth + + divider = (float) 1625000 / bandwidth; //data sheet says 1600000, but bandwidth is 1625000 + regvalue = getFrequencyErrorRegValue(); + error = (FREQ_ERROR_CORRECTION * regvalue) / divider; + + return error; +} + +uint8_t SX128XLT::transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t timeout, int8_t txpower, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("transmitAddressed()")); +#endif + uint8_t index; + uint8_t bufferdata; + + if (size == 0) + { + return false; + } + + setMode(MODE_STDBY_RC); + setBufferBaseAddress(0, 0); + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); + SPI.transfer(RADIO_WRITE_BUFFER); + SPI.transfer(0); + + SPI.transfer(txpackettype); //Write the packet type + SPI.transfer(txdestination); //Destination node + SPI.transfer(txsource); //Source node + _TXPacketL = 3 + size; //we have added 3 header bytes to size + + for (index = 0; index < size; index++) + { + bufferdata = txbuffer[index]; + SPI.transfer(bufferdata); + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + + if (savedPacketType == PACKET_TYPE_LORA) + { + writeRegister(REG_LR_PAYLOADLENGTH, _TXPacketL); //only seems to work for lora + } + else if (savedPacketType == PACKET_TYPE_FLRC) + { + setPacketParams(savedPacketParam1, savedPacketParam2, savedPacketParam3, savedPacketParam4, _TXPacketL, savedPacketParam6, savedPacketParam7); + } + + setTxParams(txpower, RAMP_TIME); + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_TX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on TX done and timeout on DIO1 + setTx(timeout); //this starts the TX + + if (!wait) + { + return _TXPacketL; + } + + while (!digitalRead(_TXDonePin)); //Wait for DIO1 to go high + + if (readIrqStatus() & IRQ_RX_TX_TIMEOUT ) //check for timeout + { + return 0; + } + else + { + return _TXPacketL; + } +} + + +uint8_t SX128XLT::receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint16_t timeout, uint8_t wait) +{ +#ifdef SX128XDEBUG + Serial.println(F("receiveAddressed()")); +#endif + + uint8_t index, RXstart, RXend; + uint16_t regdata; + uint8_t buffer[2]; + + setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0); //set for IRQ on RX done or timeout + setRx(timeout); + + if (!wait) + { + return 0; //not wait requested so no packet length to pass + } + + while (!digitalRead(_RXDonePin)); //Wait for DIO1 to go high + + setMode(MODE_STDBY_RC); //ensure to stop further packet reception + + regdata = readIrqStatus(); + + if ( (regdata & IRQ_HEADER_ERROR) | (regdata & IRQ_CRC_ERROR) | (regdata & IRQ_RX_TX_TIMEOUT ) ) //check if any of the preceding IRQs is set + { + return 0; //packet is errored somewhere so return 0 + } + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + + RXstart = buffer[1]; + + RXend = RXstart + _RXPacketL; + + checkBusy(); + +#ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(RXstart); + SPI.transfer(0xFF); + + _RXPacketType = SPI.transfer(0); + _RXDestination = SPI.transfer(0); + _RXSource = SPI.transfer(0); + + for (index = RXstart; index < RXend; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + + digitalWrite(_NSS, HIGH); + +#ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint8_t SX128XLT::readRXPacketType() +{ +#ifdef SX128XDEBUG + Serial.println(F("readRXPacketType()")); +#endif +return _RXPacketType; +} + + +uint8_t SX128XLT::readPacket(uint8_t *rxbuffer, uint8_t size) +{ +#ifdef SX128XDEBUG + Serial.println(F("readPacket()")); +#endif + + uint8_t index, regdata, RXstart, RXend; + uint8_t buffer[2]; + + readCommand(RADIO_GET_RXBUFFERSTATUS, buffer, 2); + _RXPacketL = buffer[0]; + + if (_RXPacketL > size) //check passed buffer is big enough for packet + { + _RXPacketL = size; //truncate packet if not enough space + } + + RXstart = buffer[1]; + + RXend = RXstart + _RXPacketL; + + #ifdef USE_SPI_TRANSACTION //to use SPI_TRANSACTION enable define at beginning of CPP file + SPI.beginTransaction(SPISettings(LTspeedMaximum, LTdataOrder, LTdataMode)); +#endif + + digitalWrite(_NSS, LOW); //start the burst read + SPI.transfer(RADIO_READ_BUFFER); + SPI.transfer(RXstart); + SPI.transfer(0xFF); + + for (index = RXstart; index < RXend; index++) + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; + } + + digitalWrite(_NSS, HIGH); + + #ifdef USE_SPI_TRANSACTION + SPI.endTransaction(); +#endif + + return _RXPacketL; //so we can check for packet having enough buffer space +} + + +uint16_t SX128XLT::addCRC(uint8_t data, uint16_t libraryCRC) +{ + uint8_t j; + + libraryCRC ^= ((uint16_t)data << 8); + for (j = 0; j < 8; j++) + { + if (libraryCRC & 0x8000) + libraryCRC = (libraryCRC << 1) ^ 0x1021; + else + libraryCRC <<= 1; + } + return libraryCRC; +} + + +void SX128XLT::writeBufferChar(char *txbuffer, uint8_t size) +{ +#ifdef SX128XDEBUG1 + Serial.println(F("writeBuffer()")); +#endif + + uint8_t index, regdata; + + _TXPacketL = _TXPacketL + size; //these are the number of bytes that will be added + + size--; //loose one byte from size, the last byte written MUST be a 0 + + for (index = 0; index < size; index++) + { + regdata = txbuffer[index]; + SPI.transfer(regdata); + } + + SPI.transfer(0); //this ensures last byte of buffer writen really is a null (0) + +} + + +uint8_t SX128XLT::readBufferChar(char *rxbuffer) +{ +#ifdef SX128XDEBUG1 + Serial.println(F("readBuffer()")); +#endif + + uint8_t index = 0, regdata; + + do //need to find the size of the buffer first + { + regdata = SPI.transfer(0); + rxbuffer[index] = regdata; //fill the buffer. + index++; + } while (regdata != 0); //keep reading until we have reached the null (0) at the buffer end + //or exceeded size of buffer allowed + + _RXPacketL = _RXPacketL + index; //increment count of bytes read + + return index; //return the actual size of the buffer, till the null (0) detected + +} + + + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + + + + + diff --git a/lib/SX12XX-LoRa/src/SX128XLT.h b/lib/SX12XX-LoRa/src/SX128XLT.h new file mode 100644 index 0000000..b58b1b2 --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX128XLT.h @@ -0,0 +1,197 @@ +#ifndef SX128XLT_h +#define SX128XLT_h + +#include "Arduino.h" +#include + +/************************************************************************** + + ToDO + + DONE - Why is SX1280LT.setPacketType(PACKET_TYPE_LORA) required before getFreqInt works with FLRC + - The register addresses where the frequency is stored are different for FLRC and LORA + DONE - Checkbusy at end of setmode ? - not needed, Checkbusy before all SPI activity + DONE - Ranging in complement2 - warning: comparison between signed and unsigned integer + DONE - Trap use of devices with RX\TX switching in ranging mode + DONE - Ensure ranging distance is not negative + + + Add routine to change period_base for RX,TX timeout + Is there a direct register access to packet length for transmit ? + Test RSSI and SNR are realistic for LoRa and FLRC + Review error rate in FLRC mode + Error packets at -99dBm due to noise ? + Add support for printPacketStatus for FLRC + +**************************************************************************/ + +class SX128XLT { + + public: + + SX128XLT(); + + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinDIO2, int8_t pinDIO3, int8_t pinRXEN, int8_t pinTXEN, uint8_t device); + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, uint8_t device); + bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinRFBUSY, int8_t pinDIO1, int8_t pinRXEN, int8_t pinTXEN, uint8_t device); + + void rxEnable(); + void txEnable(); + + void checkBusy(); + bool config(); + void readRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + uint8_t readRegister( uint16_t address ); + void writeRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + void writeRegister( uint16_t address, uint8_t value ); + void writeCommand(uint8_t Opcode, uint8_t *buffer, uint16_t size ); + void readCommand( uint8_t Opcode, uint8_t *buffer, uint16_t size ); + void resetDevice(); + bool checkDevice(); + void setupLoRa(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3); + void setMode(uint8_t modeconfig); + void setRegulatorMode(uint8_t mode); + void setPacketType(uint8_t PacketType); + void setRfFrequency( uint32_t frequency, int32_t offset ); + void setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress); + void setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3); + void setPacketParams(uint8_t packetParam1, uint8_t packetParam2, uint8_t packetParam3, uint8_t packetParam4, uint8_t packetParam5, uint8_t packetParam6, uint8_t packetParam7); + void setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ); + void setHighSensitivity(); + void setLowPowerRX(); + void printModemSettings(); + void printDevice(); + uint32_t getFreqInt(); + uint8_t getLoRaSF(); + uint32_t returnBandwidth(uint8_t data); + uint8_t getLoRaCodingRate(); + uint8_t getInvertIQ(); + uint16_t getPreamble(); + void printOperatingSettings(); + uint8_t getLNAgain(); + void printRegisters(uint16_t Start, uint16_t End); + void printASCIIPacket(uint8_t *buff, uint8_t tsize); + uint8_t transmit(uint8_t *txbuffer, uint8_t size, uint16_t timeout, int8_t txpower, uint8_t wait); + void setTxParams(int8_t TXpower, uint8_t RampTime); + void setTx(uint16_t timeout); + void clearIrqStatus( uint16_t irq ); + uint16_t readIrqStatus(); + void printIrqStatus(); + uint16_t CRCCCITT(uint8_t *buffer, uint8_t size, uint16_t start); + uint8_t receive(uint8_t *rxbuffer, uint8_t size, uint16_t timeout, uint8_t wait); + uint8_t readPacketRSSI(); + uint8_t readPacketSNR(); + uint8_t readRXPacketL(); + void setRx(uint16_t timeout); + void setSyncWord1(uint32_t syncword); + void setSleep(uint8_t sleepconfig); + uint16_t CRCCCITTSX(uint8_t startadd, uint8_t endadd, uint16_t startvalue); + uint8_t getByteSXBuffer(uint8_t addr); + int32_t getFrequencyErrorRegValue(); + int32_t getFrequencyErrorHz(); + void printHEXByte(uint8_t temp); + void wake() ; + uint8_t transmitAddressed(uint8_t *txbuffer, uint8_t size, char txpackettype, char txdestination, char txsource, uint32_t timeout, int8_t txpower, uint8_t wait); + uint8_t receiveAddressed(uint8_t *rxbuffer, uint8_t size, uint16_t timeout, uint8_t wait); + uint8_t readRXPacketType(); + uint8_t readPacket(uint8_t *rxbuffer, uint8_t size); +/********************************************************** +***************** +//Start direct access SX buffer routines +***************************************************************************/ + + void startWriteSXBuffer(uint8_t ptr); + uint8_t endWriteSXBuffer(); + void startReadSXBuffer(uint8_t ptr); + uint8_t endReadSXBuffer(); + + void writeUint8(uint8_t x); + uint8_t readUint8(); + + void writeInt8(int8_t x); + int8_t readInt8(); + + void writeInt16(int16_t x); + int16_t readInt16(); + + void writeUint16(uint16_t x); + uint16_t readUint16(); + + void writeInt32(int32_t x); + int32_t readInt32(); + + void writeUint32(uint32_t x); + uint32_t readUint32(); + + void writeFloat(float x); + float readFloat(); + + uint8_t transmitSXBuffer(uint8_t startaddr, uint8_t length, uint16_t timeout, int8_t txpower, uint8_t wait); + void writeBuffer(uint8_t *txbuffer, uint8_t size); + uint8_t receiveSXBuffer(uint8_t startaddr, uint16_t timeout, uint8_t wait); + uint8_t readBuffer(uint8_t *rxbuffer); + void printSXBufferHEX(uint8_t start, uint8_t end); + uint16_t addCRC(uint8_t data, uint16_t libraryCRC); + void writeBufferChar(char *txbuffer, uint8_t size); + uint8_t readBufferChar(char *rxbuffer); +/*************************************************************************** +//End direct access SX buffer routines +***************************************************************************/ + + +/*************************************************************************** +//Start ranging routines +***************************************************************************/ + + + void setRangingSlaveAddress(uint32_t address); + void setRangingMasterAddress(uint32_t address); + void setRangingCalibration(uint16_t cal); + void setRangingRole(uint8_t role); + double getRangingDistance(uint8_t resultType, int32_t regval, float adjust); + uint32_t getRangingResultRegValue(uint8_t resultType); + int32_t complement2( uint32_t num, uint8_t bitCnt ); + bool setupRanging(uint32_t frequency, int32_t offset, uint8_t modParam1, uint8_t modParam2, uint8_t modParam3, uint32_t address, uint8_t role); + bool transmitRanging(uint32_t address, uint16_t timeout, int8_t txpower, uint8_t wait); + uint8_t receiveRanging(uint32_t address, uint16_t timeout, int8_t txpower, uint8_t wait); + uint16_t lookupCalibrationValue(uint8_t spreadingfactor, uint8_t bandwidth); + uint16_t getSetCalibrationValue(); + +/*************************************************************************** +//End ranging routines +***************************************************************************/ + + private: + + int8_t _NSS, _NRESET, _RFBUSY, _DIO1, _DIO2, _DIO3; + int8_t _RXEN, _TXEN; + uint8_t _RXPacketL; //length of packet received + uint8_t _RXPacketType; //type number of received packet + uint8_t _RXDestination; //destination address of received packet + uint8_t _RXSource; //source address of received packet + int8_t _PacketRSSI; //RSSI of received packet + int8_t _PacketSNR; //signal to noise ratio of received packet + int8_t _TXPacketL; //transmitted packet length + uint8_t _RXcount; //used to keep track of the bytes read from SX1280 buffer during readFloat() etc + uint8_t _TXcount; //used to keep track of the bytes written to SX1280 buffer during writeFloat() etc + uint8_t _OperatingMode; //current operating mode + bool _rxtxpinmode = false; //set to true if RX and TX pin mode is used. + + uint8_t _Device; //saved device type + uint8_t _TXDonePin; //the pin that will indicate TX done + uint8_t _RXDonePin; //the pin that will indicate RX done + uint8_t _PERIODBASE = PERIODBASE_01_MS; + + uint8_t savedRegulatorMode; + uint8_t savedPacketType; + uint32_t savedFrequency; + int32_t savedOffset; + uint8_t savedModParam1, savedModParam2, savedModParam3; //sequence is spreading factor, bandwidth, coding rate + uint8_t savedPacketParam1, savedPacketParam2, savedPacketParam3, savedPacketParam4, savedPacketParam5, savedPacketParam6, savedPacketParam7; + uint16_t savedIrqMask, savedDio1Mask, savedDio2Mask, savedDio3Mask; + int8_t savedTXPower; + uint16_t savedCalibration; + uint32_t savedFrequencyReg; + +}; +#endif diff --git a/lib/SX12XX-LoRa/src/SX128XLT_Definitions.h b/lib/SX12XX-LoRa/src/SX128XLT_Definitions.h new file mode 100644 index 0000000..d3e527c --- /dev/null +++ b/lib/SX12XX-LoRa/src/SX128XLT_Definitions.h @@ -0,0 +1,388 @@ +//SX1280LT Includes + + +//************************************************************* +// LoRa Modem Settings +//************************************************************* +// +//LoRa spreading factors +#define LORA_SF5 0x50 +#define LORA_SF6 0x60 +#define LORA_SF7 0x70 +#define LORA_SF8 0x80 +#define LORA_SF9 0x90 +#define LORA_SF10 0xA0 +#define LORA_SF11 0xB0 +#define LORA_SF12 0xC0 + +//LoRa bandwidths +#define LORA_BW_0200 0x34 //actually 203125hz +#define LORA_BW_0400 0x26 //actually 406250hz +#define LORA_BW_0800 0x18 //actually 812500hz +#define LORA_BW_1600 0x0A //actually 1625000hz + +//LoRa coding rates +#define LORA_CR_4_5 0x01 +#define LORA_CR_4_6 0x02 +#define LORA_CR_4_7 0x03 +#define LORA_CR_4_8 0x04 + +//LoRa CAD settings +#define LORA_CAD_01_SYMBOL 0x00 +#define LORA_CAD_02_SYMBOL 0x20 +#define LORA_CAD_04_SYMBOL 0x40 +#define LORA_CAD_08_SYMBOL 0x60 +#define LORA_CAD_16_SYMBOL 0x80 + +//LoRa Header Types +#define LORA_PACKET_VARIABLE_LENGTH 0x00 +#define LORA_PACKET_FIXED_LENGTH 0x80 +#define LORA_PACKET_EXPLICIT LORA_PACKET_VARIABLE_LENGTH +#define LORA_PACKET_IMPLICIT LORA_PACKET_FIXED_LENGTH + +//LoRa packet CRC settings +#define LORA_CRC_ON 0x20 +#define LORA_CRC_OFF 0x00 + +//LoRa IQ Setings +#define LORA_IQ_NORMAL 0x40 +#define LORA_IQ_INVERTED 0x00 + + +#define FREQ_STEP 198.364 +#define FREQ_ERROR_CORRECTION 1.55 + + + + +//************************************************************* +// SX1280 Interrupt flags +//************************************************************* + +#define IRQ_RADIO_NONE 0x0000 +#define IRQ_TX_DONE 0x0001 +#define IRQ_RX_DONE 0x0002 +#define IRQ_SYNCWORD_VALID 0x0004 +#define IRQ_SYNCWORD_ERROR 0x0008 +#define IRQ_HEADER_VALID 0x0010 +#define IRQ_HEADER_ERROR 0x0020 +#define IRQ_CRC_ERROR 0x0040 +#define IRQ_RANGING_SLAVE_RESPONSE_DONE 0x0080 + +#define IRQ_RANGING_SLAVE_REQUEST_DISCARDED 0x0100 +#define IRQ_RANGING_MASTER_RESULT_VALID 0x0200 +#define IRQ_RANGING_MASTER_RESULT_TIMEOUT 0x0400 +#define IRQ_RANGING_SLAVE_REQUEST_VALID 0x0800 +#define IRQ_CAD_DONE 0x1000 +#define IRQ_CAD_ACTIVITY_DETECTED 0x2000 +#define IRQ_RX_TX_TIMEOUT 0x4000 +#define IRQ_TX_TIMEOUT 0x4000 +#define IRQ_RX_TIMEOUT 0x4000 +#define IRQ_PREAMBLE_DETECTED 0x8000 +#define IRQ_RADIO_ALL 0xFFFF + + +//************************************************************* +// SX1280 Commands +//************************************************************* + +#define RADIO_GET_PACKETTYPE 0x03 +#define RADIO_GET_IRQSTATUS 0x15 +#define RADIO_GET_RXBUFFERSTATUS 0x17 +#define RADIO_WRITE_REGISTER 0x18 +#define RADIO_READ_REGISTER 0x19 +#define RADIO_WRITE_BUFFER 0x1A +#define RADIO_READ_BUFFER 0x1B +#define RADIO_GET_PACKETSTATUS 0x1D +#define RADIO_GET_RSSIINST 0x1F +#define RADIO_SET_STANDBY 0x80 +#define RADIO_SET_RX 0x82 +#define RADIO_SET_TX 0x83 +#define RADIO_SET_SLEEP 0x84 +#define RADIO_SET_RFFREQUENCY 0x86 +#define RADIO_SET_CADPARAMS 0x88 +#define RADIO_CALIBRATE 0x89 +#define RADIO_SET_PACKETTYPE 0x8A +#define RADIO_SET_MODULATIONPARAMS 0x8B +#define RADIO_SET_PACKETPARAMS 0x8C +#define RADIO_SET_DIOIRQPARAMS 0x8D +#define RADIO_SET_TXPARAMS 0x8E +#define RADIO_SET_BUFFERBASEADDRESS 0x8F +#define RADIO_SET_RXDUTYCYCLE 0x94 +#define RADIO_SET_REGULATORMODE 0x96 +#define RADIO_CLR_IRQSTATUS 0x97 +#define RADIO_SET_AUTOTX 0x98 +#define RADIO_SET_LONGPREAMBLE 0x9B +#define RADIO_SET_UARTSPEED 0x9D +#define RADIO_SET_AUTOFS 0x9E +#define RADIO_SET_RANGING_ROLE 0xA3 +#define RADIO_GET_STATUS 0xC0 +#define RADIO_SET_FS 0xC1 +#define RADIO_SET_CAD 0xC5 +#define RADIO_SET_TXCONTINUOUSWAVE 0xD1 +#define RADIO_SET_TXCONTINUOUSPREAMBLE 0xD2 +#define RADIO_SET_SAVECONTEXT 0xD5 + + +//************************************************************* +// SX1280 Registers +//************************************************************* + +#define REG_LNA_REGIME 0x0891 +#define REG_LR_PAYLOADLENGTH 0x901 +#define REG_LR_PACKETPARAMS 0x903 + +#define REG_RFFrequency23_16 0x906 +#define REG_RFFrequency15_8 0x907 +#define REG_RFFrequency7_0 0x908 + +#define REG_FLRC_RFFrequency23_16 0x9A3 //found by experiment +#define REG_FLRC_RFFrequency15_8 0x9A4 +#define REG_FLRC_RFFrequency7_0 0x9A5 + +#define REG_RANGING_FILTER_WINDOW_SIZE 0x091E +#define REG_LR_DEVICERANGINGADDR 0x0916 +#define REG_LR_DEVICERANGINGADDR 0x0916 +#define REG_LR_RANGINGRESULTCONFIG 0x0924 +#define REG_LR_RANGINGRERXTXDELAYCAL 0x092C +#define REG_LR_RANGINGIDCHECKLENGTH 0x0931 +#define REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB 0x954 +#define REG_LR_ESTIMATED_FREQUENCY_ERROR_MID 0x955 +#define REG_LR_ESTIMATED_FREQUENCY_ERROR_LSB 0x956 +#define REG_LR_RANGINGRESULTBASEADDR 0x0961 +#define REG_LR_SYNCWORDTOLERANCE 0x09CD +#define REG_LR_SYNCWORDBASEADDRESS1 0x09CE +#define REG_FLRCSYNCWORD1_BASEADDR 0x09CF +#define REG_LR_SYNCWORDBASEADDRESS2 0x09D3 +#define REG_FLRCSYNCWORD2_BASEADDR 0x09D4 +#define REG_LR_SYNCWORDBASEADDRESS3 0x09D8 + +#define REG_LR_ESTIMATED_FREQUENCY_ERROR_MASK 0x0FFFFF + +//SX1280 Packet Types +#define PACKET_TYPE_GFSK 0x00 +#define PACKET_TYPE_LORA 0x01 +#define PACKET_TYPE_RANGING 0x02 +#define PACKET_TYPE_FLRC 0x03 +#define PACKET_TYPE_BLE 0x04 + +//SX1280 Standby modes +#define MODE_STDBY_RC 0x00 +#define MODE_STDBY_XOSC 0x01 + +//TX and RX timeout based periods +#define PERIODBASE_15_US 0x00 +#define PERIODBASE_62_US 0x01 +#define PERIODBASE_01_MS 0x02 +#define PERIODBASE_04_MS 0x03 + +//TX ramp periods +#define RADIO_RAMP_02_US 0x00 +#define RADIO_RAMP_04_US 0x20 +#define RADIO_RAMP_06_US 0x40 +#define RADIO_RAMP_08_US 0x60 +#define RADIO_RAMP_10_US 0x80 +#define RADIO_RAMP_12_US 0xA0 +#define RADIO_RAMP_16_US 0xC0 +#define RADIO_RAMP_20_US 0xE0 + +//SX1280 Power settings +#define USE_LDO 0x00 +#define USE_DCDC 0x01 + + +//************************************************************* +//SX1280 Ranging settings +//************************************************************* + +#define RANGING_IDCHECK_LENGTH_08_BITS 0x00 +#define RANGING_IDCHECK_LENGTH_16_BITS 0x01 +#define RANGING_IDCHECK_LENGTH_24_BITS 0x02 +#define RANGING_IDCHECK_LENGTH_32_BITS 0x03 + +#define RANGING_RESULT_RAW 0x00 +#define RANGING_RESULT_AVERAGED 0x01 +#define RANGING_RESULT_DEBIASED 0x02 +#define RANGING_RESULT_FILTERED 0x03 + + +#define MASK_RANGINGMUXSEL 0xCF + +#define RANGING_SLAVE 0x00 +#define RANGING_MASTER 0x01 + + +//************************************************************* +//GFSK modem settings +//************************************************************* + +#define GFS_BLE_BR_2_000_BW_2_4 0x04 +#define GFS_BLE_BR_1_600_BW_2_4 0x28 +#define GFS_BLE_BR_1_000_BW_2_4 0x4C +#define GFS_BLE_BR_1_000_BW_1_2 0x45 +#define GFS_BLE_BR_0_800_BW_2_4 0x70 +#define GFS_BLE_BR_0_800_BW_1_2 0x69 +#define GFS_BLE_BR_0_500_BW_1_2 0x8D +#define GFS_BLE_BR_0_500_BW_0_6 0x86 +#define GFS_BLE_BR_0_400_BW_1_2 0xB1 +#define GFS_BLE_BR_0_400_BW_0_6 0xAA +#define GFS_BLE_BR_0_250_BW_0_6 0xCE +#define GFS_BLE_BR_0_250_BW_0_3 0xC7 +#define GFS_BLE_BR_0_125_BW_0_3 0xEF + +#define GFS_BLE_MOD_IND_0_35 0 +#define GFS_BLE_MOD_IND_0_50 1 +#define GFS_BLE_MOD_IND_0_75 2 +#define GFS_BLE_MOD_IND_1_00 3 +#define GFS_BLE_MOD_IND_1_25 4 +#define GFS_BLE_MOD_IND_1_50 5 +#define GFS_BLE_MOD_IND_1_75 6 +#define GFS_BLE_MOD_IND_2_00 7 +#define GFS_BLE_MOD_IND_2_25 8 +#define GFS_BLE_MOD_IND_2_50 9 +#define GFS_BLE_MOD_IND_2_75 10 +#define GFS_BLE_MOD_IND_3_00 11 +#define GFS_BLE_MOD_IND_3_25 12 +#define GFS_BLE_MOD_IND_3_50 13 +#define GFS_BLE_MOD_IND_3_75 14 +#define GFS_BLE_MOD_IND_4_00 15 + +#define PREAMBLE_LENGTH_04_BITS 0x00 //4 bits +#define PREAMBLE_LENGTH_08_BITS 0x10 //8 bits +#define PREAMBLE_LENGTH_12_BITS 0x20 //12 bits +#define PREAMBLE_LENGTH_16_BITS 0x30 //16 bits +#define PREAMBLE_LENGTH_20_BITS 0x40 //20 bits +#define PREAMBLE_LENGTH_24_BITS 0x50 //24 bits +#define PREAMBLE_LENGTH_28_BITS 0x60 //28 bits +#define PREAMBLE_LENGTH_32_BITS 0x70 //32 bits + +#define GFS_SYNCWORD_LENGTH_1_BYTE 0x00 //Sync word length 1 byte +#define GFS_SYNCWORD_LENGTH_2_BYTE 0x02 //Sync word length 2 bytes +#define GFS_SYNCWORD_LENGTH_3_BYTE 0x04 //Sync word length 3 bytes +#define GFS_SYNCWORD_LENGTH_4_BYTE 0x06 //Sync word length 4 bytes +#define GFS_SYNCWORD_LENGTH_5_BYTE 0x08 //Sync word length 5 bytes + +#define RADIO_RX_MATCH_SYNCWORD_OFF 0x00 //no search for SyncWord +#define RADIO_RX_MATCH_SYNCWORD_1 0x10 +#define RADIO_RX_MATCH_SYNCWORD_2 0x20 +#define RADIO_RX_MATCH_SYNCWORD_1_2 0x30 +#define RADIO_RX_MATCH_SYNCWORD_3 0x40 +#define RADIO_RX_MATCH_SYNCWORD_1_3 0x50 +#define RADIO_RX_MATCH_SYNCWORD_2_3 0x60 +#define RADIO_RX_MATCH_SYNCWORD_1_2_3 0x70 + +#define RADIO_PACKET_FIXED_LENGTH 0x00 //The packet is fixed length, klnown on both RX and TX, no header +#define RADIO_PACKET_VARIABLE_LENGTH 0x20 //The packet is variable size, header included + +#define RADIO_CRC_OFF 0x00 +#define RADIO_CRC_1_BYTES 0x10 +#define RADIO_CRC_2_BYTES 0x20 +#define RADIO_CRC_3_BYTES 0x30 + +#define RADIO_WHITENING_ON 0x00 +#define RADIO_WHITENING_OFF 0x08 + +//End GFSK **************************************************** + + + +//************************************************************* +//FLRC modem settings +//************************************************************* + +#define FLRC_SYNC_NOSYNC 0x00 +#define FLRC_SYNC_WORD_LEN_P32S 0x04 + +#define FLRC_BR_1_300_BW_1_2 0x45 //1.3Mbs +#define FLRC_BR_1_000_BW_1_2 0x69 //1.04Mbs +#define FLRC_BR_0_650_BW_0_6 0x86 //0.65Mbs +#define FLRC_BR_0_520_BW_0_6 0xAA //0.52Mbs +#define FLRC_BR_0_325_BW_0_3 0xC7 //0.325Mbs +#define FLRC_BR_0_260_BW_0_3 0xEB //0.26Mbs + +#define FLRC_CR_1_2 0x00 //coding rate 1:2 +#define FLRC_CR_3_4 0x02 //coding rate 3:4 +#define FLRC_CR_1_0 0x04 //coding rate 1 + +#define BT_DIS 0x00 //No filtering +#define BT_1 0x10 //1 +#define BT_0_5 0x20 //0.5 + +#define RADIO_MOD_SHAPING_BT_OFF 0x00 +#define RADIO_MOD_SHAPING_BT_1_0 0x10 +#define RADIO_MOD_SHAPING_BT_0_5 0x20 + + +//Table 13-45: PacketStatus2 in FLRC Packet +#define PacketCtrlBusy 0x01 +#define PacketReceived 0x02 +#define HeaderReceived 0x04 +#define AbortError 0x08 +#define CrcError 0x10 +#define LengthError 0x20 +#define SyncError 0x40 +#define Reserved 0x80 + + +//Table 13-46: PacketStatus3 in FLRC Packet +#define PktSent 0x01 +#define rxpiderr 0x08 +#define rx_no_ack 0x10 + +//FLRC default packetparamns +#define FLRC_Default_AGCPreambleLength PREAMBLE_LENGTH_32_BITS //packetParam1 +#define FLRC_Default_SyncWordLength FLRC_SYNC_WORD_LEN_P32S //packetParam2 +#define FLRC_Default_SyncWordMatch RADIO_RX_MATCH_SYNCWORD_1 //packetParam3 +#define FLRC_Default_PacketType RADIO_PACKET_VARIABLE_LENGTH //packetParam4 +#define FLRC_Default_PayloadLength BUFFER_SIZE_DEFAULT //packetParam5 +#define FLRC_Default_CrcLength RADIO_CRC_3_BYTES //packetParam6 +#define FLRC_Default_Whitening RADIO_WHITENING_OFF //packetParam7 + + +//Table 11-15 Sleep modes +#define RETAIN_INSTRUCTION_RAM 0x04 +#define RETAIN_DATABUFFER 0x02 +#define RETAIN_DATA_RAM 0x01 +#define CONFIGURATION_RETENTION 0x01 //included for libray compatibility +#define RETAIN_None 0x00 + + +#ifndef RAMP_TIME +#define RAMP_TIME RADIO_RAMP_02_US +#endif + +#ifndef PERIODBASE +#define PERIODBASE PERIOBASE_01_MS +#endif + +#ifndef PERIODBASE_COUNT_15_8 +#define PERIODBASE_COUNT_15_8 0 +#endif + +#ifndef PERIODBASE_COUNT_7_0 +#define PERIODBASE_COUNT_7_0 0 +#endif + + +#define DEVICE_SX1280 0x20 +#define DEVICE_SX1281 0x21 + + +//SPI settings +#define LTspeedMaximum 8000000 +#define LTdataOrder MSBFIRST +#define LTdataMode SPI_MODE0 + +#define RANGING_VALID 0x03 +#define RANGING_TIMEOUT 0x02 +#define WAIT_RX 0x01 +#define WAIT_TX 0x01 +#define NO_WAIT 0x00 + +#define CalibrationSF10BW400 10180 //calibration value for ranging, SF10, BW400 +#define CalibrationSF5BW1600 13100 //calibration value for ranging, SF5, BW1600 + + +const uint16_t RNG_CALIB_0400[] = { 10260, 10244, 10228, 10212, 10196, 10180 }; //SF5 to SF10 +const uint16_t RNG_CALIB_0800[] = { 11380, 11370, 11360, 11350, 11340, 11330 }; +const uint16_t RNG_CALIB_1600[] = { 13100, 13160, 13220, 13280, 13340, 13400 }; \ No newline at end of file diff --git a/lib/SX12XX-LoRa/src/UBLOXI2CGPS.h b/lib/SX12XX-LoRa/src/UBLOXI2CGPS.h new file mode 100644 index 0000000..032a95a --- /dev/null +++ b/lib/SX12XX-LoRa/src/UBLOXI2CGPS.h @@ -0,0 +1,569 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 27/06/20 +*/ + +/******************************************************************************************************* + Program Operation - This is a library file for the UBLOX 6,7 and 8 series GPSs. + + This GPS library file is designed for use with the GPSs I2C interface. + +*******************************************************************************************************/ + + + +//For use with I2C the configurations sent must be even numbers of bytes, thus the last byte in some cases may be a 0x00 padding byte +const PROGMEM uint8_t ClearConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x19, 0x98, 0x00}; //22 +const PROGMEM uint8_t GLONASSOff[] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2}; //20 +const PROGMEM uint8_t GPGLLOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A}; //16 +const PROGMEM uint8_t GPGLSOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46}; //16 +const PROGMEM uint8_t GPGSAOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31}; //16 +const PROGMEM uint8_t GPGSVOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38}; //16 +const PROGMEM uint8_t GNSSmode[] = {0xB5, 0x62, 0x06, 0x3E, 0x2C, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, +0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00, +0x00, 0x00, 0x01, 0x01, 0xFC, 0x11}; + +const PROGMEM uint8_t SetBalloonMode[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, + 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC}; //44 +const PROGMEM uint8_t SaveConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA9, 0x00}; //22 +const PROGMEM uint8_t PollNavigation[] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00, 0x2A, 0x84}; //8 +const PROGMEM uint8_t SetCyclicMode[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92}; //10 +const PROGMEM uint8_t SoftwareBackup[] = {0xB5, 0x62, 0x06, 0x57, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4B, 0x43, 0x42, 0x86, 0x46}; //16 +const PROGMEM uint8_t EnableI2C[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x92}; //28 +//const PROGMEM uint8_t PMREQBackup[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B}; //16 + +uint8_t GPS_GetByte(); +void GPS_OutputOn(); +void GPS_OutputOff(); +void GPS_PowerOn(int8_t pin, uint8_t state); +void GPS_PowerOff(int8_t pin, uint8_t state); +bool GPS_Setup(); +bool GPS_SendConfig(unsigned int Progmem_ptr, byte length, byte replylength); +bool GPS_WaitAck(unsigned long waitms, byte length); +//uint8_t GPS_GetNextChar(uint32_t waitmS); +//bool GPS_CheckAck(); +bool GPS_SetBalloonMode(); +bool GPS_CheckBalloonMode(); +bool GPS_ClearConfig(); +bool GPS_SetCyclicMode(); +bool GPS_SoftwareBackup(); +//bool GPS_HotStart(); +bool GPS_PollNavigation(); +bool GPS_SaveConfig(); +bool GPS_GLONASSOff(); +bool GPS_GPGLLOff(); +bool GPS_GPGLSOff(); +bool GPS_GPGSAOff(); +bool GPS_GPGSVOff(); +bool GPS_GNSSmode(); +bool GPS_GGARMCOnly(); +//void GPS_PMREQBackup(); +//void GPS_StartRead(); +//void GPS_SetGPMode(); +//void GPS_StopMessages(); + +const int16_t GPSI2CAddress = 0x42; +const uint32_t GPS_WaitAck_mS = 1000; //number of mS to wait for an ACK response from GPS +const uint8_t GPS_attempts = 5; //number of times the sending of GPS config will be attempted. +const uint8_t GPS_Reply_Size = 16; //size of GPS reply buffer +const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent +uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands + + +#define USING_I2CGPS //so the rest of the program knows I2C GPS is in use +#define UBLOX //so the rest of the program knows UBLOX GPS is in use +//#define GPSDEBUG //include define to see some debug messages + + + +uint8_t GPS_GetByte() //get and process output from GPS +{ + uint8_t GPSchar; + + Wire.requestFrom(GPSI2CAddress, 1); + GPSchar = Wire.read(); + + return GPSchar; +} + + + +void GPS_OutputOn() +{ +//not used function for I2C library, included for compatibility with other libraries +} + + +void GPS_OutputOff() +{ +//not used function for I2C library, included for compatibility with other libraries +} + + +/* +void GPS_StartRead() +{ + Wire.beginTransmission(GPSI2CAddress); + Wire.write(0xFF); +} +*/ + +void GPS_PowerOn(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOn() ")); +#endif + + if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +void GPS_PowerOff(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOff() ")); +#endif + +if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +bool GPS_WaitAck(uint32_t waitmS, uint8_t length) +{ + //wait for Ack from GPS + byte i, j; + uint32_t startmS; + + startmS = millis(); + + byte ptr = 0; //used as pointer to store GPS reply + + Wire.beginTransmission(GPSI2CAddress); + Wire.write(0xFF); + + do + { + Wire.requestFrom(GPSI2CAddress, 1); + i = Wire.read(); + } + while ((i != 0xb5) && ((uint32_t) (millis() - startmS) < waitmS)); + + if (i != 0xb5) + { + Serial.print(F("Timeout ")); + return false; + } + else + { + Serial.print(F("Ack ")); + Serial.print(i, HEX); + + length--; + + for (j = 1; j <= length; j++) + { + Serial.print(F(" ")); + + Wire.requestFrom(GPSI2CAddress, 1); + i = Wire.read(); + + if (j < 12) + { + GPS_Reply[ptr++] = i; //save reply in buffer, but no more than 10 characters + } + + if (i < 0x10) + { + Serial.print(F("0")); + } + Serial.print(i, HEX); + } + + } + Serial.println(); + return true; +} + + +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts) +{ + uint8_t byteread1, byteread2, index, length; + uint8_t config_attempts = attempts; + + do + { + + if (config_attempts == 0) + { + Serial.println(F("Fail")); + Serial.println(); + return false; + } + + length = arraysize / 2; //we are sending messages 2 bytes at a time + + for (index = 0; index < length; index++) + { + byteread1 = pgm_read_byte_near(Progmem_ptr++); //we will read and write 2 bytes at a time + byteread2 = pgm_read_byte_near(Progmem_ptr++); + Wire.beginTransmission(GPSI2CAddress); + Wire.write(byteread1); + Wire.write(byteread2); + Wire.endTransmission(); + if (byteread1 < 0x10) + { + Serial.print(F("0")); + } + Serial.print(byteread1, HEX); + Serial.print(F(" ")); + if (byteread2 < 0x10) + { + Serial.print(F("0")); + } + Serial.print(byteread2, HEX); + Serial.print(F(" ")); + } + + Progmem_ptr = Progmem_ptr - arraysize; //put Progmem_ptr back to start value in case we need to re-send the config + + Serial.println(); + + if (replylength == 0) + { + #ifdef GPSDebug + Serial.println(F("Reply not required")); + #endif + break; + } + + config_attempts--; + } while (!GPS_WaitAck(GPS_WaitAck_mS, replylength)); + + delay(50); //GPS can sometimes be a bit slow getting ready for next config + return true; +} + + +bool GPS_Setup() +{ + #ifdef GPSDebug + Serial.println(F("GPS_Setup()")); + #endif + /* + Wire.begin(); + GPS_ClearConfig(); + GPS_StopMessages(); + GPS_SetBalloonMode(); + GPS_SaveConfig(); + */ + + Wire.begin(); + + if (!GPS_ClearConfig()) + { + return false; + } + + if (!GPS_SetBalloonMode()) + { + return false; + } + + if (!GPS_GNSSmode()) + { + return false; + } + + if (!GPS_GPGLLOff()) + { + return false; + } + + if (!GPS_GPGLSOff()) + { + return false; + } + + if (!GPS_GPGSAOff()) + { + return false; + } + + if (!GPS_GPGSVOff()) + { + return false; + } + + if (!GPS_SaveConfig()) + { + return false; + } + + return true; +} + + +bool GPS_CheckBalloonMode() +{ + #ifdef GPSDebug + Serial.println(F("GPS_CheckBalloonMode()")); + #endif + + uint8_t j; + + GPS_Reply[7] = 0xff; + + GPS_PollNavigation(); + + j = GPS_Reply[7]; + + Serial.print(F("Dynamic Model is ")); + Serial.println(j); + + if (j != 6) + { + Serial.println(F("Dynamic Model 6 not Set !")); + return false; + } + else + { + return true; + } +} + +bool GPS_ClearConfig() +{ + #ifdef GPSDebug + Serial.println(F("GPS_ClearConfig()")); + #endif + + Serial.println(F("ClearConfig")); + size_t SIZE = sizeof(ClearConfig); + + if (!GPS_SendConfig(ClearConfig,SIZE,10,GPS_attempts)) + { + return false; + } + + Serial.println(F("Wait clear")); + delay(GPS_Clear_DelaymS); //wait a while for GPS to clear its settings + + return true; +} + +/* +void GPS_StopMessages() +{ + #ifdef GPSDebug + Serial.print(F("GPS GPGLLOff ")); + #endif + + size_t SIZE; + + SIZE = sizeof(GPGLLOff); + GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts); + + #ifdef GPSDebug + Serial.print(F("GPS GPGLSOff ")); + #endif + + SIZE = sizeof(GPGLSOff); + GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts); + + #ifdef GPSDebug + Serial.print(F("GPS GPGSAOff ")); + #endif + + SIZE = sizeof(GPGSAOff); + GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts); + + #ifdef GPSDebug + Serial.print(F("GPS GPGSVOff ")); + #endif + + SIZE = sizeof(GPGSVOff); + GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts); +} +*/ + +bool GPS_SetBalloonMode() +{ + #ifdef GPSDebug + Serial.print(F("GPS SetBalloonMode ")); + #endif + + size_t SIZE = sizeof(SetBalloonMode); + return GPS_SendConfig(SetBalloonMode, SIZE, 10, GPS_attempts); +} + + +bool GPS_SaveConfig() +{ + #ifdef GPSDebug + Serial.print(F("GPS_SaveConfig()")); + #endif + + size_t SIZE = sizeof(SaveConfig); + return GPS_SendConfig(SaveConfig, SIZE, 10, GPS_attempts); +} + + +bool GPS_PollNavigation() +{ + #ifdef GPSDebug + Serial.print(F("GPS_PollNavigation()")); + #endif + + size_t SIZE = sizeof(PollNavigation); + return GPS_SendConfig(PollNavigation, SIZE, 44, GPS_attempts); +} + +/* +void GPS_SetGPMode() +{ + #ifdef GPSDebug + Serial.print(F("GPS_SetGPMode()")); + #endif + + size_t SIZE = sizeof(SetCyclicMode); + GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts); +} +*/ + +bool GPS_SetCyclicMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetCyclicMode() ")); +#endif + + Serial.println(F("SetCyclicMode")); + size_t SIZE = sizeof(SetCyclicMode); + + return GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts); +} + + +bool GPS_SoftwareBackup() +{ + #ifdef GPSDebug + Serial.print(F("GPS_SoftwareBackup()")); + #endif + + size_t SIZE = sizeof(SoftwareBackup); + return GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts); +} + +/* +void GPS_PMREQBackup() +{ + #ifdef GPSDebug + Serial.print(F("GPS_PMREQBackup()")); + #endif + + size_t SIZE = sizeof(PMREQBackup); + GPS_SendConfig(PMREQBackup, SIZE, 0, GPS_attempts); +} +*/ + + +bool GPS_GLONASSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GLONASSOff() ")); +#endif + + size_t SIZE = sizeof(GLONASSOff); + return GPS_SendConfig(GLONASSOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGLLOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLLOff() ")); +#endif + + size_t SIZE = sizeof(GPGLLOff); + return GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGLSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLSOff() ")); +#endif + + size_t SIZE = sizeof(GPGLSOff); + return GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGSAOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSAOff() ")); +#endif + + size_t SIZE = sizeof(GPGSAOff); + return GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGSVOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSVOff() ")); +#endif + + size_t SIZE = sizeof(GPGSVOff); + return GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GNSSmode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GNSSmode() ")); +#endif + + size_t SIZE = sizeof(GNSSmode); + return GPS_SendConfig(GNSSmode, SIZE, 10, GPS_attempts); +} + + +bool GPS_GGARMCOnly() +{ +//null function, not used with Ublox library +return true; +} + + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ diff --git a/lib/SX12XX-LoRa/src/UBLOXSerialGPS.h b/lib/SX12XX-LoRa/src/UBLOXSerialGPS.h new file mode 100644 index 0000000..9b09232 --- /dev/null +++ b/lib/SX12XX-LoRa/src/UBLOXSerialGPS.h @@ -0,0 +1,690 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 27/06/20 +*/ + +/******************************************************************************************************* + Program Operation - This is a library file for the UBLOX 6,7 and 8 series GPSs. + + The routines assume that the GPS has been setup on GPSserial which could be either software serial or + hardware serial. This library file can be used with both Hardware serial and SoftwareSerial. The + configuration of the GPS prints debug output to the Serial console and mixing thisdebug output with + the use of software serial has required several optimistations, in particular tha the GPS serial + output is turned off at some points in the configuration process to allow prints to the serial monitor + to continue without interruption or missed characters, see the post below for details on the problem; + + https://stuartsprojects.github.io/2020/05/05/softwareserial-problems.html + + The library assumes that the GPS is connected onto a port named GPSserial, this is achived in software + serial with; + + SoftwareSerial GPSserial(RXpin, TXpin); + + And for hardware serial, assuming Serila2 is used for the GPS with; + + #define GPSserial Serial2 + + The calling program should also include a define for the GPS baud rate as follows; + + #define GPSBaud 9600 + + If this define is missing then 9600 baud is assumed +*******************************************************************************************************/ + + + +const PROGMEM uint8_t ClearConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x19, 0x98}; //21 +const PROGMEM uint8_t SetBalloonMode[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, + 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC + }; //44 +const PROGMEM uint8_t SaveConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA9}; //22 +const PROGMEM uint8_t SetCyclicMode[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92}; //10 +const PROGMEM uint8_t SoftwareBackup[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B}; //16 +const PROGMEM uint8_t PollNavigation[] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00, 0x2A, 0x84}; //8 + +//B5 62 06 57 08 00 01 00 00 00 50 4B 43 42 86 46 + +//these are the commands to turn off NMEA sentences +const PROGMEM uint8_t GLONASSOff[] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2}; //20 +const PROGMEM uint8_t GPGLLOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A}; //16 +const PROGMEM uint8_t GPGLSOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46}; //16 +const PROGMEM uint8_t GPGSAOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31}; //16 +const PROGMEM uint8_t GPGSVOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38}; //16 + +const PROGMEM uint8_t GNSSmode[] = {0xB5, 0x62, 0x06, 0x3E, 0x2C, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, +0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00, +0x00, 0x00, 0x01, 0x01, 0xFC, 0x11}; + +//response to PollNavigation should be B5 62 06 24 24 00 FF FF 06 03 +//accepted response to configuaration command should be UBX-ACK-ACK B5 62 05 01 +//fail response to configuaration command should be UBX-ACK-NAK B5 62 05 00 + +uint8_t GPS_GetByte(); +void GPS_OutputOn(); +void GPS_OutputOff(); +void GPS_PowerOn(int8_t pin, uint8_t state); +void GPS_PowerOff(int8_t pin, uint8_t state); +bool GPS_Setup(); +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts); +bool GPS_WaitAck(uint32_t waitms, uint8_t length); +bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS); +//uint8_t GPS_GetNextChar(uint32_t waitmS); +bool GPS_CheckAck(); +bool GPS_SetBalloonMode(); +bool GPS_CheckBalloonMode(); +bool GPS_ClearConfig(); +bool GPS_SetCyclicMode(); +bool GPS_SoftwareBackup(); +bool GPS_HotStart(); +bool GPS_PollNavigation(); +bool GPS_SaveConfig(); +bool GPS_GLONASSOff(); +bool GPS_GPGLLOff(); +bool GPS_GPGLSOff(); +bool GPS_GPGSAOff(); +bool GPS_GPGSVOff(); +bool GPS_GNSSmode(); +bool GPS_GGARMCOnly(); + +const uint32_t GPS_WaitAck_mS = 1000; //number of mS to wait for an ACK response from GPS +const uint8_t GPS_attempts = 10; //number of times the sending of GPS config will be attempted. +const uint8_t GPS_Reply_Size = 16; //size of GPS reply buffer +const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent +uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands + + +#define UBLOXINUSE //so complier can know which GPS library is used +//#define GPSDebug + +#ifndef GPSBaud +#define GPSBaud 9600 +#endif + + +void GPS_OutputOn() +{ +#ifdef GPSDebug + Serial.print(F("GPS_On() ")); +#endif + uint8_t GPSchar = 0; + //turns on serial output from GPS + GPSserial.begin(GPSBaud); + GPSserial.write(GPSchar); +} + + +void GPS_OutputOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_Off() ")); +#endif + + GPSserial.end(); //turns off serial output from GPS +} + + +void GPS_PowerOn(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOn() ")); +#endif + + if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +void GPS_PowerOff(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOff() ")); +#endif + +if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +bool GPS_Setup() +{ +#ifdef GPSDebug + Serial.print(F("GPS_Setup() ")); +#endif + + if (!GPS_ClearConfig()) + { + return false; + } + + if (!GPS_SetBalloonMode()) + { + return false; + } + + if (!GPS_GNSSmode()) + { + return false; + } + + if (!GPS_GPGLLOff()) + { + return false; + } + + if (!GPS_GPGLSOff()) + { + return false; + } + + if (!GPS_GPGSAOff()) + { + return false; + } + + if (!GPS_GPGSVOff()) + { + return false; + } + + if (!GPS_SaveConfig()) + { + return false; + } + + return true; +} + + +bool GPS_CheckBalloonMode() +{ + //navigation model setting for UBLOX is at GPS_Reply[8] of poll request reply. + +#ifdef GPSDebug + Serial.print(F("GPS_CheckBalloonMode() ")); +#endif + + uint8_t j; + GPS_Reply[8] = 0xff; + + GPS_PollNavigation(); + + if ( (GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62) && (GPS_Reply[2] == 0x06) && (GPS_Reply[3] == 0X24) ) + { + j = GPS_Reply[8]; + + if (j == 6) + { + return true; + } + else + { + return false; + } + } + + return false; + +} + + +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts) +{ +#ifdef GPSDebug + Serial.print(F("GPS_SendConfig() ")); +#endif + + uint8_t byteread, index; + uint8_t config_attempts = attempts; + + Serial.flush(); //ensure there are no pending interrupts from serial monitor printing + + do + { + if (config_attempts == 0) + { + Serial.println(F("Fail")); + Serial.println(); + return false; + } + + GPS_OutputOff(); + + Serial.print(F("GPSSend ")); + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + if (byteread < 0x10) + { + Serial.print(F("0")); + } + Serial.print(byteread, HEX); + Serial.print(F(" ")); + } + + Serial.flush(); //make sure serial out buffer is empty + + GPS_OutputOn(); + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + GPSserial.write(byteread); + } + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start + + if (replylength == 0) + { +#ifdef GPSDebug + Serial.println(F("Reply not required")); +#endif + break; + } + GPSserial.flush(); //make sure all of config command has been sent + config_attempts--; + } + while (!GPS_WaitAck(GPS_WaitAck_mS, replylength)); + + Serial.println(F("OK")); + Serial.println(); + delay(100); //GPS can sometimes be a bit slow getting ready for next config + + return true; +} + + +bool GPS_WaitAck(uint32_t waitmS, uint8_t length) +{ +#ifdef GPSDebug + Serial.print(F("GPS_WaitAck() ")); + Serial.print(F(" Reply length ")); + Serial.print(length); + Serial.print(F(" ")); +#endif + + //wait for Ack (UBX-ACK-ACK) response from GPS is 0xb5,0x62, 0x05, 0x01 + //Nack (UBX-ACK-NAK) response from GPS is 0xb5,0x62, 0x05, 0x00 + + uint8_t GPSchar; + uint32_t startmS; + + startmS = millis(); + + uint8_t ptr = 0; //used as pointer to store GPS reply + + Serial.println(); + Serial.print(F("Received ")); + Serial.flush(); + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + } + } + while ((GPSchar != 0xb5) && ((uint32_t) (millis() - startmS) < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang + + if (GPSchar != 0xb5) + { + Serial.println(F("Timeout Error")); + return false; + } + + GPS_Reply[ptr++] = 0xB5; //test if a 0xB5 has been received + + startmS = millis(); + + do + { + if (GPSserial.available()) + { + GPS_Reply[ptr++] = GPSserial.read(); + } + } + while ((ptr < length) && ((uint32_t) (millis() - startmS) < waitmS)); //fill buffer, stop when either ptr is (length-1) or timeout + + + if (ptr < length) + { + Serial.print(F("Short Reply Error")); + return false; + } + + GPS_OutputOff(); + + for (ptr = 0; ptr < length; ptr++) + { + GPSchar = GPS_Reply[ptr]; + + if (GPSchar < 0x10) + { + Serial.print(F("0")); + } + + Serial.print(GPSchar , HEX); + Serial.print(F(" ")); + } + + Serial.println(); + + if (GPS_CheckAck()) + { + return true; + } + + return false; +} + + +bool GPS_WaitChar(uint8_t waitforchar, uint32_t waitmS) +{ + uint8_t GPSchar; + uint32_t startmS; + + startmS = millis(); + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + if (GPSchar == waitforchar) + { + GPS_Reply[0] = GPSchar; + return true; + } + } + } + while ((uint32_t) (millis() - startmS) < waitmS); //use the timeout to ensure a lack of GPS does not cause the program to hang + return false; +} + +/* +uint8_t GPS_GetNextChar(uint32_t waitmS) +{ + uint8_t GPSchar; + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + GPS_Reply[1] = GPSchar; + return GPSchar; + } + } + while ((millis() < waitmS)); //use the timeout to ensure a lack of GPS does not cause the program to hang + return '*'; +} +*/ + + +bool GPS_PollNavigation() +{ +#ifdef GPSDebug + Serial.print(F("GPS_PollNavigation() ")); +#endif + //Serial.println(F("PollNavigation")); + size_t SIZE = sizeof(PollNavigation); + if (GPS_SendConfig(PollNavigation, SIZE, 10, GPS_attempts)) + { + return true; + } + return false; +} + + + +bool GPS_CheckAck() +{ + +#ifdef GPSDebug + Serial.print(F("GPS_CheckAck() ")); +#endif + + if ((GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62)) + { +#ifdef GPSDebug + Serial.println(F(" UBX-ACK-ACK")); +#endif + return true; //there has been a UBX-ACK-ACK response + } + else + { +#ifdef GPSDebug + Serial.println(F(" Not UBX-ACK-ACK ")); +#endif + return false; //there has been a UBX-ACK-ACK response + } +} + + + +/********************************************************************* + // GPS configuration commands +*********************************************************************/ + + +bool GPS_ClearConfig() +{ + #ifdef GPSDebug + Serial.print(F("GPS_ClearConfig() ")); + #endif + + //Serial.println(F("ClearConfig")); + size_t SIZE = sizeof(ClearConfig); + if (GPS_SendConfig(ClearConfig, SIZE, 10, GPS_attempts)) + { + Serial.println(F("Wait clear")); + Serial.println(); + delay(GPS_Clear_DelaymS); //wait a while for GPS to clear its settings + return true; + } + + return false; +} + + +bool GPS_SetBalloonMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetBalloonMode() ")); +#endif + + //Serial.println(F("SetBalloonMode")); + size_t SIZE = sizeof(SetBalloonMode); + if (GPS_SendConfig(SetBalloonMode, SIZE, 10, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_SaveConfig() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SaveConfig() ")); +#endif + + //Serial.println(F("SaveConfig")); + size_t SIZE = sizeof(SaveConfig); + + if (GPS_SendConfig(SaveConfig, SIZE, 10, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_SetCyclicMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetCyclicMode() ")); +#endif + + //Serial.println(F("SetCyclicMode")); + size_t SIZE = sizeof(SetCyclicMode); + + if (GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_SoftwareBackup() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SoftwareBackup() ")); +#endif + + //Serial.println(F("SoftwareBackup")); + size_t SIZE = sizeof(SoftwareBackup); + + if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts)) + { + return true; + } + + return false; +} + + + +bool GPS_HotStart() + { + #ifdef GPSDebug + Serial.print(F("GPS_HotStart() ")); + #endif + + //Serial.println(F("HotStart")); + GPSserial.println(); + + return true; + +} + + + +bool GPS_GLONASSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GLONASSOff() ")); +#endif + + size_t SIZE = sizeof(GLONASSOff); + return GPS_SendConfig(GLONASSOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGLLOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLLOff() ")); +#endif + + size_t SIZE = sizeof(GPGLLOff); + return GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGLSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLSOff() ")); +#endif + + size_t SIZE = sizeof(GPGLSOff); + return GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGSAOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSAOff() ")); +#endif + + size_t SIZE = sizeof(GPGSAOff); + return GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGSVOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSVOff() ")); +#endif + + size_t SIZE = sizeof(GPGSVOff); + return GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GNSSmode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GNSSmode() ")); +#endif + + size_t SIZE = sizeof(GNSSmode); + return GPS_SendConfig(GNSSmode, SIZE, 10, GPS_attempts); +} + + +uint8_t GPS_GetByte() //get a byte for GPS +{ + if (GPSserial.available() == 0) + { + return 0xFF; //for compatibility with I2C reading of GPS + } + else + { + return GPSserial.read(); + } +} + + +bool GPS_GGARMCOnly() +{ +//null function, not used with Ublox library +return true; +} + + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/lib/SX12XX-LoRa/src/UBLOX_HWSerialGPS.h b/lib/SX12XX-LoRa/src/UBLOX_HWSerialGPS.h new file mode 100644 index 0000000..be6c477 --- /dev/null +++ b/lib/SX12XX-LoRa/src/UBLOX_HWSerialGPS.h @@ -0,0 +1,580 @@ +/* + Copyright 2020 - Stuart Robinson + Licensed under a MIT license displayed at the bottom of this document. + Original published 07/08/20 +*/ + +const PROGMEM uint8_t ClearConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x19, 0x98}; //21 +const PROGMEM uint8_t SetBalloonMode[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, + 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC + }; //44 +const PROGMEM uint8_t SaveConfig[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA9}; //22 +const PROGMEM uint8_t SetCyclicMode[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92}; //10 +const PROGMEM uint8_t SoftwareBackup[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B}; //16 +const PROGMEM uint8_t PollNavigation[] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00, 0x2A, 0x84}; //8 + +//these are the commands to turn off NMEA sentences +const PROGMEM uint8_t GLONASSOff[] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2}; //20 +const PROGMEM uint8_t GPGLLOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A}; //16 +const PROGMEM uint8_t GPGLSOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46}; //16 +const PROGMEM uint8_t GPGSAOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31}; //16 +const PROGMEM uint8_t GPGSVOff[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38}; //16 +const PROGMEM uint8_t GNSSmode[] = {0xB5, 0x62, 0x06, 0x3E, 0x2C, 0x00, 0x00, 0x00, 0x20, 0x05, 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, +0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x08, 0x0E, 0x00, +0x00, 0x00, 0x01, 0x01, 0xFC, 0x11}; + +//response to PollNavigation should be B5 62 06 24 24 00 FF FF 06 03 +//accepted response to configuaration command should be UBX-ACK-ACK B5 62 05 01 +//fail response to configuaration command should be UBX-ACK-NAK B5 62 05 00 + +void GPS_OutputOn(); +void GPS_OutputOff(); +void GPS_PowerOn(); +bool GPS_CheckConfiguration(); +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts); +bool GPS_WaitAck(uint32_t waitms, uint8_t length); +bool GPS_PollNavigation(); + +bool GPS_ClearConfig(); +bool GPS_SaveConfig(); +bool GPS_SetBalloonMode(); +bool GPS_SetCyclicMode(); +bool GPS_SoftwareBackup(); +bool GPS_GLONASSOff(); +bool GPS_GPGLLOff(); +bool GPS_GPGLSOff(); +bool GPS_GPGSAOff(); +bool GPS_GPGSVOff(); +bool GPS_GNSSmode(); +bool GPS_CheckAck(); +uint8_t GPS_GetByte(); + + +const uint32_t GPS_WaitAck_mS = 1000; //number of mS to wait for an ACK response from GPS +const uint8_t GPS_attempts = 5; //number of times the sending of GPS config will be attempted. +const uint8_t GPS_Reply_Size = 16; //size of GPS reply buffer +const uint16_t GPS_Clear_DelaymS = 2000; //mS to wait after a GPS Clear command is sent +uint8_t GPS_Reply[GPS_Reply_Size]; //byte array for storing GPS reply to UBX commands + + +#define UBLOXINUSE //so complier can know which GPS library is used +//#define GPSDebug + +#ifndef GPSConfigSerial // if GPSDebugSerial is not defined set to Serial as default + #define GPSConfigSerial Serial +#endif + +#ifndef GPSDebugSerial // if GPSDebugSerial is not defined set to Serial as default + #define GPSDebugSerial Serial +#endif + +#ifndef GPSBaud +#define GPSBaud 9600 +#endif + + +void GPS_OutputOn() +{ +#ifdef GPSDebug + Serial.print(F("GPS_On() ")); +#endif + uint8_t GPSchar = 0; + //turns on serial output from GPS + GPSserial.begin(GPSBaud); + GPSserial.write(GPSchar); +} + + +void GPS_OutputOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_Off() ")); +#endif + + GPSserial.end(); //turns off serial output from GPS +} + + +void GPS_PowerOn(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOn() ")); +#endif + + if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + +void GPS_PowerOff(int8_t pin, uint8_t state) +{ +#ifdef GPSDebug + Serial.print(F("GPS_PowerOff() ")); +#endif + +if (pin >= 0) + { + digitalWrite(pin, state); + } + +} + + + +bool GPS_Setup() +{ +#ifdef GPSDebug + Serial.print(F("GPS_Setup() ")); +#endif + + if (!GPS_ClearConfig()) + { + return false; + } + + if (!GPS_SetBalloonMode()) + { + return false; + } + + if (!GPS_CheckConfiguration()) + { + return false; + } + + if (!GPS_SaveConfig()) + { + return false; + } + + return true; +} + + +bool GPS_CheckConfiguration() +{ + //navigation model setting for UBLOX is at GPS_Reply[8] of poll request reply. + +#ifdef GPSDebug + Serial.print(F("GPS_CheckConfiguration() UBLOX ")); +#endif + + uint8_t j; + GPS_Reply[8] = 0xff; + + GPS_PollNavigation(); + + if ( (GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62) && (GPS_Reply[2] == 0x06) && (GPS_Reply[3] == 0X24) ) + { + j = GPS_Reply[8]; + + if (j == 6) + { + return true; + } + else + { + return false; + } + } + + return false; + +} + + +bool GPS_SendConfig(const uint8_t *Progmem_ptr, uint8_t arraysize, uint8_t replylength, uint8_t attempts) +{ +#ifdef GPSDebug + Serial.print(F("GPS_SendConfig() ")); +#endif + + + + uint8_t byteread, index; + uint8_t config_attempts = attempts; + + Serial.flush(); //ensure there are no pending interrupts from serial monitor printing + + do + { + if (config_attempts == 0) + { + Serial.println(F("Fail")); + Serial.println(); + return false; + } + + Serial.print(F("GPSSend ")); + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + Serial.print(byteread, HEX); + Serial.print(F(" ")); + } + + Serial.flush(); //make sure serial out buffer is empty + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start + + for (index = 0; index < arraysize; index++) + { + byteread = pgm_read_byte_near(Progmem_ptr++); + GPSserial.write(byteread); + } + + Progmem_ptr = Progmem_ptr - arraysize; //set Progmem_ptr back to start + + if (replylength == 0) + { +#ifdef GPSDebug + Serial.println(F("Reply not required")); +#endif + break; + } + + config_attempts--; + } + while (!GPS_WaitAck(GPS_WaitAck_mS, replylength)); + + Serial.println(F("OK")); + Serial.println(); + delay(100); //GPS can sometimes be a bit slow getting ready for next config + + return true; +} + + +bool GPS_WaitAck(uint32_t waitms, uint8_t length) +{ +#ifdef GPSDebug + Serial.print(F("GPS_WaitAck() ")); + Serial.print(F(" Reply length ")); + Serial.print(length); + Serial.print(F(" ")); +#endif + + //wait for Ack (UBX-ACK-ACK) response from GPS is 0xb5,0x62, 0x05, 0x01 + //Nack (UBX-ACK-NAK) response from GPS is 0xb5,0x62, 0x05, 0x00 + + uint8_t GPSchar; + + uint32_t endms; + endms = millis() + waitms; + uint8_t ptr = 0; //used as pointer to store GPS reply + + Serial.println(); + Serial.print(F("Received ")); + Serial.flush(); + + + do + { + if (GPSserial.available()) + { + GPSchar = GPSserial.read(); + } + } + while ((GPSchar != 0xb5) && (millis() < endms)); //use the timeout to ensure a lack of GPS does not cause the program to hang + + if (GPSchar != 0xb5) + { + Serial.println(F("Timeout Error")); + return false; + } + + GPS_Reply[ptr++] = 0xB5; //test if a 0xB5 has been received + + do + { + if (GPSserial.available()) + { + GPS_Reply[ptr++] = GPSserial.read(); + } + } + while ((ptr < length) || (millis() >= endms)); //fill buffer, stop when either ptr is (length-1) or timeout + + + if (millis() >= endms) //check for another timeout + { + Serial.print(F("NoReply Error")); + return false; + } + + for (ptr = 0; ptr < length; ptr++) + { + GPSchar = GPS_Reply[ptr]; + + if (GPSchar < 0x10) + { + Serial.print(F("0")); + } + + Serial.print(GPSchar , HEX); + Serial.print(F(" ")); + } + + Serial.println(); + + if (GPS_CheckAck()) + { + return true; + } + + return false; +} + + +bool GPS_PollNavigation() +{ +#ifdef GPSDebug + Serial.print(F("GPS_PollNavigation() ")); +#endif + Serial.println(F("PollNavigation")); + size_t SIZE = sizeof(PollNavigation); + if (GPS_SendConfig(PollNavigation, SIZE, 10, GPS_attempts)) + { + return true; + } + return false; +} + + + +bool GPS_CheckAck() +{ + +#ifdef GPSDebug + Serial.print(F("GPS_CheckAck() ")); +#endif + + if ((GPS_Reply[0] == 0xB5) && (GPS_Reply[1] == 0x62)) + { +#ifdef GPSDebug + Serial.println(F(" UBX-ACK-ACK")); +#endif + return true; //there has been a UBX-ACK-ACK response + } + else + { +#ifdef GPSDebug + Serial.println(F(" Not UBX-ACK-ACK ")); +#endif + return false; //there has been a UBX-ACK-ACK response + } +} + + + +/********************************************************************* + // GPS configuration commands +*********************************************************************/ + + +bool GPS_ClearConfig() +{ + #ifdef GPSDebug + Serial.print(F("GPS_ClearConfig() ")); + #endif + + Serial.println(F("ClearConfig")); + size_t SIZE = sizeof(ClearConfig); + if (GPS_SendConfig(ClearConfig, SIZE, 10, GPS_attempts)) + { + Serial.println(F("Wait clear")); + Serial.println(); + delay(GPS_Clear_DelaymS); //wait a while for GPS to clear its settings + return true; + } + + return false; +} + + +bool GPS_SetBalloonMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetBalloonMode() ")); +#endif + + Serial.println(F("SetBalloonMode")); + size_t SIZE = sizeof(SetBalloonMode); + if (GPS_SendConfig(SetBalloonMode, SIZE, 10, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_SaveConfig() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SaveConfig() ")); +#endif + + Serial.println(F("SaveConfig")); + size_t SIZE = sizeof(SaveConfig); + + if (GPS_SendConfig(SaveConfig, SIZE, 10, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_SetCyclicMode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SetCyclicMode() ")); +#endif + + Serial.println(F("SetCyclicMode")); + size_t SIZE = sizeof(SetCyclicMode); + + if (GPS_SendConfig(SetCyclicMode, SIZE, 10, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_SoftwareBackup() +{ +#ifdef GPSDebug + Serial.print(F("GPS_SoftwareBackup() ")); +#endif + + Serial.println(F("SoftwareBackup")); + size_t SIZE = sizeof(SoftwareBackup); + + if (GPS_SendConfig(SoftwareBackup, SIZE, 0, GPS_attempts)) + { + return true; + } + + return false; +} + + +bool GPS_HotStart() + { + #ifdef GPSDebug + Serial.print(F("GPS_HotStart() ")); + #endif + + Serial.println(F("HotStart")); + GPSserial.println(); + + return true; + +} + + +bool GPS_GLONASSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GLONASSOff() ")); +#endif + + size_t SIZE = sizeof(GLONASSOff); + return GPS_SendConfig(GLONASSOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGLLOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLLOff() ")); +#endif + + size_t SIZE = sizeof(GPGLLOff); + return GPS_SendConfig(GPGLLOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGLSOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGLSOff() ")); +#endif + + size_t SIZE = sizeof(GPGLSOff); + return GPS_SendConfig(GPGLSOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGSAOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSAOff() ")); +#endif + + size_t SIZE = sizeof(GPGSAOff); + return GPS_SendConfig(GPGSAOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GPGSVOff() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GPGSVOff() ")); +#endif + + size_t SIZE = sizeof(GPGSVOff); + return GPS_SendConfig(GPGSVOff, SIZE, 10, GPS_attempts); +} + + +bool GPS_GNSSmode() +{ +#ifdef GPSDebug + Serial.print(F("GPS_GNSSmode() ")); +#endif + + size_t SIZE = sizeof(GNSSmode); + return GPS_SendConfig(GNSSmode, SIZE, 10, GPS_attempts); +} + + +uint8_t GPS_GetByte() //get a byte for GPS +{ + if (GPSserial.available() == 0) + { + return 0xFF; //for compatibility with I2C reading of GPS + } + else + { + return GPSserial.read(); + } +} + + + +/* + MIT license + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..d5317d7 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,22 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = arduino +lib_deps = + adafruit/Adafruit BNO055@^1.4.3 + adafruit/Adafruit BMP3XX Library@^2.0.2 + bblanchon/ArduinoJson@^6.17.3 + adafruit/Adafruit BMP085 Library@^1.2.0 + adafruit/Adafruit SHT31 Library@^2.0.0 + slashdevin/NeoGPS@^4.2.9 +monitor_speed = 115200 diff --git a/src/bmp180.h b/src/bmp180.h new file mode 100644 index 0000000..f2597e6 --- /dev/null +++ b/src/bmp180.h @@ -0,0 +1,45 @@ +#include + +Adafruit_BMP085 bmp180; + +void setup_180() { + if (!bmp180.begin()) { + Serial.println("Could not find a valid BMP085 sensor, check wiring!"); + } +} + +void loop_180(JsonObject &root) { + JsonObject bmp388 = root.createNestedObject("bmp388"); + /* + Serial.print("Temperature = "); + Serial.print(bmp180.readTemperature()); + Serial.println(" *C"); + + Serial.print("Pressure = "); + Serial.print(bmp180.readPressure()); + Serial.println(" Pa"); + + // Calculate altitude assuming 'standard' barometric + // pressure of 1013.25 millibar = 101325 Pascal + Serial.print("Altitude = "); + Serial.print(bmp180.readAltitude()); + Serial.println(" meters"); + + Serial.print("Pressure at sealevel (calculated) = "); + Serial.print(bmp180.readSealevelPressure()); + Serial.println(" Pa"); + + // you can get a more precise measurement of altitude + // if you know the current sea level pressure which will + // vary with weather and such. If it is 1015 millibars + // that is equal to 101500 Pascals. + Serial.print("Real altitude = "); + Serial.print(bmp180.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" meters"); + + Serial.println(); + */ + bmp388["temperature"] = bmp180.readTemperature(); + bmp388["pressure"] = bmp180.readPressure(); + bmp388["altitude"] = bmp180.readAltitude(); +} \ No newline at end of file diff --git a/src/bmp388.h b/src/bmp388.h new file mode 100644 index 0000000..0d53dc6 --- /dev/null +++ b/src/bmp388.h @@ -0,0 +1,40 @@ +#include + +Adafruit_BMP3XX bmp; + +void setup_bmp() { + if (!bmp.begin_I2C()) { // hardware I2C mode, can pass in address & alt Wire + Serial.println("Could not find a valid BMP3 sensor, check wiring!"); + return; + } + bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X); + bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X); + bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3); + bmp.setOutputDataRate(BMP3_ODR_50_HZ); +} + +void loop_bmp(JsonObject &root) { +JsonObject bmp388 = root.createNestedObject("bmp388"); + if (! bmp.performReading()) { + Serial.println("Failed to perform reading :("); + return; + } + #ifdef debug + Serial.print("Temperature = "); + Serial.print(bmp.temperature); + Serial.println(" *C"); + + Serial.print("Pressure = "); + Serial.print(bmp.pressure / 100.0); + Serial.println(" hPa"); + + Serial.print("Approx. Altitude = "); + Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" m"); + + Serial.println(); + #endif + bmp388["temperature"] = bmp.temperature; + bmp388["pressure"] = bmp.pressure; + bmp388["altitude"] = bmp.readAltitude(SEALEVELPRESSURE_HPA); +} \ No newline at end of file diff --git a/src/bno055.h b/src/bno055.h new file mode 100644 index 0000000..654b39b --- /dev/null +++ b/src/bno055.h @@ -0,0 +1,160 @@ +#include + +#define BNO055_SAMPLERATE_DELAY_MS (100) +Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x29); + +void displaySensorDetails(void) +{ + sensor_t sensor; + bno.getSensor(&sensor); + Serial.println("------------------------------------"); + Serial.print ("Sensor: "); Serial.println(sensor.name); + Serial.print ("Driver Ver: "); Serial.println(sensor.version); + Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); + Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" xxx"); + Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" xxx"); + Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" xxx"); + Serial.println("------------------------------------"); + Serial.println(""); +} + +void setup_bno(void) +{ + Serial.println("Orientation Sensor Test"); Serial.println(""); + + /* Initialise the sensor */ + if(!bno.begin()) + { + /* There was a problem detecting the BNO055 ... check your connections */ + Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!"); + return; + } + + /* Use external crystal for better accuracy */ + bno.setExtCrystalUse(true); + + /* Display some basic information on this sensor */ + displaySensorDetails(); +} + +void printEvent(sensors_event_t* event, JsonObject obj) { + double x = -1000000, y = -1000000 , z = -1000000; //dumb values, easy to spot problem + if (event->type == SENSOR_TYPE_ACCELEROMETER) { + #ifdef debug + Serial.print("Accl:"); + #endif + x = event->acceleration.x; + y = event->acceleration.y; + z = event->acceleration.z; + } + else if (event->type == SENSOR_TYPE_ORIENTATION) { + #ifdef debug + Serial.print("Orient:"); + #endif + x = event->orientation.x; + y = event->orientation.y; + z = event->orientation.z; + } + else if (event->type == SENSOR_TYPE_MAGNETIC_FIELD) { + #ifdef debug + Serial.print("Mag:"); + #endif + x = event->magnetic.x; + y = event->magnetic.y; + z = event->magnetic.z; + } + else if (event->type == SENSOR_TYPE_GYROSCOPE) { + #ifdef debug + Serial.print("Gyro:"); + #endif + x = event->gyro.x; + y = event->gyro.y; + z = event->gyro.z; + } + else if (event->type == SENSOR_TYPE_ROTATION_VECTOR) { + #ifdef debug + Serial.print("Rot:"); + #endif + x = event->gyro.x; + y = event->gyro.y; + z = event->gyro.z; + } + else if (event->type == SENSOR_TYPE_LINEAR_ACCELERATION) { + #ifdef debug + Serial.print("Linear:"); + #endif + x = event->acceleration.x; + y = event->acceleration.y; + z = event->acceleration.z; + } + else { + #ifdef debug + Serial.print("Unk:"); + #endif + } + obj["x"] = x; + obj["y"] = y; + obj["z"] = z; + #ifdef debug + Serial.print("\tx= "); + Serial.print(x); + Serial.print(" |\ty= "); + Serial.print(y); + Serial.print(" |\tz= "); + Serial.println(z); + #endif +} + + +void loop_bno(JsonObject &root) +{ + JsonObject bno055 = root.createNestedObject("bno055"); + sensors_event_t orientationData , angVelocityData , linearAccelData, magnetometerData, accelerometerData, gravityData; + bno.getEvent(&orientationData, Adafruit_BNO055::VECTOR_EULER); + bno.getEvent(&angVelocityData, Adafruit_BNO055::VECTOR_GYROSCOPE); + bno.getEvent(&linearAccelData, Adafruit_BNO055::VECTOR_LINEARACCEL); + bno.getEvent(&magnetometerData, Adafruit_BNO055::VECTOR_MAGNETOMETER); + bno.getEvent(&accelerometerData, Adafruit_BNO055::VECTOR_ACCELEROMETER); + bno.getEvent(&gravityData, Adafruit_BNO055::VECTOR_GRAVITY); + JsonObject orientation_data = bno055.createNestedObject("orientation_data"); + printEvent(&orientationData, orientation_data); + JsonObject ang_velocity_data = bno055.createNestedObject("ang_velocity_data"); + printEvent(&angVelocityData, ang_velocity_data); + JsonObject linear_accel_data = bno055.createNestedObject("linear_accel_data"); + printEvent(&linearAccelData, linear_accel_data); + JsonObject magnetometer_data = bno055.createNestedObject("magnetometer_data"); + printEvent(&magnetometerData, magnetometer_data); + JsonObject accelerometer_data = bno055.createNestedObject("accelerometer_data"); + printEvent(&accelerometerData, accelerometer_data); + JsonObject gravity_data = bno055.createNestedObject("gravity_data"); + printEvent(&gravityData, gravity_data); + + int8_t boardTemp = bno.getTemp(); + #ifdef bebug + Serial.println(); + Serial.print(F("temperature: ")); + Serial.println(boardTemp); + #endif + bno055["temperature"] = boardTemp; + + uint8_t system, gyro, accel, mag = 0; + bno.getCalibration(&system, &gyro, &accel, &mag); + JsonObject calibration = bno055.createNestedObject("calibration"); + calibration["system"] = system; + calibration["gyro"] = gyro; + calibration["accel"] = accel; + calibration["mag"] = mag; + #ifdef debug + Serial.println(); + Serial.print("Calibration: Sys="); + Serial.print(system); + Serial.print(" Gyro="); + Serial.print(gyro); + Serial.print(" Accel="); + Serial.print(accel); + Serial.print(" Mag="); + Serial.println(mag); + + Serial.println("--"); + #endif +} \ No newline at end of file diff --git a/src/gps.h b/src/gps.h new file mode 100644 index 0000000..d6e60b5 --- /dev/null +++ b/src/gps.h @@ -0,0 +1,28 @@ +#include +#ifndef GPSport_h +#define GPSport_h + +#define gpsPort Serial2 +#define GPS_PORT_NAME "Serial2" + +#endif + + +static NMEAGPS gps; +gps_fix fix; + +void setup_gps() +{ + gpsPort.begin(9600); +} + +void loop_gps(JsonObject &root) +{ + if (gps.available( gpsPort)) { + fix = gps.read(); + } + JsonObject gps = root.createNestedObject("gps"); + gps["lat"] = fix.latitude(); + gps["lon"] = fix.longitude(); + gps["alt"] = fix.altitude(); +} \ No newline at end of file diff --git a/src/lora.h b/src/lora.h new file mode 100644 index 0000000..b100f5a --- /dev/null +++ b/src/lora.h @@ -0,0 +1,93 @@ +#include +#include + +#define NSS 5 //select on LoRa device +#define SCK 18 //SCK on SPI3 +#define MISO 19 //MISO on SPI3 +#define MOSI 23 //MOSI on SPI3 + +#define NRESET 35 //reset on LoRa device +#define DIO0 33 //DIO0 on LoRa device, used for RX and TX done +#define DIO1 32 //DIO1 on LoRa device, normally not used so set to -1 +#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1 + +#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using + +//******* Setup LoRa Test Parameters Here ! *************** + +//LoRa Modem Parameters +const uint32_t Frequency = 429700000; //frequency of transmissions +const uint32_t Offset = 0; //offset frequency for calibration purposes + +const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth +const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor +const uint8_t CodeRate = LORA_CR_4_8; //LoRa coding rate +const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting + +const int8_t TXpower = 20; //LoRa transmit power in dBm + +SX127XLT LT; + +void setup_lora() { + SPI.begin(SCK, MISO, MOSI, NSS); +if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE)) + { + Serial.println(F("LoRa Device found")); + } + else + { + Serial.println(F("No device responding")); + } + + 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(); + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeFloat(0.0); //add latitude + LT.writeFloat(0.0); //add longitude + LT.writeFloat(0.0); //add altitude + LT.writeUint8(0); //add number of satellites + LT.writeUint8(0); //add tracker status + uint8_t len = LT.endWriteSXBuffer(); //close buffer write + + LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); +} + +void sendLocation(int32_t Lat, int32_t Lon) +{ + uint8_t len; + + LT.startWriteSXBuffer(0); //initialise buffer write at address 0 + LT.writeInt32(Lat); //add latitude + LT.writeInt32(Lon); //add longitude + LT.writeInt16(fix.alt.whole); //add altitude + LT.writeInt8(fix.alt.frac); + LT.writeUint8(fix.satellites); //add number of satellites + LT.writeUint8(fix.status); //add tracker status + len = LT.endWriteSXBuffer(); //close buffer write + /* + Serial.print("Sending data: "); + Serial.print(fix.alt.whole); + Serial.print("."); + Serial.println(fix.alt.frac); + */ + LT.transmitSXBuffer(0, len, 10000, TXpower, NO_WAIT); +} + + +void loop_lora_pre() { + if (gps.available( gpsPort) && digitalRead(DIO0)) { + fix = gps.read(); + sendLocation(fix.latitudeL(), fix.longitudeL()); + } +} + +void loop_lora() { + if (digitalRead(DIO0)) { + sendLocation(fix.latitudeL(), fix.longitudeL()); + } +} diff --git a/src/main copy.old b/src/main copy.old new file mode 100644 index 0000000..2e75c9f --- /dev/null +++ b/src/main copy.old @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "esp_wifi.h" + +String maclist[64][3]; +int listcount = 0; + +uint8_t beacon_raw[] = { + 0x80, 0x00, // 0-1: Frame Control + 0x00, 0x00, // 2-3: Duration + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 4-9: Destination address (broadcast) + 0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06, // 10-15: Source address + 0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06, // 16-21: BSSID + 0x00, 0x00, // 22-23: Sequence / fragment number + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 24-31: Timestamp (GETS OVERWRITTEN TO 0 BY HARDWARE) + 0x64, 0x00, // 32-33: Beacon interval + 0x31, 0x04, // 34-35: Capability info + 0x00, 0x00, /* FILL CONTENT HERE */ // 36-38: SSID parameter set, 0x00:length:content + 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, // 39-48: Supported rates + 0x03, 0x01, 0x01, // 49-51: DS Parameter set, current channel 1 (= 0x01), + 0x05, 0x04, 0x01, 0x02, 0x00, 0x00, // 52-57: Traffic Indication Map + +}; + +String KnownMac[10][2] = { // Put devices you want to be reconized + {"Will-Phone","BC2DEF21B423"}, + {"Will-PC","E894Fffffff3"}, + {"NAME","MACADDRESS"}, + {"NAME","MACADDRESS"}, + {"NAME","MACADDRESS"}, + {"NAME","MACADDRESS"}, + {"NAME","MACADDRESS"}, + {"NAME","MACADDRESS"}, + {"NAME","MACADDRESS"} + +}; + +String defaultTTL = "60"; // Maximum time (Apx seconds) elapsed before device is consirded offline + +const wifi_promiscuous_filter_t filt={ //Idk what this does + .filter_mask=WIFI_PROMIS_FILTER_MASK_MGMT|WIFI_PROMIS_FILTER_MASK_DATA +}; + +typedef struct { // or this + uint8_t mac[6]; +} __attribute__((packed)) MacAddr; + +typedef struct { // still dont know much about this + int16_t fctl; + int16_t duration; + MacAddr da; + MacAddr sa; + MacAddr bssid; + int16_t seqctl; + unsigned char payload[]; +} __attribute__((packed)) WifiMgmtHdr; + + + +#define maxCh 13 //max Channel -> US = 11, EU = 13, Japan = 14 + + +int curChannel = 10; + + +void sniffer(void* buf, wifi_promiscuous_pkt_type_t type) { //This is where packets end up after they get sniffed + wifi_promiscuous_pkt_t *p = (wifi_promiscuous_pkt_t*)buf; // Dont know what these 3 lines do + int len = p->rx_ctrl.sig_len; + WifiMgmtHdr *wh = (WifiMgmtHdr*)p->payload; + len -= sizeof(WifiMgmtHdr); + if (len < 0){ + Serial.println("Receuved 0"); + return; + } + String packet; + String mac; + int fctl = ntohs(wh->fctl); + for(int i=8;i<=8+6+1;i++){ // This reads the first couple of bytes of the packet. This is where you can read the whole packet replaceing the "8+6+1" with "p->rx_ctrl.sig_len" + packet += String(p->payload[i],HEX); + } + for(int i=4;i<=15;i++){ // This removes the 'nibble' bits from the stat and end of the data we want. So we only get the mac address. + mac += packet[i]; + } + mac.toUpperCase(); + + + int added = 0; + for(int i=0;i<=63;i++){ // checks if the MAC address has been added before + if(mac == maclist[i][0]){ + maclist[i][1] = defaultTTL; + if(maclist[i][2] == "OFFLINE"){ + maclist[i][2] = "0"; + } + added = 1; + } + } + + if(added == 0){ // If its new. add it to the array. + maclist[listcount][0] = mac; + maclist[listcount][1] = defaultTTL; + //Serial.println(mac); + listcount ++; + if(listcount >= 64){ + Serial.println("Too many addresses"); + listcount = 0; + } + } +} + + + +//===== SETUP =====// +void setup() { + + /* start Serial */ + Serial.begin(9600); + + /* setup wifi */ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_wifi_init(&cfg); + esp_wifi_set_storage(WIFI_STORAGE_RAM); + esp_wifi_set_mode(WIFI_MODE_STA); + esp_wifi_start(); + esp_wifi_set_promiscuous(true); + esp_wifi_set_promiscuous_filter(&filt); + esp_wifi_set_promiscuous_rx_cb(&sniffer); + esp_wifi_set_channel(curChannel, WIFI_SECOND_CHAN_NONE); + + Serial.println("starting!"); +} + +void purge(){ // This maanges the TTL + for(int i=0;i<=63;i++){ + if(!(maclist[i][0] == "")){ + int ttl = (maclist[i][1].toInt()); + ttl --; + if(ttl <= 0){ + Serial.println("OFFLINE: " + maclist[i][0]); + maclist[i][2] = "OFFLINE"; + maclist[i][1] = defaultTTL; + }else{ + maclist[i][1] = String(ttl); + } + } + } +} + +void updatetime(){ // This updates the time the device has been online for + for(int i=0;i<=63;i++){ + if(!(maclist[i][0] == "")){ + if(maclist[i][2] == "")maclist[i][2] = "0"; + if(!(maclist[i][2] == "OFFLINE")){ + int timehere = (maclist[i][2].toInt()); + timehere ++; + maclist[i][2] = String(timehere); + } + + Serial.println(maclist[i][0] + " : " + maclist[i][2]); + + } + } +} + +void showpeople(){ // This checks if the MAC is in the reckonized list and then displays it on the OLED and/or prints it to serial. + String forScreen = ""; + for(int i=0;i<=63;i++){ + String tmp1 = maclist[i][0]; + if(!(tmp1 == "")){ + for(int j=0;j<=9;j++){ + String tmp2 = KnownMac[j][1]; + if(tmp1 == tmp2){ + forScreen += (KnownMac[j][0] + " : " + maclist[i][2] + "\n"); + Serial.print(KnownMac[j][0] + " : " + tmp1 + " : " + maclist[i][2] + "\n -- \n"); + } + } + } + } +} + +//===== LOOP =====// +void loop() { + Serial.println("Changed channel:" + String(curChannel)); + if(curChannel > maxCh){ + curChannel = 1; + } + esp_wifi_set_channel(curChannel, WIFI_SECOND_CHAN_NONE); + delay(1000); + updatetime(); + purge(); + showpeople(); + switch(esp_wifi_80211_tx(ESP_IF_WIFI_STA, packet, sizeof(packet), 0)) + { + case ESP_OK: + printf("Packet in the air!\n"); + break; + case ESP_ERR_WIFI_IF: + printf("Invalid interface\n"); + break; + case ESP_ERR_INVALID_ARG: + printf("Invalid parameter\n"); + break; + default: + printf("Some other error I don't want to control now\n"); + break; + } + //curChannel++; +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..c85af92 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,132 @@ +#define SEALEVELPRESSURE_HPA (1013.25) +#include +#include +#include +#include "sdcard.h" +#include "wifi_setup.h" +#include "bmp388.h" +#include "bmp180.h" +#include "bno055.h" +#include "sht31.h" +#include "gps.h" +#include "lora.h" + +#define PWM 34 + +bool deployed = 0; + +void deploy() { + digitalWrite(PWM, HIGH); + delay(1000); + digitalWrite(PWM, LOW); + delay(1000); +} + +void TaskDeploycode( void * pvParameters ){ + deploy(); + deployed = 1; +} +TaskHandle_t TaskDelpoy; + +float original_height; +bool flight = false; +unsigned long start = 0; +File file; +bool save = false; +float previous_height; +bool altitude = false; + +void setup(){ + Serial.begin(115200); + Wire.setClock(800000); + setup_sdcard(); + setup_bmp(); + //setup_180(); + setup_bno(); + setup_sht(); + setup_gps(); + setup_lora(); + Serial.println(); + Serial.println("Configuring access point..."); + + connectToWiFi(networkName, networkPswd); + ESP_ERROR_CHECK(esp_wifi_set_protocol (WIFI_IF_STA, WIFI_PROTOCOL_11B)); + wifi_country_t country_info = {"JP", 1, 14, WIFI_COUNTRY_POLICY_MANUAL}; + ESP_ERROR_CHECK(esp_wifi_set_country(&country_info)); + ESP_ERROR_CHECK(esp_wifi_set_max_tx_power(80)); + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); + pinMode(PWM, OUTPUT); + + uint8_t buffer[50] = "test.txt"; + while(1) { + if (connected) { + bmp.performReading(); + original_height = bmp.readAltitude(SEALEVELPRESSURE_HPA); + udp.parsePacket(); + if(udp.read(buffer, 50) > 0){ + Serial.print("Server to client: "); + Serial.println((char *)buffer); + start = millis(); + break; + } + } + delay(100); + loop_lora_pre(); + } + file = SD_MMC.open((char *)buffer, FILE_WRITE); + previous_height = original_height; + Serial.println(original_height); +} + +void loop(){ + DynamicJsonDocument doc(1024); + JsonObject obj = doc.to(); + obj["seconds"] = millis()/1000; + obj["deployed"] = deployed; + obj["save"] = save; + obj["flight"] = flight; + obj["altitude"] = altitude; + loop_bmp(obj); + loop_bno(obj); + loop_sht(obj); + loop_gps(obj); + loop_lora(); + serializeJson(doc, file); + file.print('\n'); + file.flush(); + //only send data when connected + if(connected){ + //Send a packet + udp.beginPacket(udpAddress,udpPort); + serializeJson(doc, udp); + udp.println(); + udp.endPacket(); + } + if (!save & !deployed & ((obj["bmp388"]["altitude"].as() - original_height) > 50.0)) { + Serial.println("Deploy is save"); + save = true; + } + if (save & !deployed & (((obj["bmp388"]["altitude"].as() - previous_height) * 5) < 3.0)) { + Serial.println("Start deploy altitude"); + altitude = true; + deployed = true; + digitalWrite(PWM, HIGH); + } + if (!flight & (max(max(abs(obj["bno055"]["linear_accel_data"]["x"].as()), + abs(obj["bno055"]["linear_accel_data"]["y"].as())), + max(abs(obj["bno055"]["linear_accel_data"]["y"].as()), + abs(obj["bno055"]["linear_accel_data"]["z"].as()))) > 5.0)) { + Serial.println("Timer trigger"); + start = millis(); + flight = true; + } + if(flight & ((millis()-start) > 8*1000) & !deployed) { // Вот таймер + Serial.println("Start deploy timeout"); + deployed = 1; + digitalWrite(PWM, HIGH); + //xTaskCreate(TaskDeploycode,"TaskDeploy",10000,NULL,1,&TaskDelpoy); + } + //Wait for 1 second + previous_height = obj["bmp388"]["altitude"].as(); + delay(200); +} diff --git a/src/main.cpp.old b/src/main.cpp.old new file mode 100644 index 0000000..07c7cda --- /dev/null +++ b/src/main.cpp.old @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include + + +#include "freertos/FreeRTOS.h" + +#include "esp_event_loop.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_wifi.h" +#include "esp_vfs_fat.h" + +#include "nvs_flash.h" +#include "string.h" + +uint8_t beacon_raw[] = { + 0x80, 0x00, // 0-1: Frame Control + 0x00, 0x00, // 2-3: Duration + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 4-9: Destination address (broadcast) + 0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06, // 10-15: Source address + 0xba, 0xde, 0xaf, 0xfe, 0x00, 0x06, // 16-21: BSSID + 0x00, 0x00, // 22-23: Sequence / fragment number + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 24-31: Timestamp (GETS OVERWRITTEN TO 0 BY HARDWARE) + 0x64, 0x00, // 32-33: Beacon interval + 0x31, 0x04, // 34-35: Capability info + 0x00, 0x00, /* FILL CONTENT HERE */ // 36-38: SSID parameter set, 0x00:length:content + 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, // 39-48: Supported rates + 0x03, 0x01, 0x01, // 49-51: DS Parameter set, current channel 1 (= 0x01), + 0x05, 0x04, 0x01, 0x02, 0x00, 0x00, // 52-57: Traffic Indication Map + +}; + +char *rick_ssids[] = { + "01 Never gonna give you up", + "02 Never gonna let you down", + "03 Never gonna run around", + "04 and desert you", + "05 Never gonna make you cry", + "06 Never gonna say goodbye", + "07 Never gonna tell a lie", + "08 and hurt you" +}; + +#define BEACON_SSID_OFFSET 38 +#define SRCADDR_OFFSET 10 +#define BSSID_OFFSET 16 +#define SEQNUM_OFFSET 22 +#define TOTAL_LINES (sizeof(rick_ssids) / sizeof(char *)) + +esp_err_t event_handler(void *ctx, system_event_t *event) { + return ESP_OK; +} + +void spam_task(void *pvParameter) { + uint8_t line = 0; + + // Keep track of beacon sequence numbers on a per-songline-basis + uint16_t seqnum[TOTAL_LINES] = { 0 }; + + for (;;) { + vTaskDelay(100 / TOTAL_LINES / portTICK_PERIOD_MS); + + // Insert line of Rick Astley's "Never Gonna Give You Up" into beacon packet + printf("%i %i %s\r\n", strlen(rick_ssids[line]), TOTAL_LINES, rick_ssids[line]); + + uint8_t beacon_rick[200]; + memcpy(beacon_rick, beacon_raw, BEACON_SSID_OFFSET - 1); + beacon_rick[BEACON_SSID_OFFSET - 1] = strlen(rick_ssids[line]); + memcpy(&beacon_rick[BEACON_SSID_OFFSET], rick_ssids[line], strlen(rick_ssids[line])); + memcpy(&beacon_rick[BEACON_SSID_OFFSET + strlen(rick_ssids[line])], &beacon_raw[BEACON_SSID_OFFSET], sizeof(beacon_raw) - BEACON_SSID_OFFSET); + + // Last byte of source address / BSSID will be line number - emulate multiple APs broadcasting one song line each + beacon_rick[SRCADDR_OFFSET + 5] = line; + beacon_rick[BSSID_OFFSET + 5] = line; + + // Update sequence number + beacon_rick[SEQNUM_OFFSET] = (seqnum[line] & 0x0f) << 4; + beacon_rick[SEQNUM_OFFSET + 1] = (seqnum[line] & 0xff0) >> 4; + seqnum[line]++; + if (seqnum[line] > 0xfff) + seqnum[line] = 0; + + esp_wifi_80211_tx(WIFI_IF_AP, beacon_rick, sizeof(beacon_raw) + strlen(rick_ssids[line]), false); + + if (++line >= TOTAL_LINES) + line = 0; + } +} + +const wifi_promiscuous_filter_t filt={ //Idk what this does + .filter_mask=WIFI_PROMIS_FILTER_MASK_MGMT|WIFI_PROMIS_FILTER_MASK_DATA +}; + + + +void setup(void) { + //Serial.begin(9600); + nvs_flash_init(); + tcpip_adapter_init(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + + // Init dummy AP to specify a channel and get WiFi hardware into + // a mode where we can send the actual fake beacon frames. + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + wifi_config_t ap_config = {}; + memcpy(ap_config.ap.ssid, "esp32-beaconspam", sizeof("esp32-beaconspam")); + memcpy(ap_config.ap.password, "dummypassword", sizeof("dummypassword")); + ap_config.ap.ssid_len = 0; + ap_config.ap.channel = 1; + ap_config.ap.authmode = WIFI_AUTH_WPA2_PSK; + ap_config.ap.ssid_hidden = 1; + ap_config.ap.max_connection = 4; + ap_config.ap.beacon_interval = 60000; + ESP_ERROR_CHECK(esp_wifi_set_protocol (WIFI_IF_AP, WIFI_PROTOCOL_11B)); + wifi_country_t country_info = {"JP", 1, 14, WIFI_COUNTRY_POLICY_MANUAL}; + ESP_ERROR_CHECK(esp_wifi_set_country(&country_info)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); + ESP_ERROR_CHECK(esp_wifi_set_max_tx_power(80)); + /* + gpio_set_pull_mode(GPIO_NUM_15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes + gpio_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes + gpio_set_pull_mode(GPIO_NUM_4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only + gpio_set_pull_mode(GPIO_NUM_12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only + gpio_set_pull_mode(GPIO_NUM_13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes + */ + sdmmc_host_t host_config = SDMMC_HOST_DEFAULT(); + host_config.flags = SDMMC_HOST_FLAG_4BIT; + host_config.max_freq_khz = SDMMC_FREQ_PROBING; + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + slot_config.width = 4; + esp_vfs_fat_mount_config_t mount_config = {false, 16, 0}; + sdmmc_card_t* card; + ESP_ERROR_CHECK(esp_vfs_fat_sdmmc_mount("/sd", &host_config, &slot_config, &mount_config, &card)); + + xTaskCreate(&spam_task, "spam_task", 2048, NULL, 5, NULL); +} + +void loop(void) { + delay(1000); +} diff --git a/src/sdcard.h b/src/sdcard.h new file mode 100644 index 0000000..497abcb --- /dev/null +++ b/src/sdcard.h @@ -0,0 +1,242 @@ +#include "FS.h" +#include "SD_MMC.h" + +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ + #ifdef debug + Serial.printf("Listing directory: %s\n", dirname); + #endif + + File root = fs.open(dirname); + if(!root){ + #ifdef debug + Serial.println("Failed to open directory"); + #endif + return; + } + if(!root.isDirectory()){ + #ifdef debug + Serial.println("Not a directory"); + #endif + return; + } + + File file = root.openNextFile(); + while(file){ + if(file.isDirectory()){ + #ifdef debug + Serial.print(" DIR : "); + #endif + Serial.println(file.name()); + if(levels){ + listDir(fs, file.name(), levels -1); + } + } else { + #ifdef debug + Serial.print(" FILE: "); + #endif + Serial.print(file.name()); + #ifdef debug + Serial.print(" SIZE: "); + #endif + Serial.println(file.size()); + } + file = root.openNextFile(); + } +} + +void createDir(fs::FS &fs, const char * path){ + #ifdef debug + Serial.printf("Creating Dir: %s\n", path); + #endif + if(fs.mkdir(path)){ + #ifdef debug + Serial.println("Dir created"); + #endif + } else { + #ifdef debug + Serial.println("mkdir failed"); + #endif + } +} + +void removeDir(fs::FS &fs, const char * path){ + #ifdef debug + Serial.printf("Removing Dir: %s\n", path); + #endif + if(fs.rmdir(path)){ + #ifdef debug + Serial.println("Dir removed"); + #endif + } else { + #ifdef debug + Serial.println("rmdir failed"); + #endif + } +} + +void readFile(fs::FS &fs, const char * path){ + #ifdef debug + Serial.printf("Reading file: %s\n", path); +#endif + File file = fs.open(path); + if(!file){ + #ifdef debug + Serial.println("Failed to open file for reading"); + #endif + return; + } +#ifdef debug + Serial.print("Read from file: "); + #endif + while(file.available()){ + Serial.write(file.read()); + } +} + +void writeFile(fs::FS &fs, const char * path, const char * message){ + #ifdef debug + Serial.printf("Writing file: %s\n", path); +#endif + File file = fs.open(path, FILE_WRITE); + if(!file){ + #ifdef debug + Serial.println("Failed to open file for writing"); + #endif + return; + } + if(file.print(message)){ + #ifdef debug + Serial.println("File written"); + #endif + } else { + #ifdef debug + Serial.println("Write failed"); + #endif + } +} + +void appendFile(fs::FS &fs, const char * path, const char * message){ + Serial.printf("Appending to file: %s\n", path); + + File file = fs.open(path, FILE_APPEND); + if(!file){ + Serial.println("Failed to open file for appending"); + return; + } + if(file.print(message)){ + Serial.println("Message appended"); + } else { + Serial.println("Append failed"); + } +} + +void renameFile(fs::FS &fs, const char * path1, const char * path2){ + Serial.printf("Renaming file %s to %s\n", path1, path2); + if (fs.rename(path1, path2)) { + Serial.println("File renamed"); + } else { + Serial.println("Rename failed"); + } +} + +void deleteFile(fs::FS &fs, const char * path){ + Serial.printf("Deleting file: %s\n", path); + if(fs.remove(path)){ + Serial.println("File deleted"); + } else { + Serial.println("Delete failed"); + } +} + +void testFileIO(fs::FS &fs, const char * path){ + File file = fs.open(path); + static uint8_t buf[512]; + size_t len = 0; + uint32_t start = millis(); + uint32_t end = start; + if(file){ + len = file.size(); + size_t flen = len; + start = millis(); + while(len){ + size_t toRead = len; + if(toRead > 512){ + toRead = 512; + } + file.read(buf, toRead); + len -= toRead; + } + end = millis() - start; + Serial.printf("%u bytes read for %u ms\n", flen, end); + file.close(); + } else { + Serial.println("Failed to open file for reading"); + } + + + file = fs.open(path, FILE_WRITE); + if(!file){ + Serial.println("Failed to open file for writing"); + return; + } + + size_t i; + start = millis(); + for(i=0; i<2048; i++){ + file.write(buf, 512); + } + end = millis() - start; + Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end); + file.close(); +} + +void setup_sdcard() { + if(!SD_MMC.begin("/sdcard", true, false)){ + Serial.println("Card Mount Failed"); + return; + } + uint8_t cardType = SD_MMC.cardType(); + + if(cardType == CARD_NONE){ + Serial.println("No SD_MMC card attached"); + return; + } + + Serial.print("SD_MMC Card Type: "); + if(cardType == CARD_MMC){ + Serial.println("MMC"); + } else if(cardType == CARD_SD){ + Serial.println("SDSC"); + } else if(cardType == CARD_SDHC){ + Serial.println("SDHC"); + } else { + Serial.println("UNKNOWN"); + } + + uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024); + Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize); + /* + listDir(SD_MMC, "/", 0); + createDir(SD_MMC, "/mydir"); + listDir(SD_MMC, "/", 0); + removeDir(SD_MMC, "/mydir"); + listDir(SD_MMC, "/", 2); + writeFile(SD_MMC, "/hello.txt", "Hello "); + appendFile(SD_MMC, "/hello.txt", "World!\n"); + readFile(SD_MMC, "/hello.txt"); + deleteFile(SD_MMC, "/foo.txt"); + renameFile(SD_MMC, "/hello.txt", "/foo.txt"); + readFile(SD_MMC, "/foo.txt"); + */ + /* + xTaskCreate( + Task1code, + "Task1", + 10000, + NULL, + 1, + &Task1); + */ + //Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024)); + //Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024)); +} diff --git a/src/sht31.h b/src/sht31.h new file mode 100644 index 0000000..61129af --- /dev/null +++ b/src/sht31.h @@ -0,0 +1,52 @@ +#include + +Adafruit_SHT31 sht31 = Adafruit_SHT31(); + +void setup_sht() { + if (! sht31.begin(0x44)) { // Set to 0x45 for alternate i2c addr + Serial.println("Couldn't find SHT31"); + } + sht31.heater(1); + Serial.print("Heater Enabled State: "); + if (sht31.isHeaterEnabled()) + Serial.println("ENABLED"); + else + Serial.println("DISABLED"); +} + +void loop_sht(JsonObject &root) { + JsonObject sht = root.createNestedObject("sht31"); + float t = sht31.readTemperature(); + float h = sht31.readHumidity(); + sht["temperature"] = t; + sht["humidity"] = h; + +/* + if (! isnan(t)) { // check if 'is not a number' + Serial.print("Temp *C = "); Serial.print(t); Serial.print("\t\t"); + } else { + Serial.println("Failed to read temperature"); + } + + if (! isnan(h)) { // check if 'is not a number' + Serial.print("Hum. % = "); Serial.println(h); + } else { + Serial.println("Failed to read humidity"); + } + + // Toggle heater enabled state every 30 seconds + // An ~3.0 degC temperature increase can be noted when heater is enabled + /* + if (++loopCnt == 30) { + enableHeater = !enableHeater; + sht31.heater(enableHeater); + Serial.print("Heater Enabled State: "); + if (sht31.isHeaterEnabled()) + Serial.println("ENABLED"); + else + Serial.println("DISABLED"); + + loopCnt = 0; + } + */ +} \ No newline at end of file diff --git a/src/wifi_setup.h b/src/wifi_setup.h new file mode 100644 index 0000000..4a9c1bc --- /dev/null +++ b/src/wifi_setup.h @@ -0,0 +1,47 @@ +#include +#include +#include "esp_wifi.h" + +const char * networkName = "Overlord"; +const char * networkPswd = "justmonika"; + +const char * udpAddress = "192.168.2.255"; +const int udpPort = 3333; + +boolean connected = false; + +WiFiUDP udp; + +//wifi event handler +void WiFiEvent(WiFiEvent_t event){ + switch(event) { + case SYSTEM_EVENT_STA_GOT_IP: + //When connected set + Serial.print("WiFi connected! IP address: "); + Serial.println(WiFi.localIP()); + //initializes the UDP state + //This initializes the transfer buffer + udp.begin(WiFi.localIP(),udpPort); + connected = true; + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + Serial.println("WiFi lost connection"); + connected = false; + break; + default: break; + } +} + +void connectToWiFi(const char * ssid, const char * pwd){ + Serial.println("Connecting to WiFi network: " + String(ssid)); + + // delete old config + WiFi.disconnect(true); + //register event handler + WiFi.onEvent(WiFiEvent); + + //Initiate connection + WiFi.begin(ssid, pwd); + + Serial.println("Waiting for WIFI connection..."); +} \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html