├── Ra01S.cpp ├── library.properties ├── library.json ├── LICENSE ├── RadioLibLicense.txt ├── example ├── Ra01S-Ping │ ├── README.md │ └── Ra01S-Ping.ino ├── Ra01S-Pong │ ├── README.md │ └── Ra01S-Pong.ino ├── Ra01S-RX-Interrupt │ ├── README.md │ └── Ra01S-RX-Interrupt.ino ├── Ra01S-TX-Interrupt │ ├── README.md │ └── Ra01S-TX-Interrupt.ino ├── Ra01S-TX │ └── Ra01S-TX.ino └── Ra01S-RX │ └── Ra01S-RX.ino ├── README.md └── Ra01S.h /Ra01S.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/Arduino-LoRa-Ra01S/HEAD/Ra01S.cpp -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Arduino-Ra01S 2 | version=1.0.0 3 | author=nopnop2002 4 | maintainer=nopnop2002 5 | sentence=Driver for Ai-Thinker Ra-01S/Ra-01SH. 6 | paragraph=Driver for Ai-Thinker Ra-01S/Ra-01SH. These use SX1268/SX1262. 7 | category=Communication 8 | url=https://github.com/nopnop2002/Arduino-Ra01S 9 | architectures=avr,esp8266 10 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Arduino-Ra01S", 3 | "frameworks": "Arduino", 4 | "keywords": "SX1262, SX1268, Ra-01S, RA-01SH", 5 | "description": "Implement a driver for LoRa chipset SX1262/1268, tested with module Ai-Thinker RA-01S/01SH", 6 | "authors": 7 | [ 8 | { 9 | "name": "nopnop2002", 10 | "url": "", 11 | "maintainer": true 12 | }, 13 | ], 14 | "repository": 15 | { 16 | "type": "git", 17 | "url": "https://github.com/nopnop2002/Arduino-Ra01S" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 nopnop2002 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RadioLibLicense.txt: -------------------------------------------------------------------------------- 1 | Most of the hardware drivers (all hardware specific definitions, most sx126x.h and most sx126x.cpp) have been copied from https://github.com/jgromes/RadioLib. 2 | Which is a great project and helped me a lot to get startet with LoRa SX126x Semtech chips! 3 | As most of this hard work was not mine I want to add the Radiolib License here: 4 | 5 | MIT License 6 | 7 | Copyright (c) 2018 Jan Gromeš 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /example/Ra01S-Ping/README.md: -------------------------------------------------------------------------------- 1 | # Ping-Pong Example 2 | Send data from primary to secondary. 3 | In the secondary, the characters are converted and sent back. 4 | 5 | - Arduino is Primary 6 | When using Arduino as a secondary, use Ra01S-Pong. 7 | ``` 8 | +-----------+ +-----------+ +-----------+ +-----------+ 9 | | | | | | | | | 10 | | Primary |===(SPI)==>| SX126x |---(LoRa)-->| SX126x |===(SPI)==>| Secondary | 11 | | Arduino | | | | | | | 12 | | | | | | | | | 13 | | |<==(SPI)===| |<--(LoRa)---| |<==(SPI)===| | 14 | | | | | | | | | 15 | +-----------+ +-----------+ +-----------+ +-----------+ 16 | ``` 17 | 18 | - Arduino is Secondary 19 | When using Arduino as a primary, use Ra01S-Ping. 20 | 21 | ``` 22 | +-----------+ +-----------+ +-----------+ +-----------+ 23 | | | | | | | | | 24 | | Primary |===(SPI)==>| SX126x |---(LoRa)-->| SX126x |===(SPI)==>| Secondary | 25 | | | | | | | | Arduino | 26 | | | | | | | | | 27 | | |<==(SPI)===| |<--(LoRa)---| |<==(SPI)===| | 28 | | | | | | | | | 29 | +-----------+ +-----------+ +-----------+ +-----------+ 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /example/Ra01S-Pong/README.md: -------------------------------------------------------------------------------- 1 | # Ping-Pong Example 2 | Send data from primary to secondary. 3 | In the secondary, the characters are converted and sent back. 4 | 5 | - Arduino is Primary 6 | When using Arduino as a secondary, use Ra01S-Pong. 7 | ``` 8 | +-----------+ +-----------+ +-----------+ +-----------+ 9 | | | | | | | | | 10 | | Primary |===(SPI)==>| SX126x |---(LoRa)-->| SX126x |===(SPI)==>| Secondary | 11 | | Arduino | | | | | | | 12 | | | | | | | | | 13 | | |<==(SPI)===| |<--(LoRa)---| |<==(SPI)===| | 14 | | | | | | | | | 15 | +-----------+ +-----------+ +-----------+ +-----------+ 16 | ``` 17 | 18 | - Arduino is Secondary 19 | When using Arduino as a primary, use Ra01S-Ping. 20 | 21 | ``` 22 | +-----------+ +-----------+ +-----------+ +-----------+ 23 | | | | | | | | | 24 | | Primary |===(SPI)==>| SX126x |---(LoRa)-->| SX126x |===(SPI)==>| Secondary | 25 | | | | | | | | Arduino | 26 | | | | | | | | | 27 | | |<==(SPI)===| |<--(LoRa)---| |<==(SPI)===| | 28 | | | | | | | | | 29 | +-----------+ +-----------+ +-----------+ +-----------+ 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /example/Ra01S-RX-Interrupt/README.md: -------------------------------------------------------------------------------- 1 | # Interrupt Example 2 | The SX126x supports the following interrupts. 3 | This example demonstrates how to use RxDone. 4 | __Bit 3 cannot be used with LoRa.__ 5 | 6 | |Bit|IRQ|Description|Modulation| 7 | |:-:|:-:|:-:|:-:| 8 | |0|TxDone|Packet transmission completed|All| 9 | |1|RxDone|Packet received|All| 10 | |2|PreambleDetected|Preamble detected|All| 11 | |3|SyncWordValid|Valid sync word detected|FSK| 12 | |4|HeaderValid|Valid LoRa header received|LoRa| 13 | |5|HeaderErr|LoRa header CRC error|LoRa| 14 | |6|CrcErr|Wrong CRC received|All| 15 | |7|CadDone|Channel activity detection finished|LoRa| 16 | |8|CadDetected|Channel activity detected|LoRa| 17 | |9|Timeout|Rx or Tx timeout|All| 18 | 19 | # Wiring 20 | Add a wire to DIO1. 21 | |Ra-01S/SH||UNO|MEGA|ESP8266| 22 | |:-:|:-:|:-:|:-:|:-:| 23 | |VCC|--|3.3V(*1)|3.3V|3.3V| 24 | |GND|--|GND|GND|GND| 25 | |SCK|--|D13(*2)|D52(*2)|IO14| 26 | |MISO|--|D12|D50|IO12| 27 | |MOSI|--|D11(*2)|D51(*2)|IO13| 28 | |NSS|--|D5(*2)|D5(*2)|IO2| 29 | |RST|--|D6(*2)|D6(*2)|IO0| 30 | |BUSY|--|D7(*2)|D7(*2)|IO16| 31 | |DIO1|--|D3(*2)|D3(*2)|IO3| 32 | |TXEN|--|N/C|N/C|N/C| 33 | |RXEN|--|N/C|N/C|N/C| 34 | 35 | (*1) 36 | UNO's 3.3V output can only supply 50mA. 37 | In addition, the output current capacity of UNO-compatible devices is smaller than that of official products. 38 | __So this module may not work normally when supplied from the on-board 3v3.__ 39 | 40 | (*2) 41 | SX126x is not 5V tolerant. 42 | You need level shift from 5V to 3.3V. 43 | I used [this](https://www.ti.com/lit/ds/symlink/txs0108e.pdf?ts=1647593549503) for a level shift. 44 | 45 | # How to use interrupt 46 | irqMask sets the interrupt bits you need. You can set multiple bits. 47 | dioXMask sets the interrupt bits to notify DIOX. You can set multiple bits. 48 | The following setting enables all interrupts: 49 | When SX126X_IRQ_TX_DONE occurs, DIO1 turns ON. 50 | When SX126X_IRQ_RX_DONE occurs, DIO2 turns ON. 51 | When SX126X_IRQ_TIMEOUT occurs, DIO3 turns ON. 52 | ``` 53 | uint16_t irqMask = SX126X_IRQ_ALL; 54 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE; 55 | uint16_t dio2Mask = SX126X_IRQ_RX_DONE;; 56 | uint16_t dio3Mask = SX126X_IRQ_TIMEOUT; 57 | SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 58 | ``` 59 | 60 | This will give the same result as above. 61 | ``` 62 | uint16_t irqMask = SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT; 63 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE; 64 | uint16_t dio2Mask = SX126X_IRQ_RX_DONE; 65 | uint16_t dio3Mask = SX126X_IRQ_TIMEOUT; 66 | SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 67 | ``` 68 | 69 | The following setting enables TxDone/RxDone/Timeout interrupts and triggers them all to DIO1. 70 | ``` 71 | uint16_t irqMask = SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT; 72 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT; 73 | uint16_t dio2Mask = SX126X_IRQ_NONE; 74 | uint16_t dio3Mask = SX126X_IRQ_NONE; 75 | SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /example/Ra01S-TX-Interrupt/README.md: -------------------------------------------------------------------------------- 1 | # Interrupt Example 2 | The SX126x supports the following interrupts. 3 | This example demonstrates how to use TxDone. 4 | __Bit 3 cannot be used with LoRa.__ 5 | 6 | |Bit|IRQ|Description|Modulation| 7 | |:-:|:-:|:-:|:-:| 8 | |0|TxDone|Packet transmission completed|All| 9 | |1|RxDone|Packet received|All| 10 | |2|PreambleDetected|Preamble detected|All| 11 | |3|SyncWordValid|Valid sync word detected|FSK| 12 | |4|HeaderValid|Valid LoRa header received|LoRa| 13 | |5|HeaderErr|LoRa header CRC error|LoRa| 14 | |6|CrcErr|Wrong CRC received|All| 15 | |7|CadDone|Channel activity detection finished|LoRa| 16 | |8|CadDetected|Channel activity detected|LoRa| 17 | |9|Timeout|Rx or Tx timeout|All| 18 | 19 | # Wiring 20 | Add a wire to DIO1. 21 | |Ra-01S/SH||UNO|MEGA|ESP8266| 22 | |:-:|:-:|:-:|:-:|:-:| 23 | |VCC|--|3.3V(*1)|3.3V|3.3V| 24 | |GND|--|GND|GND|GND| 25 | |SCK|--|D13(*2)|D52(*2)|IO14| 26 | |MISO|--|D12|D50|IO12| 27 | |MOSI|--|D11(*2)|D51(*2)|IO13| 28 | |NSS|--|D5(*2)|D5(*2)|IO2| 29 | |RST|--|D6(*2)|D6(*2)|IO0| 30 | |BUSY|--|D7(*2)|D7(*2)|IO16| 31 | |DIO1|--|D3(*2)|D3(*2)|IO3| 32 | |TXEN|--|N/C|N/C|N/C| 33 | |RXEN|--|N/C|N/C|N/C| 34 | 35 | (*1) 36 | UNO's 3.3V output can only supply 50mA. 37 | In addition, the output current capacity of UNO-compatible devices is smaller than that of official products. 38 | __So this module may not work normally when supplied from the on-board 3v3.__ 39 | 40 | (*2) 41 | SX126x is not 5V tolerant. 42 | You need level shift from 5V to 3.3V. 43 | I used [this](https://www.ti.com/lit/ds/symlink/txs0108e.pdf?ts=1647593549503) for a level shift. 44 | 45 | # How to use interrupt 46 | irqMask sets the interrupt bits you need. You can set multiple bits. 47 | dioXMask sets the interrupt bits to notify DIOX. You can set multiple bits. 48 | The following setting enables all interrupts: 49 | When SX126X_IRQ_TX_DONE occurs, DIO1 turns ON. 50 | When SX126X_IRQ_RX_DONE occurs, DIO2 turns ON. 51 | When SX126X_IRQ_TIMEOUT occurs, DIO3 turns ON. 52 | ``` 53 | uint16_t irqMask = SX126X_IRQ_ALL; 54 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE; 55 | uint16_t dio2Mask = SX126X_IRQ_RX_DONE;; 56 | uint16_t dio3Mask = SX126X_IRQ_TIMEOUT; 57 | SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 58 | ``` 59 | 60 | This will give the same result as above. 61 | ``` 62 | uint16_t irqMask = SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT; 63 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE; 64 | uint16_t dio2Mask = SX126X_IRQ_RX_DONE; 65 | uint16_t dio3Mask = SX126X_IRQ_TIMEOUT; 66 | SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 67 | ``` 68 | 69 | The following setting enables TxDone/RxDone/Timeout interrupts and triggers them all to DIO1. 70 | ``` 71 | uint16_t irqMask = SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT; 72 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE | SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT; 73 | uint16_t dio2Mask = SX126X_IRQ_NONE; 74 | uint16_t dio3Mask = SX126X_IRQ_NONE; 75 | SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /example/Ra01S-TX-Interrupt/Ra01S-TX-Interrupt.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define INTERRUPT_GPIO 3 // Digital pin 3 for external interrupt 0 5 | 6 | //#define RF_FREQUENCY 433000000 // Hz center frequency 7 | //#define RF_FREQUENCY 866000000 // Hz center frequency 8 | #define RF_FREQUENCY 915000000 // Hz center frequency 9 | #define TX_OUTPUT_POWER 22 // dBm tx output power 10 | #define LORA_BANDWIDTH 4 // bandwidth 11 | // 2: 31.25Khz 12 | // 3: 62.5Khz 13 | // 4: 125Khz 14 | // 5: 250KHZ 15 | // 6: 500Khz 16 | #define LORA_SPREADING_FACTOR 7 // spreading factor [SF5..SF12] 17 | #define LORA_CODINGRATE 1 // [1: 4/5, 18 | // 2: 4/6, 19 | // 3: 4/7, 20 | // 4: 4/8] 21 | 22 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 23 | #define LORA_PAYLOADLENGTH 0 // 0: Variable length packet (explicit header) 24 | // 1..255 Fixed length packet (implicit header) 25 | #if 1 26 | /* 27 | * for ATmega328/2560 28 | * VCC 3V3/3V3 29 | * GND GND/GND 30 | * SCK 13/52 31 | * MISO 12/50 32 | * MOSI 11/51 33 | * NSS 5/5 34 | * RST 6/6 35 | * BUSY 7/7 36 | * DIO1 3/3 37 | */ 38 | 39 | SX126x lora(5, //Port-Pin Output: SPI select 40 | 6, //Port-Pin Output: Reset 41 | 7 //Port-Pin Input: Busy 42 | ); 43 | #endif // ATmega328/2560 44 | 45 | #if 0 46 | /* 47 | * for ESP8266 48 | * VCC 3V3 49 | * GND GND 50 | * SCK GPIO14 51 | * MISO GPIO12 52 | * MOSI GPIO13 53 | * NSS GPIO2 54 | * RST GPIO0 55 | * BUSY GPIO16 56 | * DIO1 GPIO3 57 | */ 58 | 59 | SX126x lora(2, //Port-Pin Output: SPI select 60 | 0, //Port-Pin Output: Reset 61 | 16 //Port-Pin Input: Busy 62 | ); 63 | #endif // ESP8266 64 | 65 | void gpio_isr() { 66 | Serial.println("Interrupt"); 67 | } 68 | 69 | void setup() 70 | { 71 | delay(1000); 72 | Serial.begin(115200); 73 | 74 | // Initialize the interrupt pin as an input with internal pull-up resistor 75 | pinMode(INTERRUPT_GPIO, INPUT_PULLUP); 76 | // Attach the interrupt to the specified pin 77 | attachInterrupt(digitalPinToInterrupt(INTERRUPT_GPIO), gpio_isr, RISING); 78 | 79 | //lora.DebugPrint(true); 80 | 81 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 82 | TX_OUTPUT_POWER); //tx power in dBm 83 | if (ret != ERR_NONE) while(1) {delay(1);} 84 | 85 | lora.LoRaConfig(LORA_SPREADING_FACTOR, 86 | LORA_BANDWIDTH, 87 | LORA_CODINGRATE, 88 | LORA_PREAMBLE_LENGTH, 89 | LORA_PAYLOADLENGTH, 90 | true, //crcOn 91 | false); //invertIrq 92 | 93 | // Set up an interrupt for SPI transactions 94 | uint16_t irqMask = SX126X_IRQ_TX_DONE; 95 | uint16_t dio1Mask = SX126X_IRQ_TX_DONE; 96 | uint16_t dio2Mask = 0; 97 | uint16_t dio3Mask = 0; 98 | lora.SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 99 | } 100 | 101 | void loop() 102 | { 103 | uint8_t txData[255]; 104 | sprintf((char *)txData, "Hello World %lu", millis()); 105 | uint8_t len = strlen((char *)txData); 106 | 107 | // Wait for transmission to complete 108 | if (lora.Send(txData, len, SX126x_TXMODE_SYNC)) { 109 | //Serial.println("Send success"); 110 | } else { 111 | Serial.println("Send fail"); 112 | } 113 | 114 | // Do not wait for the transmission to be completed 115 | //lora.Send(txData, len, SX126x_TXMODE_ASYNC ); 116 | 117 | delay(1000); 118 | } 119 | -------------------------------------------------------------------------------- /example/Ra01S-RX-Interrupt/Ra01S-RX-Interrupt.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define INTERRUPT_GPIO 3 // Digital pin 3 for external interrupt 0 5 | 6 | //#define RF_FREQUENCY 433000000 // Hz center frequency 7 | //#define RF_FREQUENCY 866000000 // Hz center frequency 8 | #define RF_FREQUENCY 915000000 // Hz center frequency 9 | #define TX_OUTPUT_POWER 22 // dBm tx output power 10 | #define LORA_BANDWIDTH 4 // bandwidth 11 | // 2: 31.25Khz 12 | // 3: 62.5Khz 13 | // 4: 125Khz 14 | // 5: 250KHZ 15 | // 6: 500Khz 16 | #define LORA_SPREADING_FACTOR 7 // spreading factor [SF5..SF12] 17 | #define LORA_CODINGRATE 1 // [1: 4/5, 18 | // 2: 4/6, 19 | // 3: 4/7, 20 | // 4: 4/8] 21 | 22 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 23 | #define LORA_PAYLOADLENGTH 0 // 0: Variable length packet (explicit header) 24 | // 1..255 Fixed length packet (implicit header) 25 | 26 | 27 | 28 | #if 1 29 | /* 30 | * for ATmega328/2560 31 | * VCC 3V3/3V3 32 | * GND GND/GND 33 | * SCK 13/52 34 | * MISO 12/50 35 | * MOSI 11/51 36 | * NSS 5/5 37 | * RST 6/6 38 | * BUSY 7/7 39 | * DIO1 3/3 40 | */ 41 | 42 | SX126x lora(5, //Port-Pin Output: SPI select 43 | 6, //Port-Pin Output: Reset 44 | 7 //Port-Pin Input: Busy 45 | ); 46 | #endif // ATmega328/2560 47 | 48 | #if 0 49 | /* 50 | * for ESP8266 51 | * VCC 3V3 52 | * GND GND 53 | * SCK GPIO14 54 | * MISO GPIO12 55 | * MOSI GPIO13 56 | * NSS GPIO2 57 | * RST GPIO0 58 | * BUSY GPIO16 59 | * DIO1 GPIO3 60 | */ 61 | 62 | SX126x lora(2, //Port-Pin Output: SPI select 63 | 0, //Port-Pin Output: Reset 64 | 16 //Port-Pin Input: Busy 65 | ); 66 | #endif // ESP8266 67 | 68 | void gpio_isr() { 69 | Serial.println("Interrupt"); 70 | } 71 | 72 | void setup() 73 | { 74 | delay(1000); 75 | Serial.begin(115200); 76 | 77 | // Initialize the interrupt pin as an input with internal pull-up resistor 78 | pinMode(INTERRUPT_GPIO, INPUT_PULLUP); 79 | // Attach the interrupt to the specified pin 80 | attachInterrupt(digitalPinToInterrupt(INTERRUPT_GPIO), gpio_isr, RISING); 81 | 82 | //lora.DebugPrint(true); 83 | 84 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 85 | TX_OUTPUT_POWER); //tx power in dBm 86 | if (ret != ERR_NONE) while(1) {delay(1);} 87 | 88 | lora.LoRaConfig(LORA_SPREADING_FACTOR, 89 | LORA_BANDWIDTH, 90 | LORA_CODINGRATE, 91 | LORA_PREAMBLE_LENGTH, 92 | LORA_PAYLOADLENGTH, 93 | true, //crcOn 94 | false); //invertIrq 95 | 96 | // Set up an interrupt for SPI transactions 97 | uint16_t irqMask = SX126X_IRQ_RX_DONE; 98 | uint16_t dio1Mask = SX126X_IRQ_RX_DONE; 99 | uint16_t dio2Mask = 0; 100 | uint16_t dio3Mask = 0; 101 | lora.SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask); 102 | } 103 | 104 | void loop() 105 | { 106 | uint8_t rxData[255]; 107 | uint8_t rxLen = lora.Receive(rxData, 255); 108 | if ( rxLen > 0 ) 109 | { 110 | Serial.print("Receive rxLen:"); 111 | Serial.println(rxLen); 112 | for(int i=0;i< rxLen;i++) { 113 | Serial.print(rxData[i], HEX); 114 | Serial.print(" "); 115 | } 116 | Serial.println(); 117 | for(int i=0;i< rxLen;i++) { 118 | if (rxData[i] > 0x19 && rxData[i] < 0x7F) { 119 | char myChar = rxData[i]; 120 | Serial.print(myChar); 121 | } else { 122 | Serial.print("?"); 123 | } 124 | } 125 | Serial.println(); 126 | 127 | int8_t rssi, snr; 128 | lora.GetPacketStatus(&rssi, &snr); 129 | Serial.print("rssi: "); 130 | Serial.print(rssi, DEC); 131 | Serial.println(" dBm"); 132 | Serial.print("snr: "); 133 | Serial.print(snr, DEC); 134 | Serial.println(" dB"); 135 | } 136 | delay(1); 137 | } 138 | -------------------------------------------------------------------------------- /example/Ra01S-TX/Ra01S-TX.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | //#define RF_FREQUENCY 433000000 // Hz center frequency 5 | //#define RF_FREQUENCY 866000000 // Hz center frequency 6 | #define RF_FREQUENCY 915000000 // Hz center frequency 7 | #define TX_OUTPUT_POWER 22 // dBm tx output power 8 | #define LORA_BANDWIDTH 4 // bandwidth 9 | // 2: 31.25Khz 10 | // 3: 62.5Khz 11 | // 4: 125Khz 12 | // 5: 250KHZ 13 | // 6: 500Khz 14 | #define LORA_SPREADING_FACTOR 7 // spreading factor [SF5..SF12] 15 | #define LORA_CODINGRATE 1 // [1: 4/5, 16 | // 2: 4/6, 17 | // 3: 4/7, 18 | // 4: 4/8] 19 | 20 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 21 | #define LORA_PAYLOADLENGTH 0 // 0: Variable length packet (explicit header) 22 | // 1..255 Fixed length packet (implicit header) 23 | 24 | //#define USE_EBYTE 25 | 26 | #if 1 27 | /* 28 | * for ATmega328/2560 29 | * VCC 3V3/3V3 30 | * GND GND/GND 31 | * SCK 13/52 32 | * MISO 12/50 33 | * MOSI 11/51 34 | * NSS 5/5 35 | * RST 6/6 36 | * BUSY 7/7 37 | * TXEN 8/8 for EBYTE 38 | * RXEN 9/9 for EBYTE 39 | */ 40 | 41 | #ifdef USE_EBYTE 42 | SX126x lora(5, //Port-Pin Output: SPI select 43 | 6, //Port-Pin Output: Reset 44 | 7, //Port-Pin Input: Busy 45 | 8, //Port-Pin Output: TXEN 46 | 9 //Port-Pin Output: RXEN 47 | ); 48 | 49 | #else 50 | SX126x lora(5, //Port-Pin Output: SPI select 51 | 6, //Port-Pin Output: Reset 52 | 7 //Port-Pin Input: Busy 53 | ); 54 | #endif // USE_EBYTE 55 | 56 | #endif // ATmega328/2560 57 | 58 | #if 0 59 | /* 60 | * for ESP8266 61 | * VCC 3V3 62 | * GND GND 63 | * SCK GPIO14 64 | * MISO GPIO12 65 | * MOSI GPIO13 66 | * NSS GPIO2 67 | * RST GPIO0 68 | * BUSY GPIO16 69 | * TXEN GPIO4 for EBYTE 70 | * RXEN GPIO5 for EBYTE 71 | */ 72 | 73 | #ifdef USE_EBYTE 74 | SX126x lora(2, //Port-Pin Output: SPI select 75 | 0, //Port-Pin Output: Reset 76 | 16, //Port-Pin Input: Busy 77 | 4, //Port-Pin Output: TXEN 78 | 5 //Port-Pin Output: RXEN 79 | ); 80 | #else 81 | SX126x lora(2, //Port-Pin Output: SPI select 82 | 0, //Port-Pin Output: Reset 83 | 16 //Port-Pin Input: Busy 84 | ); 85 | #endif // USE_EBYTE 86 | 87 | #endif // ESP8266 88 | 89 | void setup() 90 | { 91 | delay(1000); 92 | Serial.begin(115200); 93 | 94 | //lora.DebugPrint(true); 95 | 96 | #ifdef USE_EBYTE 97 | Serial.println("Enable TCXO"); 98 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 99 | TX_OUTPUT_POWER, //tx power in dBm 100 | 3.3, //use TCXO 101 | true); //use TCXO 102 | if (ret != ERR_NONE) while(1) {delay(1);} 103 | #else 104 | Serial.println("Disable TCXO"); 105 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 106 | TX_OUTPUT_POWER); //tx power in dBm 107 | if (ret != ERR_NONE) while(1) {delay(1);} 108 | #endif // USE_EBYTE 109 | 110 | lora.LoRaConfig(LORA_SPREADING_FACTOR, 111 | LORA_BANDWIDTH, 112 | LORA_CODINGRATE, 113 | LORA_PREAMBLE_LENGTH, 114 | LORA_PAYLOADLENGTH, 115 | true, //crcOn 116 | false); //invertIrq 117 | 118 | } 119 | 120 | void loop() 121 | { 122 | uint8_t txData[255]; 123 | sprintf((char *)txData, "Hello World %lu", millis()); 124 | uint8_t len = strlen((char *)txData); 125 | 126 | // Wait for transmission to complete 127 | if (lora.Send(txData, len, SX126x_TXMODE_SYNC)) { 128 | //Serial.println("Send success"); 129 | } else { 130 | Serial.println("Send fail"); 131 | } 132 | 133 | // Do not wait for the transmission to be completed 134 | //lora.Send(txData, len, SX126x_TXMODE_ASYNC ); 135 | 136 | delay(1000); 137 | } 138 | -------------------------------------------------------------------------------- /example/Ra01S-RX/Ra01S-RX.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | //#define RF_FREQUENCY 433000000 // Hz center frequency 5 | //#define RF_FREQUENCY 866000000 // Hz center frequency 6 | #define RF_FREQUENCY 915000000 // Hz center frequency 7 | #define TX_OUTPUT_POWER 22 // dBm tx output power 8 | #define LORA_BANDWIDTH 4 // bandwidth 9 | // 2: 31.25Khz 10 | // 3: 62.5Khz 11 | // 4: 125Khz 12 | // 5: 250KHZ 13 | // 6: 500Khz 14 | #define LORA_SPREADING_FACTOR 7 // spreading factor [SF5..SF12] 15 | #define LORA_CODINGRATE 1 // [1: 4/5, 16 | // 2: 4/6, 17 | // 3: 4/7, 18 | // 4: 4/8] 19 | 20 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 21 | #define LORA_PAYLOADLENGTH 0 // 0: Variable length packet (explicit header) 22 | // 1..255 Fixed length packet (implicit header) 23 | 24 | //#define USE_EBYTE 25 | 26 | #if 1 27 | /* 28 | * for ATmega328/2560 29 | * VCC 3V3/3V3 30 | * GND GND/GND 31 | * SCK 13/52 32 | * MISO 12/50 33 | * MOSI 11/51 34 | * NSS 5/5 35 | * RST 6/6 36 | * BUSY 7/7 37 | * TXEN 8/8 for EBYTE 38 | * RXEN 9/9 for EBYTE 39 | */ 40 | 41 | #ifdef USE_EBYTE 42 | SX126x lora(5, //Port-Pin Output: SPI select 43 | 6, //Port-Pin Output: Reset 44 | 7, //Port-Pin Input: Busy 45 | 8, //Port-Pin Output: TXEN 46 | 9 //Port-Pin Output: RXEN 47 | ); 48 | 49 | #else 50 | SX126x lora(5, //Port-Pin Output: SPI select 51 | 6, //Port-Pin Output: Reset 52 | 7 //Port-Pin Input: Busy 53 | ); 54 | #endif // USE_EBYTE 55 | 56 | #endif // ATmega328/2560 57 | 58 | #if 0 59 | /* 60 | * for ESP8266 61 | * VCC 3V3 62 | * GND GND 63 | * SCK GPIO14 64 | * MISO GPIO12 65 | * MOSI GPIO13 66 | * NSS GPIO2 67 | * RST GPIO0 68 | * BUSY GPIO16 69 | * TXEN GPIO4 for EBYTE 70 | * RXEN GPIO5 for EBYTE 71 | */ 72 | 73 | #ifdef USE_EBYTE 74 | SX126x lora(2, //Port-Pin Output: SPI select 75 | 0, //Port-Pin Output: Reset 76 | 16, //Port-Pin Input: Busy 77 | 4, //Port-Pin Output: TXEN 78 | 5 //Port-Pin Output: RXEN 79 | ); 80 | #else 81 | SX126x lora(2, //Port-Pin Output: SPI select 82 | 0, //Port-Pin Output: Reset 83 | 16 //Port-Pin Input: Busy 84 | ); 85 | #endif // USE_EBYTE 86 | 87 | #endif // ESP8266 88 | 89 | void setup() 90 | { 91 | delay(1000); 92 | Serial.begin(115200); 93 | 94 | //lora.DebugPrint(true); 95 | 96 | #ifdef USE_EBYTE 97 | Serial.println("Enable TCXO"); 98 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 99 | TX_OUTPUT_POWER, //tx power in dBm 100 | 3.3, //use TCXO 101 | true); //use TCXO 102 | if (ret != ERR_NONE) while(1) {delay(1);} 103 | #else 104 | Serial.println("Disable TCXO"); 105 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 106 | TX_OUTPUT_POWER); //tx power in dBm 107 | if (ret != ERR_NONE) while(1) {delay(1);} 108 | #endif // USE_EBYTE 109 | 110 | lora.LoRaConfig(LORA_SPREADING_FACTOR, 111 | LORA_BANDWIDTH, 112 | LORA_CODINGRATE, 113 | LORA_PREAMBLE_LENGTH, 114 | LORA_PAYLOADLENGTH, 115 | true, //crcOn 116 | false); //invertIrq 117 | 118 | } 119 | 120 | void loop() 121 | { 122 | uint8_t rxData[255]; 123 | uint8_t rxLen = lora.Receive(rxData, 255); 124 | if ( rxLen > 0 ) 125 | { 126 | Serial.print("Receive rxLen:"); 127 | Serial.println(rxLen); 128 | for(int i=0;i< rxLen;i++) { 129 | Serial.print(rxData[i], HEX); 130 | Serial.print(" "); 131 | } 132 | Serial.println(); 133 | for(int i=0;i< rxLen;i++) { 134 | if (rxData[i] > 0x19 && rxData[i] < 0x7F) { 135 | char myChar = rxData[i]; 136 | Serial.print(myChar); 137 | } else { 138 | Serial.print("?"); 139 | } 140 | } 141 | Serial.println(); 142 | 143 | int8_t rssi, snr; 144 | lora.GetPacketStatus(&rssi, &snr); 145 | Serial.print("rssi: "); 146 | Serial.print(rssi, DEC); 147 | Serial.println(" dBm"); 148 | Serial.print("snr: "); 149 | Serial.print(snr, DEC); 150 | Serial.println(" dB"); 151 | } 152 | delay(1); 153 | } 154 | -------------------------------------------------------------------------------- /example/Ra01S-Pong/Ra01S-Pong.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | //#define RF_FREQUENCY 433000000 // Hz center frequency 5 | //#define RF_FREQUENCY 866000000 // Hz center frequency 6 | #define RF_FREQUENCY 915000000 // Hz center frequency 7 | #define TX_OUTPUT_POWER 22 // dBm tx output power 8 | #define LORA_BANDWIDTH 4 // bandwidth 9 | // 2: 31.25Khz 10 | // 3: 62.5Khz 11 | // 4: 125Khz 12 | // 5: 250KHZ 13 | // 6: 500Khz 14 | #define LORA_SPREADING_FACTOR 7 // spreading factor [SF5..SF12] 15 | #define LORA_CODINGRATE 1 // [1: 4/5, 16 | // 2: 4/6, 17 | // 3: 4/7, 18 | // 4: 4/8] 19 | 20 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 21 | #define LORA_PAYLOADLENGTH 0 // 0: Variable length packet (explicit header) 22 | // 1..255 Fixed length packet (implicit header) 23 | 24 | //#define USE_EBYTE 25 | 26 | #if 1 27 | /* 28 | * for ATmega328/2560 29 | * VCC 3V3/3V3 30 | * GND GND/GND 31 | * SCK 13/52 32 | * MISO 12/50 33 | * MOSI 11/51 34 | * NSS 5/5 35 | * RST 6/6 36 | * BUSY 7/7 37 | * TXEN 8/8 for EBYTE 38 | * RXEN 9/9 for EBYTE 39 | */ 40 | 41 | #ifdef USE_EBYTE 42 | SX126x lora(5, //Port-Pin Output: SPI select 43 | 6, //Port-Pin Output: Reset 44 | 7, //Port-Pin Input: Busy 45 | 8, //Port-Pin Output: TXEN 46 | 9 //Port-Pin Output: RXEN 47 | ); 48 | 49 | #else 50 | SX126x lora(5, //Port-Pin Output: SPI select 51 | 6, //Port-Pin Output: Reset 52 | 7 //Port-Pin Input: Busy 53 | ); 54 | #endif // USE_EBYTE 55 | 56 | #endif // ATmega328/2560 57 | 58 | #if 0 59 | /* 60 | * for ESP8266 61 | * VCC 3V3 62 | * GND GND 63 | * SCK GPIO14 64 | * MISO GPIO12 65 | * MOSI GPIO13 66 | * NSS GPIO2 67 | * RST GPIO0 68 | * BUSY GPIO16 69 | * TXEN GPIO4 for EBYTE 70 | * RXEN GPIO5 for EBYTE 71 | */ 72 | 73 | #ifdef USE_EBYTE 74 | SX126x lora(2, //Port-Pin Output: SPI select 75 | 0, //Port-Pin Output: Reset 76 | 16, //Port-Pin Input: Busy 77 | 4, //Port-Pin Output: TXEN 78 | 5 //Port-Pin Output: RXEN 79 | ); 80 | #else 81 | SX126x lora(2, //Port-Pin Output: SPI select 82 | 0, //Port-Pin Output: Reset 83 | 16 //Port-Pin Input: Busy 84 | ); 85 | #endif // USE_EBYTE 86 | 87 | #endif // ESP8266 88 | 89 | void setup() 90 | { 91 | delay(1000); 92 | Serial.begin(115200); 93 | 94 | //lora.DebugPrint(true); 95 | 96 | #ifdef USE_EBYTE 97 | Serial.println("Enable TCXO"); 98 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 99 | TX_OUTPUT_POWER, //tx power in dBm 100 | 3.3, //use TCXO 101 | true); //use TCXO 102 | if (ret != ERR_NONE) while(1) {delay(1);} 103 | #else 104 | Serial.println("Disable TCXO"); 105 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 106 | TX_OUTPUT_POWER); //tx power in dBm 107 | if (ret != ERR_NONE) while(1) {delay(1);} 108 | #endif // USE_EBYTE 109 | 110 | lora.LoRaConfig(LORA_SPREADING_FACTOR, 111 | LORA_BANDWIDTH, 112 | LORA_CODINGRATE, 113 | LORA_PREAMBLE_LENGTH, 114 | LORA_PAYLOADLENGTH, 115 | true, //crcOn 116 | false); //invertIrq 117 | 118 | } 119 | 120 | void loop() 121 | { 122 | uint8_t txData[255]; 123 | uint8_t rxData[255]; 124 | uint8_t rxLen = lora.Receive(rxData, 255); 125 | if ( rxLen > 0 ) 126 | { 127 | Serial.print("Receive rxLen:"); 128 | Serial.println(rxLen); 129 | for(int i=0;i< rxLen;i++) { 130 | Serial.print(rxData[i], HEX); 131 | Serial.print(" "); 132 | } 133 | Serial.println(); 134 | for(int i=0;i< rxLen;i++) { 135 | if (rxData[i] > 0x19 && rxData[i] < 0x7F) { 136 | char myChar = rxData[i]; 137 | Serial.print(myChar); 138 | } else { 139 | Serial.print("?"); 140 | } 141 | } 142 | Serial.println(); 143 | 144 | int8_t rssi, snr; 145 | lora.GetPacketStatus(&rssi, &snr); 146 | Serial.print("rssi: "); 147 | Serial.print(rssi, DEC); 148 | Serial.println(" dBm"); 149 | Serial.print("snr: "); 150 | Serial.print(snr, DEC); 151 | Serial.println(" dB"); 152 | 153 | for(int i=0;i 3 | 4 | //#define RF_FREQUENCY 433000000 // Hz center frequency 5 | //#define RF_FREQUENCY 866000000 // Hz center frequency 6 | #define RF_FREQUENCY 915000000 // Hz center frequency 7 | #define TX_OUTPUT_POWER 22 // dBm tx output power 8 | #define LORA_BANDWIDTH 4 // bandwidth 9 | // 2: 31.25Khz 10 | // 3: 62.5Khz 11 | // 4: 125Khz 12 | // 5: 250KHZ 13 | // 6: 500Khz 14 | #define LORA_SPREADING_FACTOR 7 // spreading factor [SF5..SF12] 15 | #define LORA_CODINGRATE 1 // [1: 4/5, 16 | // 2: 4/6, 17 | // 3: 4/7, 18 | // 4: 4/8] 19 | 20 | #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 21 | #define LORA_PAYLOADLENGTH 0 // 0: Variable length packet (explicit header) 22 | // 1..255 Fixed length packet (implicit header) 23 | 24 | //#define USE_EBYTE 25 | 26 | #if 1 27 | /* 28 | * for ATmega328/2560 29 | * VCC 3V3/3V3 30 | * GND GND/GND 31 | * SCK 13/52 32 | * MISO 12/50 33 | * MOSI 11/51 34 | * NSS 5/5 35 | * RST 6/6 36 | * BUSY 7/7 37 | * TXEN 8/8 for EBYTE 38 | * RXEN 9/9 for EBYTE 39 | */ 40 | 41 | #ifdef USE_EBYTE 42 | SX126x lora(5, //Port-Pin Output: SPI select 43 | 6, //Port-Pin Output: Reset 44 | 7, //Port-Pin Input: Busy 45 | 8, //Port-Pin Output: TXEN 46 | 9 //Port-Pin Output: RXEN 47 | ); 48 | 49 | #else 50 | SX126x lora(5, //Port-Pin Output: SPI select 51 | 6, //Port-Pin Output: Reset 52 | 7 //Port-Pin Input: Busy 53 | ); 54 | #endif // USE_EBYTE 55 | 56 | #endif // ATmega328/2560 57 | 58 | #if 0 59 | /* 60 | * for ESP8266 61 | * VCC 3V3 62 | * GND GND 63 | * SCK GPIO14 64 | * MISO GPIO12 65 | * MOSI GPIO13 66 | * NSS GPIO2 67 | * RST GPIO0 68 | * BUSY GPIO16 69 | * TXEN GPIO4 for EBYTE 70 | * RXEN GPIO5 for EBYTE 71 | */ 72 | 73 | #ifdef USE_EBYTE 74 | SX126x lora(2, //Port-Pin Output: SPI select 75 | 0, //Port-Pin Output: Reset 76 | 16, //Port-Pin Input: Busy 77 | 4, //Port-Pin Output: TXEN 78 | 5 //Port-Pin Output: RXEN 79 | ); 80 | #else 81 | SX126x lora(2, //Port-Pin Output: SPI select 82 | 0, //Port-Pin Output: Reset 83 | 16 //Port-Pin Input: Busy 84 | ); 85 | #endif // USE_EBYTE 86 | 87 | #endif // ESP8266 88 | 89 | void setup() 90 | { 91 | delay(1000); 92 | Serial.begin(115200); 93 | 94 | //lora.DebugPrint(true); 95 | 96 | #ifdef USE_EBYTE 97 | Serial.println("Enable TCXO"); 98 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 99 | TX_OUTPUT_POWER, //tx power in dBm 100 | 3.3, //use TCXO 101 | true); //use TCXO 102 | if (ret != ERR_NONE) while(1) {delay(1);} 103 | #else 104 | Serial.println("Disable TCXO"); 105 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 106 | TX_OUTPUT_POWER); //tx power in dBm 107 | if (ret != ERR_NONE) while(1) {delay(1);} 108 | #endif // USE_EBYTE 109 | 110 | lora.LoRaConfig(LORA_SPREADING_FACTOR, 111 | LORA_BANDWIDTH, 112 | LORA_CODINGRATE, 113 | LORA_PREAMBLE_LENGTH, 114 | LORA_PAYLOADLENGTH, 115 | true, //crcOn 116 | false); //invertIrq 117 | 118 | } 119 | 120 | void loop() 121 | { 122 | static uint8_t i = 0; 123 | uint8_t txData[255]; 124 | uint8_t rxData[255]; 125 | sprintf((char *)txData, "Hello World %d", i); 126 | uint8_t len = strlen((char *)txData); 127 | 128 | // Wait for transmission to complete 129 | if (lora.Send(txData, len, SX126x_TXMODE_SYNC)) { 130 | Serial.println("Send success"); 131 | 132 | // Wait for responce 133 | unsigned long startMills = millis(); 134 | while(1) { 135 | uint8_t rxLen = lora.Receive(rxData, 255); 136 | if ( rxLen > 0 ) 137 | { 138 | Serial.print("Receive rxLen:"); 139 | Serial.println(rxLen); 140 | for(int i=0;i< rxLen;i++) { 141 | Serial.print(rxData[i], HEX); 142 | Serial.print(" "); 143 | } 144 | Serial.println(); 145 | for(int i=0;i< rxLen;i++) { 146 | if (rxData[i] > 0x19 && rxData[i] < 0x7F) { 147 | char myChar = rxData[i]; 148 | Serial.print(myChar); 149 | } else { 150 | Serial.print("?"); 151 | } 152 | } 153 | Serial.println(); 154 | 155 | int8_t rssi, snr; 156 | lora.GetPacketStatus(&rssi, &snr); 157 | Serial.print("rssi: "); 158 | Serial.print(rssi, DEC); 159 | Serial.println(" dBm"); 160 | Serial.print("snr: "); 161 | Serial.print(snr, DEC); 162 | Serial.println(" dB"); 163 | break; 164 | } // end if 165 | delay(1); 166 | 167 | // Check responce timeout 168 | if ( (millis() - startMills) > 5000) { 169 | Serial.println("No response within 5 seconds"); 170 | break; 171 | } 172 | } // end while 173 | 174 | } else { 175 | Serial.println("Send fail"); 176 | } 177 | 178 | i++; 179 | delay(1000); 180 | } 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino-LoRa-Ra01S 2 | This is an Arduino library for LoRa Communication using the radio transceiver chips [SX1262](https://www.semtech.com/products/wireless-rf/lora-core/sx1262) and [SX1268](https://www.semtech.com/products/wireless-rf/lora-core/sx1268). 3 | 4 | ![ra01s_ra01sh](https://user-images.githubusercontent.com/6020549/161641357-a0fe292b-095e-440b-b8ae-24c58084a51d.JPG) 5 | 6 | 7 | Ai-Thinker offers several LoRa modules. 8 | You can get these on AliExpress and eBay. 9 | 10 | |Model|Type|Interface/Core|Chip|Frequency|Foot-Pattern|High-Power|LoRa-WAN| 11 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 12 | |Ra-01|Tranceiver|SPI|SX1278|410-525Mhz|SMD16|No|No| 13 | |Ra-02|Tranceiver|SPI|SX1278|410-525Mhz|SMD16|No|No| 14 | |Ra-01H|Tranceiver|SPI|SX1276|803-930Mhz|SMD16|No|No| 15 | |Ra-01S|Tranceiver|SPI|**SX1268**|410-525Mhz|SMD16|No|No| 16 | |Ra-01S-P|Tranceiver|SPI|**SX1268**|410-525Mhz|SMD16|Yes|No| 17 | |Ra-01SH|Tranceiver|SPI|**SX1262**|803-930Mhz|SMD16|No|No| 18 | |Ra-01SH-P|Tranceiver|SPI|**SX1262**|803-930Mhz|SMD16|Yes|No| 19 | |Ra-01SC|Tranceiver|SPI|**LLCC68**|410-525Mhz|SMD16|No|No| 20 | |Ra-01SC-P|Tranceiver|SPI|**LLCC68**|410-525Mhz|SMD16|Yes|No| 21 | |Ra-01SCH|Tranceiver|SPI|**LLCC68**|803-930Mhz|SMD16|No|No| 22 | |Ra-01SCH-P|Tranceiver|SPI|**LLCC68**|803-930Mhz|SMD16|Yes|No| 23 | |Ra-03SCH|Tranceiver|SPI|**LLCC68**|803-930Mhz|SMD14|No|No| 24 | |Ra-06|MCU|ARM Cortex M0+|SX1278|410-525Mhz|SMD20|No|No| 25 | |Ra-07|MCU|ARM Cortex M0+|ASR6501|410-525Mhz|SMD18|No|Yes| 26 | |Ra-07H|MCU|ARM Cortex M0+|ASR6501|803-930Mhz|SMD18|No|Yes| 27 | |Ra-08|MCU|ARM Cortex M4|ASR6601|410-525Mhz|SMD18|No|Yes| 28 | |Ra-08H|MCU|ARM Cortex M4|ASR6601|803-930Mhz|SMD18|No|Yes| 29 | 30 | Datasheets for each module can be found [here](https://docs.ai-thinker.com/en/lora/). 31 | 32 | # Option with SX1262/1268 33 | LoRa modules with SX1262/1268 have several options. 34 | 35 | - Using TCXO(Temperature-Compensated Crystal Oscillator) 36 | SX1262/1268 can use the TCXO. 37 | If the TCXO is used, the XTB pin is not connected. 38 | However, the 6th pin (DIO3) of the SX1262/1268 can be used to power the TCXO. 39 | Explanation for TXCO and antenna control is [here](https://github.com/beegee-tokyo/SX126x-Arduino). 40 | Ra-01S / Ra-01SH does not use TCXO. 41 | 42 | - Power supply modes 43 | SX1262/1268 has two power supply modes. 44 | One is that only LDO used in all modes. 45 | Another is that DC_DC+LDO used for STBY_XOSC,FS, RX and TX modes. 46 | Explanation for LDO and DCDC selection is [here](https://github.com/beegee-tokyo/SX126x-Arduino). 47 | Ra-01S / Ra-01SH use only LDO in all modes. 48 | 49 | - RF-Switching 50 | In general, use DIO2 to switch the RF-Switch. 51 | However, some tranceiver use an external gpio to switch the RF-Switch. 52 | Ra-01S / Ra-01SH use the SC70-6 integrated load switch to switch between RFO and RFI. 53 | Ra-01S / Ra-01SH use DIO2 to control this. 54 | DIO2 = 1, CTRL = 0, RFC to RF1 Tx Mode. 55 | DIO2 = 0, CTRL = 1, RFC to R21 Rx Mode. 56 | 57 | You need to look at the schematic to set these options properly, but it's very esoteric. 58 | The default settings for this library are for Ra-01S / Ra-01SH. 59 | __When using other than Ra-01S/01SH, you need to set them appropriately.__ 60 | 61 | I created this library based on [this](https://github.com/tinytronix/SX126x). 62 | With this library, Ra-01S/01SH doesn't work. 63 | 64 | # About LLCC68 65 | LLCC68 is compatible with SX1262/SX1268. 66 | Different between LLCC68 and SX1262/SX1268: 67 | (1) SX1262/SX1268 support spreading factor SF5,SF6,SF7,SF8,SF9,SF10,SF11,SF12. 68 | SX1262/SX1268 can set spreading factor and receiving bandwidth: 69 | LoRa@ Rx/Tx, BW = 7.8 - 500 kHz 70 | SF5 TO SF12,BR=0.018-62.5 Kb/S 71 | 72 | (2) LLCC68 support spreading factor SF5,SF6,SF7,SF8,SF9,SF10,SF11. 73 | LLCC68 can set spreading factor and receiving bandwidth: 74 | LoRa@ Rx/Tx, BW = 125 - 250 - 500 kHz 75 | LoRa@ SF=5-6-7-8-9 for BW=125kHz 76 | LoRa@ SF=5-6-7-8-9-10 for BW =250 kHz 77 | LoRa@ SF=5-6-7-8-9-10-11 for BW=500 kHz 78 | 79 | __When using LLCC68 other than Ra-01SC/01SCH, it is necessary to set the options appropriately based on the datasheet.__ 80 | 81 | ![ra01sc](https://user-images.githubusercontent.com/6020549/169180199-12a88938-1d6d-43c7-836d-f3c2081ac10d.JPG) 82 | 83 | # Foot pattern 84 | RA-0x(SMD16) has the same foot pattern as ESP12. 85 | Therefore, a pitch conversion PCB for ESP12 can be used. 86 | We have pitch conversion PCBs available on eBay and AliExpress. 87 | 88 | ![ra01s-3](https://user-images.githubusercontent.com/6020549/161641874-32a79d5f-dbae-42f1-a8cd-d0787c238a06.JPG) 89 | ![ra01s-2](https://user-images.githubusercontent.com/6020549/161641421-e720a7da-4889-4bd4-b2c6-1f3a28518cf8.JPG) 90 | 91 | # Installation 92 | Download this repo as zip. Then in the Arduino IDE go to Sketch->Add library->add .zip library. 93 | 94 | # Wiring 95 | |Ra-01S/SH||UNO|MEGA|ESP8266| 96 | |:-:|:-:|:-:|:-:|:-:| 97 | |VCC|--|3.3V(*1)|3.3V|3.3V| 98 | |GND|--|GND|GND|GND| 99 | |SCK|--|D13(*2)|D52(*2)|IO14| 100 | |MISO|--|D12|D50|IO12| 101 | |MOSI|--|D11(*2)|D51(*2)|IO13| 102 | |NSS|--|D5(*2)|D5(*2)|IO2| 103 | |RST|--|D6(*2)|D6(*2)|IO0| 104 | |BUSY|--|D7(*2)|D7(*2)|IO16| 105 | |TXEN|--|N/C|N/C|N/C| 106 | |RXEN|--|N/C|N/C|N/C| 107 | 108 | 109 | (*1) 110 | UNO's 3.3V output can only supply 50mA. 111 | In addition, the output current capacity of UNO-compatible devices is smaller than that of official products. 112 | __So this module may not work normally when supplied from the on-board 3v3.__ 113 | 114 | (*2) 115 | SX126x is not 5V tolerant. 116 | You need level shift from 5V to 3.3V. 117 | I used [this](https://www.ti.com/lit/ds/symlink/txs0108e.pdf?ts=1647593549503) for a level shift. 118 | 119 | # Using EBYTE Module 120 | 121 | EBYTE offers several LoRa modules. 122 | You can get these on AliExpress and eBay. 123 | 124 | |Model|Interface|Chip|Frequency|Power|Foot-Patten|IPEX-Antena|LoRa-WAN| 125 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 126 | |E22-400M22S|SPI|SX1268|433/470Mhz|160mW|Standard|Yes|No| 127 | |E22-400M30S|SPI|SX1268|433/470Mhz|1000mW|Standard|Yes|No| 128 | |E22-400MM22S|SPI|SX1268|433/470Mhz|160mW|Small|No|No| 129 | |E22-900M22S|SPI|SX1262|868/915Mhz|160mW|Standard|Yes|No| 130 | |E22-900M30S|SPI|SX1262|868/915Mhz|1000mW|Standard|Yes|No| 131 | |E22-900MM22S|SPI|SX1262|868/915Mhz|160mW|Small|No|No| 132 | 133 | ![EBYTE-1](https://user-images.githubusercontent.com/6020549/221339540-4330b34d-1aea-4911-87c5-607a5a3d4b57.JPG) 134 | ![EBYTE-2](https://user-images.githubusercontent.com/6020549/221339539-40fc9e6f-9224-4b0c-b222-efa5d9850560.JPG) 135 | 136 | With this change it work. 137 | 138 | 139 | ``` 140 | /* 141 | SX126x lora(5, //Port-Pin Output: SPI select 142 | 6, //Port-Pin Output: Reset 143 | 7 //Port-Pin Input: Busy 144 | ); 145 | 146 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 147 | TX_OUTPUT_POWER); //tx power in dBm 148 | */ 149 | 150 | SX126x lora(5, //Port-Pin Output: SPI select 151 | 6, //Port-Pin Output: Reset 152 | 7 //Port-Pin Input: Busy 153 | 8 //Port-Pin Output: TXEN 154 | 9 //Port-Pin Output: RXEN 155 | ); 156 | 157 | int16_t ret = lora.begin(RF_FREQUENCY, //frequency in Hz 158 | TX_OUTPUT_POWER, //tx power in dBm 159 | 3.3, //use TCXO 160 | true); //use TCXO 161 | ``` 162 | 163 | 164 | Two additional wires are required. 165 | |EBYTE||UNO|MEGA|ESP8266| 166 | |:-:|:-:|:-:|:-:|:-:| 167 | |TXEN|--|8(*3)|8(*3)|D4| 168 | |RXEN|--|9(*3)|9(*3)|D5| 169 | 170 | (*3) 171 | SX126x is not 5V tolerant. 172 | You need level shift from 5V to 3.3V. 173 | 174 | The pitch conversion base is [here](https://github.com/nopnop2002/esp-idf-sx126x/tree/main/ebyte-smd-pcb). 175 | 176 | SX1262 and LLCC68 are compatible, but for some reason they don't work. 177 | |Model|Interface|Chip|Frequency|Power|Foot-Patten|IPEX-Antena|LoRa-WAN| 178 | |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| 179 | |E220-400M22S|SPI|LLCC68|433/470Mhz|160mW|Standard|Yes|No| 180 | |E220-400M30S|SPI|LLCC68|433/470Mhz|1000mW|Standard|Yes|No| 181 | |E220-900M22S|SPI|LLCC68|868/915Mhz|160mW|Standard|Yes|No| 182 | |E220-900M30S|SPI|LLCC68|868/915Mhz|1000mW|Standard|Yes|No| 183 | 184 | # Software compatibility 185 | This library can communicate with [RadioLib](https://github.com/jgromes/RadioLib). 186 | RadioLib require DIO1 connected in order to works. 187 | 188 | ``` 189 | // Set frequency: 866Mhz 190 | // Set bandwidth(BW): 125Khz 191 | // Set Spreading Factor(SF): 7 192 | // Set Error Cording Rate(CR): 4/5 193 | // Set SyncWord: 0x1424(Private Network) 194 | // Set Power: 10dBm 195 | // Set Preamble Length: 8 196 | // Configure the radio to NOT use a TCXO controlled by DIO3 197 | // Set regulator mode: DC-DC 198 | int state = radio.begin(866.0, 125.0, 7, 5, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, 10, 8, 0.0, false); 199 | ``` 200 | 201 | # Limitation 202 | The SX126x chip supports FSK/GFSK/MSK/GMSK/OOK modulation methods , but these are not supported by this library. 203 | 204 | # Communication with SX127X 205 | LoRa's packet format is strictly specified. 206 | Therefore, if the following three parameters are the same, they can communicate with each other. 207 | - Signal Bandwidth (= BW) 208 | - Error Cording Rate (= CR) 209 | - Spreading Factor (= SF) 210 | 211 | # About communication speed and maximum reception sensitivity 212 | In LoRa modulation mode, the communication speed (bps) and maximum reception sensitivity (RSSI) are determined by a combination of spreading factor (SF), bandwidth (BW), and coding rate (CDR). 213 | - SF 214 | Increasing SF increases the spreading factor and improves noise resistance. 215 | This improves reception sensitivity and extends communication distance, but communication speed decreases. 216 | - BW 217 | Bandwidth sets the width of the communication band. Setting a larger bandwidth will improve communication speed. 218 | However, the radio reception sensitivity (RSSI) will decrease. 219 | - CDR 220 | CDR (CodingRate) sets the level of error correction rate. 221 | The larger the number, the better the correction rate, but the amount of information per packet increases. 222 | (No effect on maximum reception sensitivity) 223 | You can set whether to use Optimaise for each CDR, and enabling it will improve the correction rate, but will reduce communication speed. 224 | 225 | # SX1262 and SX1278, SX1276 Comparison 226 | [This](https://www.cdebyte.com/news/580) will be helpful. 227 | 228 | # Build ESP8266 with PlatformIO 229 | ``` 230 | $ git clone https://github.com/nopnop2002/Arduino-LoRa-Ra01S 231 | 232 | $ cd Arduino-LoRa-Ra01S/example/Ra01S-RX/ 233 | 234 | $ pio init -b d1_mini 235 | 236 | $ cp Ra01S-RX.ino src/ 237 | 238 | $ vi src/Ra01S-RX.ino 239 | Disable AtMega 240 | Enable ESP8266 241 | 242 | $ vi platform.ini 243 | [env:d1_mini] 244 | platform = espressif8266 245 | board = d1_mini 246 | framework = arduino 247 | lib_deps = https://github.com/nopnop2002/Arduino-LoRa-Ra01S --> Add this line 248 | 249 | $ pio run -t upload && pio device monitor -b 115200 250 | ``` 251 | 252 | -------------------------------------------------------------------------------- /Ra01S.h: -------------------------------------------------------------------------------- 1 | #ifndef _RA01S_H 2 | #define _RA01S_H 3 | 4 | //return values 5 | #define ERR_NONE 0 6 | #define ERR_PACKET_TOO_LONG 1 7 | #define ERR_UNKNOWN 2 8 | #define ERR_TX_TIMEOUT 3 9 | #define ERR_RX_TIMEOUT 4 10 | #define ERR_CRC_MISMATCH 5 11 | #define ERR_WRONG_MODEM 6 12 | #define ERR_INVALID_BANDWIDTH 7 13 | #define ERR_INVALID_SPREADING_FACTOR 8 14 | #define ERR_INVALID_CODING_RATE 9 15 | #define ERR_INVALID_FREQUENCY_DEVIATION 10 16 | #define ERR_INVALID_BIT_RATE 11 17 | #define ERR_INVALID_RX_BANDWIDTH 12 18 | #define ERR_INVALID_DATA_SHAPING 13 19 | #define ERR_INVALID_SYNC_WORD 14 20 | #define ERR_INVALID_OUTPUT_POWER 15 21 | #define ERR_INVALID_MODE 16 22 | #define ERR_INVALID_TRANCEIVER 17 23 | 24 | // SX126X physical layer properties 25 | #define XTAL_FREQ ( double )32000000 26 | #define FREQ_DIV ( double )pow( 2.0, 25.0 ) 27 | #define FREQ_STEP ( double )( XTAL_FREQ / FREQ_DIV ) 28 | #define BUSY_WAIT 5000 29 | 30 | // SX126X Model 31 | #define SX1261_TRANCEIVER 0x01 32 | #define SX1262_TRANCEIVER 0x02 33 | #define SX1268_TRANCEIVER 0x08 34 | 35 | // SX126X SPI commands 36 | // operational modes commands 37 | #define SX126X_CMD_NOP 0x00 38 | #define SX126X_CMD_SET_SLEEP 0x84 39 | #define SX126X_CMD_SET_STANDBY 0x80 40 | #define SX126X_CMD_SET_FS 0xC1 41 | #define SX126X_CMD_SET_TX 0x83 42 | #define SX126X_CMD_SET_RX 0x82 43 | #define SX126X_CMD_STOP_TIMER_ON_PREAMBLE 0x9F 44 | #define SX126X_CMD_SET_RX_DUTY_CYCLE 0x94 45 | #define SX126X_CMD_SET_CAD 0xC5 46 | #define SX126X_CMD_SET_TX_CONTINUOUS_WAVE 0xD1 47 | #define SX126X_CMD_SET_TX_INFINITE_PREAMBLE 0xD2 48 | #define SX126X_CMD_SET_REGULATOR_MODE 0x96 49 | #define SX126X_CMD_CALIBRATE 0x89 50 | #define SX126X_CMD_CALIBRATE_IMAGE 0x98 51 | #define SX126X_CMD_SET_PA_CONFIG 0x95 52 | #define SX126X_CMD_SET_RX_TX_FALLBACK_MODE 0x93 53 | 54 | // register and buffer access commands 55 | #define SX126X_CMD_WRITE_REGISTER 0x0D 56 | #define SX126X_CMD_READ_REGISTER 0x1D 57 | #define SX126X_CMD_WRITE_BUFFER 0x0E 58 | #define SX126X_CMD_READ_BUFFER 0x1E 59 | 60 | // DIO and IRQ control 61 | #define SX126X_CMD_SET_DIO_IRQ_PARAMS 0x08 62 | #define SX126X_CMD_GET_IRQ_STATUS 0x12 63 | #define SX126X_CMD_CLEAR_IRQ_STATUS 0x02 64 | #define SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 0x9D 65 | #define SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 0x97 66 | 67 | // RF, modulation and packet commands 68 | #define SX126X_CMD_SET_RF_FREQUENCY 0x86 69 | #define SX126X_CMD_SET_PACKET_TYPE 0x8A 70 | #define SX126X_CMD_GET_PACKET_TYPE 0x11 71 | #define SX126X_CMD_SET_TX_PARAMS 0x8E 72 | #define SX126X_CMD_SET_MODULATION_PARAMS 0x8B 73 | #define SX126X_CMD_SET_PACKET_PARAMS 0x8C 74 | #define SX126X_CMD_SET_CAD_PARAMS 0x88 75 | #define SX126X_CMD_SET_BUFFER_BASE_ADDRESS 0x8F 76 | #define SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT 0xA0 77 | 78 | #define SX126X_PA_CONFIG_SX1261 0x01 79 | #define SX126X_PA_CONFIG_SX1262 0x00 80 | 81 | // status commands 82 | #define SX126X_CMD_GET_STATUS 0xC0 83 | #define SX126X_CMD_GET_RSSI_INST 0x15 84 | #define SX126X_CMD_GET_RX_BUFFER_STATUS 0x13 85 | #define SX126X_CMD_GET_PACKET_STATUS 0x14 86 | #define SX126X_CMD_GET_DEVICE_ERRORS 0x17 87 | #define SX126X_CMD_CLEAR_DEVICE_ERRORS 0x07 88 | #define SX126X_CMD_GET_STATS 0x10 89 | #define SX126X_CMD_RESET_STATS 0x00 90 | 91 | 92 | // SX126X register map 93 | #define SX126X_REG_HOPPING_ENABLE 0x0385 94 | #define SX126X_REG_PACKECT_LENGTH 0x0386 95 | #define SX126X_REG_NB_HOPPING_BLOCKS 0x0387 96 | #define SX126X_REG_NB_SYMBOLS0 0x0388 97 | #define SX126X_REG_FREQ0 0x038A 98 | #define SX126X_REG_NB_SYMBOLS15 0x03E2 99 | #define SX126X_REG_FREQ15 0x03E4 100 | #define SX126X_REG_DIOX_OUTPUT_ENABLE 0x0580 101 | #define SX126X_REG_DIOX_INPUT_ENABLE 0x0583 102 | #define SX126X_REG_DIOX_PILL_UP_CONTROL 0x0584 103 | #define SX126X_REG_DIOX_PULL_DOWN_CONTROL 0x0585 104 | #define SX126X_REG_WHITENING_INITIAL_MSB 0x06B8 105 | #define SX126X_REG_WHITENING_INITIAL_LSB 0x06B9 106 | #define SX126X_REG_CRC_INITIAL_MSB 0x06BC 107 | #define SX126X_REG_CRC_INITIAL_LSB 0x06BD 108 | #define SX126X_REG_CRC_POLYNOMIAL_MSB 0x06BE 109 | #define SX126X_REG_CRC_POLYNOMIAL_LSB 0x06BF 110 | #define SX126X_REG_SYNC_WORD_0 0x06C0 111 | #define SX126X_REG_SYNC_WORD_1 0x06C1 112 | #define SX126X_REG_SYNC_WORD_2 0x06C2 113 | #define SX126X_REG_SYNC_WORD_3 0x06C3 114 | #define SX126X_REG_SYNC_WORD_4 0x06C4 115 | #define SX126X_REG_SYNC_WORD_5 0x06C5 116 | #define SX126X_REG_SYNC_WORD_6 0x06C6 117 | #define SX126X_REG_SYNC_WORD_7 0x06C7 118 | #define SX126X_REG_NODE_ADDRESS 0x06CD 119 | #define SX126X_REG_BROADCAST_ADDRESS 0x06CE 120 | #define SX126X_REG_IQ_POLARITY_SETUP 0x0736 121 | #define SX126X_REG_LORA_SYNC_WORD_MSB 0x0740 122 | #define SX126X_REG_LORA_SYNC_WORD_LSB 0x0741 123 | #define SX126X_REG_RANDOM_NUMBER_0 0x0819 124 | #define SX126X_REG_RANDOM_NUMBER_1 0x081A 125 | #define SX126X_REG_RANDOM_NUMBER_2 0x081B 126 | #define SX126X_REG_RANDOM_NUMBER_3 0x081C 127 | #define SX126X_REG_TX_MODULETION 0x0889 128 | #define SX126X_REG_RX_GAIN 0x08AC 129 | #define SX126X_REG_TX_CLAMP_CONFIG 0x08D8 130 | #define SX126X_REG_OCP_CONFIGURATION 0x08E7 131 | #define SX126X_REG_RTC_CONTROL 0x0902 132 | #define SX126X_REG_XTA_TRIM 0x0911 133 | #define SX126X_REG_XTB_TRIM 0x0912 134 | #define SX126X_REG_DIO3_OUTPUT_VOLTAGE_CONTROL 0x0920 135 | #define SX126X_REG_EVENT_MASK 0x0944 136 | 137 | 138 | // SX126X SPI command variables 139 | //SX126X_CMD_SET_SLEEP 140 | #define SX126X_SLEEP_START_COLD 0b00000000 // 2 2 sleep mode: cold start, configuration is lost (default) 141 | #define SX126X_SLEEP_START_WARM 0b00000100 // 2 2 warm start, configuration is retained 142 | #define SX126X_SLEEP_RTC_OFF 0b00000000 // 0 0 wake on RTC timeout: disabled 143 | #define SX126X_SLEEP_RTC_ON 0b00000001 // 0 0 enabled 144 | 145 | //SX126X_CMD_SET_STANDBY 146 | #define SX126X_STANDBY_RC 0x00 // 7 0 standby mode: 13 MHz RC oscillator 147 | #define SX126X_STANDBY_XOSC 0x01 // 7 0 32 MHz crystal oscillator 148 | 149 | //SX126X_CMD_SET_RX 150 | #define SX126X_RX_TIMEOUT_NONE 0x000000 // 23 0 Rx timeout duration: no timeout (Rx single mode) 151 | #define SX126X_RX_TIMEOUT_INF 0xFFFFFF // 23 0 infinite (Rx continuous mode) 152 | 153 | //SX126X_CMD_STOP_TIMER_ON_PREAMBLE 154 | #define SX126X_STOP_ON_PREAMBLE_OFF 0x00 // 7 0 stop timer on: sync word or header (default) 155 | #define SX126X_STOP_ON_PREAMBLE_ON 0x01 // 7 0 preamble detection 156 | 157 | //SX126X_CMD_SET_REGULATOR_MODE 158 | #define SX126X_REGULATOR_LDO 0x00 // 7 0 set regulator mode: LDO (default) 159 | #define SX126X_REGULATOR_DC_DC 0x01 // 7 0 DC-DC 160 | 161 | //SX126X_CMD_CALIBRATE 162 | #define SX126X_CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled 163 | #define SX126X_CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled 164 | #define SX126X_CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled 165 | #define SX126X_CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled 166 | #define SX126X_CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled 167 | #define SX126X_CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled 168 | #define SX126X_CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled 169 | #define SX126X_CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled 170 | #define SX126X_CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled 171 | #define SX126X_CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled 172 | #define SX126X_CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled 173 | #define SX126X_CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled 174 | #define SX126X_CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled 175 | #define SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled 176 | 177 | //SX126X_CMD_CALIBRATE_IMAGE 178 | #define SX126X_CAL_IMG_430_MHZ_1 0x6B 179 | #define SX126X_CAL_IMG_430_MHZ_2 0x6F 180 | #define SX126X_CAL_IMG_470_MHZ_1 0x75 181 | #define SX126X_CAL_IMG_470_MHZ_2 0x81 182 | #define SX126X_CAL_IMG_779_MHZ_1 0xC1 183 | #define SX126X_CAL_IMG_779_MHZ_2 0xC5 184 | #define SX126X_CAL_IMG_863_MHZ_1 0xD7 185 | #define SX126X_CAL_IMG_863_MHZ_2 0xDB 186 | #define SX126X_CAL_IMG_902_MHZ_1 0xE1 187 | #define SX126X_CAL_IMG_902_MHZ_2 0xE9 188 | 189 | //SX126X_CMD_SET_PA_CONFIG 190 | #define SX126X_PA_CONFIG_HP_MAX 0x07 191 | #define SX126X_PA_CONFIG_SX1268 0x01 192 | #define SX126X_PA_CONFIG_PA_LUT 0x01 193 | 194 | //SX126X_CMD_SET_RX_TX_FALLBACK_MODE 195 | #define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode 196 | #define SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC 0x30 // 7 0 standby with crystal oscillator 197 | #define SX126X_RX_TX_FALLBACK_MODE_STDBY_RC 0x20 // 7 0 standby with RC oscillator (default) 198 | 199 | //SX126X_CMD_SET_DIO_IRQ_PARAMS 200 | #define SX126X_IRQ_TIMEOUT 0b1000000000 // 9 9 Rx or Tx timeout 201 | #define SX126X_IRQ_CAD_DETECTED 0b0100000000 // 8 8 channel activity detected 202 | #define SX126X_IRQ_CAD_DONE 0b0010000000 // 7 7 channel activity detection finished 203 | #define SX126X_IRQ_CRC_ERR 0b0001000000 // 6 6 wrong CRC received 204 | #define SX126X_IRQ_HEADER_ERR 0b0000100000 // 5 5 LoRa header CRC error 205 | #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received 206 | #define SX126X_IRQ_SYNC_WORD_VALID 0b0000001000 // 3 3 valid sync word detected 207 | #define SX126X_IRQ_PREAMBLE_DETECTED 0b0000000100 // 2 2 preamble detected 208 | #define SX126X_IRQ_RX_DONE 0b0000000010 // 1 1 packet received 209 | #define SX126X_IRQ_TX_DONE 0b0000000001 // 0 0 packet transmission completed 210 | #define SX126X_IRQ_ALL 0b1111111111 // 9 0 all interrupts 211 | #define SX126X_IRQ_NONE 0b0000000000 // 9 0 no interrupts 212 | 213 | //SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 214 | #define SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ 215 | #define SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control 216 | 217 | //SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 218 | #define SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V 219 | #define SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V 220 | #define SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V 221 | #define SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V 222 | #define SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V 223 | #define SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V 224 | #define SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V 225 | #define SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V 226 | 227 | //Radio complete Wake-up Time with TCXO stabilisation time 228 | #define RADIO_TCXO_SETUP_TIME 5000 // [us] 229 | 230 | //SX126X_CMD_SET_PACKET_TYPE 231 | #define SX126X_PACKET_TYPE_GFSK 0x00 // 7 0 packet type: GFSK 232 | #define SX126X_PACKET_TYPE_LORA 0x01 // 7 0 LoRa 233 | 234 | //SX126X_CMD_SET_TX_PARAMS 235 | #define SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us 236 | #define SX126X_PA_RAMP_20U 0x01 // 7 0 20 us 237 | #define SX126X_PA_RAMP_40U 0x02 // 7 0 40 us 238 | #define SX126X_PA_RAMP_80U 0x03 // 7 0 80 us 239 | #define SX126X_PA_RAMP_200U 0x04 // 7 0 200 us 240 | #define SX126X_PA_RAMP_800U 0x05 // 7 0 800 us 241 | #define SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us 242 | #define SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us 243 | 244 | //SX126X_CMD_SET_MODULATION_PARAMS 245 | #define SX126X_GFSK_FILTER_NONE 0x00 // 7 0 GFSK filter: none 246 | #define SX126X_GFSK_FILTER_GAUSS_0_3 0x08 // 7 0 Gaussian, BT = 0.3 247 | #define SX126X_GFSK_FILTER_GAUSS_0_5 0x09 // 7 0 Gaussian, BT = 0.5 248 | #define SX126X_GFSK_FILTER_GAUSS_0_7 0x0A // 7 0 Gaussian, BT = 0.7 249 | #define SX126X_GFSK_FILTER_GAUSS_1 0x0B // 7 0 Gaussian, BT = 1 250 | #define SX126X_GFSK_RX_BW_4_8 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz 251 | #define SX126X_GFSK_RX_BW_5_8 0x17 // 7 0 5.8 kHz 252 | #define SX126X_GFSK_RX_BW_7_3 0x0F // 7 0 7.3 kHz 253 | #define SX126X_GFSK_RX_BW_9_7 0x1E // 7 0 9.7 kHz 254 | #define SX126X_GFSK_RX_BW_11_7 0x16 // 7 0 11.7 kHz 255 | #define SX126X_GFSK_RX_BW_14_6 0x0E // 7 0 14.6 kHz 256 | #define SX126X_GFSK_RX_BW_19_5 0x1D // 7 0 19.5 kHz 257 | #define SX126X_GFSK_RX_BW_23_4 0x15 // 7 0 23.4 kHz 258 | #define SX126X_GFSK_RX_BW_29_3 0x0D // 7 0 29.3 kHz 259 | #define SX126X_GFSK_RX_BW_39_0 0x1C // 7 0 39.0 kHz 260 | #define SX126X_GFSK_RX_BW_46_9 0x14 // 7 0 46.9 kHz 261 | #define SX126X_GFSK_RX_BW_58_6 0x0C // 7 0 58.6 kHz 262 | #define SX126X_GFSK_RX_BW_78_2 0x1B // 7 0 78.2 kHz 263 | #define SX126X_GFSK_RX_BW_93_8 0x13 // 7 0 93.8 kHz 264 | #define SX126X_GFSK_RX_BW_117_3 0x0B // 7 0 117.3 kHz 265 | #define SX126X_GFSK_RX_BW_156_2 0x1A // 7 0 156.2 kHz 266 | #define SX126X_GFSK_RX_BW_187_2 0x12 // 7 0 187.2 kHz 267 | #define SX126X_GFSK_RX_BW_234_3 0x0A // 7 0 234.3 kHz 268 | #define SX126X_GFSK_RX_BW_312_0 0x19 // 7 0 312.0 kHz 269 | #define SX126X_GFSK_RX_BW_373_6 0x11 // 7 0 373.6 kHz 270 | #define SX126X_GFSK_RX_BW_467_0 0x09 // 7 0 467.0 kHz 271 | #define SX126X_LORA_BW_7_8 0x00 // 7 0 LoRa bandwidth: 7.8 kHz 272 | #define SX126X_LORA_BW_10_4 0x08 // 7 0 10.4 kHz 273 | #define SX126X_LORA_BW_15_6 0x01 // 7 0 15.6 kHz 274 | #define SX126X_LORA_BW_20_8 0x09 // 7 0 20.8 kHz 275 | #define SX126X_LORA_BW_31_25 0x02 // 7 0 31.25 kHz 276 | #define SX126X_LORA_BW_41_7 0x0A // 7 0 41.7 kHz 277 | #define SX126X_LORA_BW_62_5 0x03 // 7 0 62.5 kHz 278 | #define SX126X_LORA_BW_125_0 0x04 // 7 0 125.0 kHz 279 | #define SX126X_LORA_BW_250_0 0x05 // 7 0 250.0 kHz 280 | #define SX126X_LORA_BW_500_0 0x06 // 7 0 500.0 kHz 281 | #define SX126X_LORA_CR_4_5 0x01 // 7 0 LoRa coding rate: 4/5 282 | #define SX126X_LORA_CR_4_6 0x02 // 7 0 4/6 283 | #define SX126X_LORA_CR_4_7 0x03 // 7 0 4/7 284 | #define SX126X_LORA_CR_4_8 0x04 // 7 0 4/8 285 | #define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF 0x00 // 7 0 LoRa low data rate optimization: disabled 286 | #define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON 0x01 // 7 0 enabled 287 | 288 | //SX126X_CMD_SET_PACKET_PARAMS 289 | #define SX126X_GFSK_PREAMBLE_DETECT_OFF 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled 290 | #define SX126X_GFSK_PREAMBLE_DETECT_8 0x04 // 7 0 8 bits 291 | #define SX126X_GFSK_PREAMBLE_DETECT_16 0x05 // 7 0 16 bits 292 | #define SX126X_GFSK_PREAMBLE_DETECT_24 0x06 // 7 0 24 bits 293 | #define SX126X_GFSK_PREAMBLE_DETECT_32 0x07 // 7 0 32 bits 294 | #define SX126X_GFSK_ADDRESS_FILT_OFF 0x00 // 7 0 GFSK address filtering: disabled 295 | #define SX126X_GFSK_ADDRESS_FILT_NODE 0x01 // 7 0 node only 296 | #define SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST 0x02 // 7 0 node and broadcast 297 | #define SX126X_GFSK_PACKET_FIXED 0x00 // 7 0 GFSK packet type: fixed (payload length known in advance to both sides) 298 | #define SX126X_GFSK_PACKET_VARIABLE 0x01 // 7 0 variable (payload length added to packet) 299 | #define SX126X_GFSK_CRC_OFF 0x01 // 7 0 GFSK packet CRC: disabled 300 | #define SX126X_GFSK_CRC_1_BYTE 0x00 // 7 0 1 byte 301 | #define SX126X_GFSK_CRC_2_BYTE 0x02 // 7 0 2 byte 302 | #define SX126X_GFSK_CRC_1_BYTE_INV 0x04 // 7 0 1 byte, inverted 303 | #define SX126X_GFSK_CRC_2_BYTE_INV 0x06 // 7 0 2 byte, inverted 304 | #define SX126X_GFSK_WHITENING_OFF 0x00 // 7 0 GFSK data whitening: disabled 305 | #define SX126X_GFSK_WHITENING_ON 0x01 // 7 0 enabled 306 | #define SX126X_LORA_HEADER_EXPLICIT 0x00 // 7 0 LoRa header mode: explicit 307 | #define SX126X_LORA_HEADER_IMPLICIT 0x01 // 7 0 implicit 308 | #define SX126X_LORA_CRC_OFF 0x00 // 7 0 LoRa CRC mode: disabled 309 | #define SX126X_LORA_CRC_ON 0x01 // 7 0 enabled 310 | #define SX126X_LORA_IQ_STANDARD 0x00 // 7 0 LoRa IQ setup: standard 311 | #define SX126X_LORA_IQ_INVERTED 0x01 // 7 0 inverted 312 | 313 | //SX126X_CMD_SET_CAD_PARAMS 314 | #define SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1 315 | #define SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2 316 | #define SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4 317 | #define SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8 318 | #define SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16 319 | #define SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode 320 | #define SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected 321 | 322 | //SX126X_CMD_GET_STATUS 323 | #define SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC 324 | #define SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC 325 | #define SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS 326 | #define SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX 327 | #define SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX 328 | #define SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved 329 | #define SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out 330 | #define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command 331 | #define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute 332 | #define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done 333 | #define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed 334 | 335 | //SX126X_CMD_GET_PACKET_STATUS 336 | #define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error 337 | #define SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error 338 | #define SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error 339 | #define SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error 340 | #define SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error 341 | #define SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error 342 | #define SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received 343 | #define SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent 344 | 345 | //SX126X_CMD_GET_DEVICE_ERRORS 346 | #define SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed 347 | #define SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock 348 | #define SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start 349 | #define SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed 350 | #define SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed 351 | #define SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed 352 | #define SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed 353 | #define SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed 354 | 355 | 356 | //SX126X SPI register variables 357 | //SX126X_REG_LORA_SYNC_WORD_MSB + LSB 358 | #define SX126X_SYNC_WORD_PUBLIC 0x3444 359 | #define SX126X_SYNC_WORD_PRIVATE 0x1424 360 | 361 | #define SX126x_TXMODE_ASYNC 0x01 362 | #define SX126x_TXMODE_SYNC 0x02 363 | #define SX126x_TXMODE_BACK2RX 0x04 364 | 365 | 366 | // common low-level SPI interface 367 | class SX126x { 368 | public: 369 | SX126x(int spiSelect, int reset, int busy, int txen = -1, int rxen = -1); 370 | 371 | int16_t begin(uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage = 0.0, bool useRegulatorLDO = false); 372 | void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, bool crcOn, bool invertIrq); 373 | uint8_t Receive(uint8_t *pData, uint16_t len); 374 | bool Send(uint8_t *pData, uint8_t len, uint8_t mode); 375 | bool ReceiveMode(void); 376 | void GetPacketStatus(int8_t *rssiPacket, int8_t *snrPacket); 377 | void SetTxPower(int8_t txPowerInDbm); 378 | uint32_t GetRandomNumber(void); 379 | void DebugPrint(bool enable); 380 | void SetDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask); 381 | 382 | 383 | private: 384 | uint8_t PacketParams[6] = {0}; 385 | bool txActive; 386 | bool debugPrint; 387 | int SX126x_SPI_SELECT; 388 | int SX126x_RESET; 389 | int SX126x_BUSY; 390 | int SX126x_TXEN; 391 | int SX126x_RXEN; 392 | 393 | void FixInvertedIQ(uint8_t iqConfig); 394 | void SetDio3AsTcxoCtrl(float voltage, uint32_t delay); 395 | void SetDio2AsRfSwitchCtrl(uint8_t enable); 396 | void Reset(void); 397 | void SetSleep(uint8_t mode); 398 | void SetStandby(uint8_t mode); 399 | void SetRfFrequency(uint32_t frequency); 400 | void Calibrate(uint8_t calibParam); 401 | void CalibrateImage(uint32_t frequency); 402 | void SetRegulatorMode(uint8_t mode); 403 | void SetBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress); 404 | void SetPowerConfig(int8_t power, uint8_t rampTime); 405 | void SetOvercurrentProtection(float currentLimit); 406 | void SetPaConfig(uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut); 407 | void SetStopRxTimerOnPreambleDetect(bool enable); 408 | void SetLoRaSymbNumTimeout(uint8_t SymbNum); 409 | void SetPacketType(uint8_t packetType); 410 | void SetModulationParams(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize); 411 | uint8_t GetStatus(void); 412 | uint16_t GetIrqStatus(void); 413 | void ClearIrqStatus(uint16_t irq); 414 | void SetTxEnable(void); 415 | void SetRxEnable(void); 416 | void SetRx(uint32_t timeout); 417 | void SetTx(uint32_t timeoutInMs); 418 | uint8_t GetRssiInst(); 419 | void GetRxBufferStatus(uint8_t *payloadLength, uint8_t *rxStartBufferPointer); 420 | void Wakeup(void); 421 | void WaitForIdle(unsigned long timeout, char *text, bool stop); 422 | uint8_t ReadBuffer(uint8_t *rxData, uint8_t maxLen); 423 | void WriteBuffer(uint8_t *txData, uint8_t txDataLen); 424 | void WriteRegister(uint16_t reg, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); 425 | void ReadRegister(uint16_t reg, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); 426 | void WriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); 427 | uint8_t WriteCommand2(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); 428 | void ReadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy = true); 429 | }; 430 | 431 | 432 | #endif 433 | --------------------------------------------------------------------------------