Closed lybgo closed 3 years ago
@lybgo I would love to help, but I do not have an ESP32 C3, so it is very difficult to do tests.
My guess: The examples are outdated and what is shown here is bad practice. Sorry, but I didn't find time to write something better.
All the callbacks for LoRa are triggered from an timer interrupt, and within timer interrupt handlers we should not do lengthy code, but instead use semaphores or flags to inform the main task about the event and handle it there.
Another potential problem is that the code is based on the ESP32's which are dual core MCU's. The library is running a task in the background, controlled by the IRQ of the SX1262 transceiver. There could be a problem as well.
@lybgo
Can you try to enable the debug output of the library. If you are using ArduinoIDE, you have to open the file src/sx126x-debug.h
and change the line 18 to #define LIB_DEBUG 1
. This will give additional debug output from the library.
I just found that you are connecting a Semtech LLCC68 . I have no idea if this chip is the same as SX1262. My library is written for the SX1262 and I cannot say if it can work with the LLCC68.
@beegee-tokyo
The only difference between LLCC68 and SX1262 is that the SF range of LLCC68 is 5~9, and the others are the same
Maybe, I do not know that module.
Can you try to enable the debug output of the library. If you are using ArduinoIDE, you have to open the file src/sx126x-debug.h and change the line 18 to #define LIB_DEBUG 1. This will give additional debug output from the library.
I guess you checked this part of the configuration:
hwConfig.CHIP_TYPE = SX1262_CHIP; // Example uses an eByte E22 module with an SX1262
hwConfig.PIN_LORA_RESET = PIN_LORA_RESET; // LORA RESET
hwConfig.PIN_LORA_NSS = PIN_LORA_NSS; // LORA SPI CS
hwConfig.PIN_LORA_SCLK = PIN_LORA_SCLK; // LORA SPI CLK
hwConfig.PIN_LORA_MISO = PIN_LORA_MISO; // LORA SPI MISO
hwConfig.PIN_LORA_DIO_1 = PIN_LORA_DIO_1; // LORA DIO_1
hwConfig.PIN_LORA_BUSY = PIN_LORA_BUSY; // LORA SPI BUSY
hwConfig.PIN_LORA_MOSI = PIN_LORA_MOSI; // LORA SPI MOSI
What about this part:
hwConfig.RADIO_TXEN = RADIO_TXEN; // LORA ANTENNA TX ENABLE
hwConfig.RADIO_RXEN = RADIO_RXEN; // LORA ANTENNA RX ENABLE
hwConfig.USE_DIO2_ANT_SWITCH = true; // Example uses an CircuitRocks Alora RFM1262 which uses DIO2 pins as antenna control
hwConfig.USE_DIO3_TCXO = true; // Example uses an CircuitRocks Alora RFM1262 which uses DIO3 to control oscillator voltage
hwConfig.USE_DIO3_ANT_SWITCH = false; // Only Insight ISP4520 module uses DIO3 as antenna control
These settings are a bit tricky, because each transceiver board is controlling the antenna switch and TCXO different. Can you send me a schematic of the LoRa transceiver board you are using?
And last, there is another setting that is not shown in the examples because most modules use DCDC
_hwConfig.USE_LDO = false;
But if your module is setup to use the LDO as internal power supply, you have to set this to true. Otherwise the transceiver will not work.
@beegee-tokyo I'll try #define LIB_DEBUG 1 later
@lybgo
Do you have an internal schematic of this module:
To define the correct functions in the library it is required to know:
Without this information, it will be difficult to control the transceiver and send and receive.
@beegee-tokyo I bought the LLCC68 module, and the merchant will not provide me with the schematic diagram
@beegee-tokyo I tried the following configuration,It doesn't make any difference.
hwConfig.USE_DIO3_TCXO = true / false;
hwConfig.USE_LDO = true / false;
My code looks like this:
#include <Arduino.h>
#include <SX126x-Arduino.h>
#include <SPI.h>
hw_config hwConfig;
// ESP32 - SX126x pin configuration
int PIN_LORA_RESET = 2; // LORA RESET
int PIN_LORA_DIO_1 = 3; // LORA DIO_1
int PIN_LORA_BUSY = 0; // LORA SPI BUSY
int PIN_LORA_NSS = SS; //7 LORA SPI CS
int PIN_LORA_SCLK = SCK; //4 LORA SPI CLK
int PIN_LORA_MISO = MISO; //5 LORA SPI MISO
int PIN_LORA_MOSI = MOSI; //6 LORA SPI MOSI
int RADIO_TXEN = -1; // LORA ANTENNA TX ENABLE
int RADIO_RXEN = -1; // LORA ANTENNA RX ENABLE
// Function declarations
void OnTxDone(void);
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
void OnTxTimeout(void);
void OnRxTimeout(void);
void OnRxError(void);
void OnCadDone(bool cadResult);
void sendPingPong(void);
// Define LoRa parameters
#define RF_FREQUENCY 433000000 // Hz
#define TX_OUTPUT_POWER 22 // dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]//比特率LLCC68 越小越慢越远
#define LORA_SPREADING_FACTOR 9 // [SF7..SF12]//扩频因子LLCC68 SF5..SF9 越大越慢越远
#define LORA_CODINGRATE 4 // [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]//编码率 越大冗余越多,越慢,越远
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx //前导码,用于睡眠唤醒
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 3000
#define TX_TIMEOUT_VALUE 3000
#define BUFFER_SIZE 64 // Define the payload size here
static RadioEvents_t RadioEvents;
static uint16_t BufferSize = BUFFER_SIZE;
static uint8_t RcvBuffer[BUFFER_SIZE];
static uint8_t TxdBuffer[BUFFER_SIZE];
static bool isMaster = true;
const uint8_t PingMsg[] = "PING";
const uint8_t PongMsg[] = "PONG";
time_t timeToSend;
time_t cadTime;
uint8_t pingCnt = 0;
uint8_t pongCnt = 0;
bool mIsConfirmDir = false;
void setup(){
// Define the HW configuration between MCU and SX126x
hwConfig.CHIP_TYPE = SX1262_CHIP; // Example uses an eByte E22 module with an SX1262
hwConfig.PIN_LORA_RESET = PIN_LORA_RESET; // LORA RESET
hwConfig.PIN_LORA_NSS = PIN_LORA_NSS; // LORA SPI CS
hwConfig.PIN_LORA_SCLK = PIN_LORA_SCLK; // LORA SPI CLK
hwConfig.PIN_LORA_MISO = PIN_LORA_MISO; // LORA SPI MISO
hwConfig.PIN_LORA_DIO_1 = PIN_LORA_DIO_1; // LORA DIO_1
hwConfig.PIN_LORA_BUSY = PIN_LORA_BUSY; // LORA SPI BUSY
hwConfig.PIN_LORA_MOSI = PIN_LORA_MOSI; // LORA SPI MOSI
hwConfig.RADIO_TXEN = RADIO_TXEN; // LORA ANTENNA TX ENABLE
hwConfig.RADIO_RXEN = RADIO_RXEN; // LORA ANTENNA RX ENABLE
hwConfig.USE_DIO2_ANT_SWITCH = true; // Example uses an CircuitRocks Alora RFM1262 which uses DIO2 pins as antenna control
hwConfig.USE_DIO3_TCXO = false; // Example uses an CircuitRocks Alora RFM1262 which uses DIO3 to control oscillator voltage
hwConfig.USE_DIO3_ANT_SWITCH = false; // Only Insight ISP4520 module uses DIO3 as antenna control
hwConfig.USE_LDO = false;
// Initialize Serial for debug output
Serial.begin(115200);
Serial.println("=====================================");
Serial.println("SX126x PingPong test");
Serial.println("=====================================");
Serial.println("MCU Espressif ESP32");
uint8_t deviceId[8];
BoardGetUniqueId(deviceId);
Serial.printf("BoardId: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
deviceId[7],
deviceId[6],
deviceId[5],
deviceId[4],
deviceId[3],
deviceId[2],
deviceId[1],
deviceId[0]);
// Initialize the LoRa chip
Serial.println("Starting lora_hardware_init");
lora_hardware_init(hwConfig);
// Initialize the Radio callbacks
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
RadioEvents.CadDone = OnCadDone;
// Initialize the Radio
Radio.Init(&RadioEvents);
// Set Radio channel
Radio.SetChannel(RF_FREQUENCY);
// Set Radio TX configuration
Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, TX_TIMEOUT_VALUE);
// Set Radio RX configuration
Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, false);
//return;
// Start LoRa
Serial.println("Starting Radio.Rx");
Radio.Rx(RX_TIMEOUT_VALUE);
timeToSend = millis();
}
uint16_t mCounter =0;
void loop() {
vTaskDelay(4000);
Serial.print(String("loop:")+mCounter);
mCounter++;
if(mIsConfirmDir == false){
sendPingPong();
}
}
void sendPingPong(void){
Radio.Standby();
if (isMaster) {
Serial.println(" Sending a PING");
// Send the next PING frame
TxdBuffer[0] = 'P';
TxdBuffer[1] = 'I';
TxdBuffer[2] = 'N';
TxdBuffer[3] = 'G';
} else {
Serial.println(" Sending a PONG");
// Send the reply to the PONG string
TxdBuffer[0] = 'P';
TxdBuffer[1] = 'O';
TxdBuffer[2] = 'N';
TxdBuffer[3] = 'G';
}
Radio.Send(TxdBuffer, 4);
vTaskDelay(2000);
Radio.Rx(RX_TIMEOUT_VALUE);
}
/**@brief Function to be executed on Radio Tx Done event
*/
void OnTxDone(void){
Serial.println("OnTxDone");
Radio.Rx(RX_TIMEOUT_VALUE);
}
/**@brief Function to be executed on Radio Rx Done event
*/
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr){
Serial.println("OnRxDone");
vTaskDelay(10);
BufferSize = size;
memcpy(RcvBuffer, payload, BufferSize);
Serial.printf("RssiValue=%d dBm, SnrValue=%d\n", rssi, snr);
for (int idx = 0; idx < size; idx++){
Serial.printf("%02X ", RcvBuffer[idx]);
}
Serial.println("");
mIsConfirmDir = true;
if (isMaster == true) {
if (BufferSize > 0) {
if (strncmp((const char *)RcvBuffer, (const char *)PongMsg, 4) == 0) {
Serial.println("Received a PONG in OnRxDone as Master");
// Wait 500ms before sending the next package
}
else if (strncmp((const char *)RcvBuffer, (const char *)PingMsg, 4) == 0) {
// A master already exists then become a slave
Serial.println("Received a PING in OnRxDone as Master");
isMaster = false;
}
vTaskDelay(1000);
sendPingPong();
}
}
else {
if (BufferSize > 0) {
if (strncmp((const char *)RcvBuffer, (const char *)PingMsg, 4) == 0) {
Serial.println("Received a PING in OnRxDone as Slave");
sendPingPong();
}
else // valid reception but not a PING as expected
{ // Set device as master and start again
Serial.println("Received something in OnRxDone as Slave");
isMaster = true;
Radio.Rx(RX_TIMEOUT_VALUE);
}
}
}
}
/**@brief Function to be executed on Radio Tx Timeout event
*/
void OnTxTimeout(void) {
// Radio.Sleep();
Serial.println("OnTxTimeout");
Radio.Rx(RX_TIMEOUT_VALUE);
}
/**@brief Function to be executed on Radio Rx Timeout event
*/
void OnRxTimeout(void) {
Serial.println("OnRxTimeout");
sendPingPong();
}
/**@brief Function to be executed on Radio Rx Error event
*/
void OnRxError(void){
Serial.println("OnRxError");
sendPingPong();
}
void OnCadDone(bool cadResult){
Serial.println("OnCadDone");
}
And logs:
[21:09:23.090]收←◆ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xd (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd6100,len:0x1428
load:0x403ce000,len:0xc04
load:0x403d0000,len:0x292c
SHA-256 comparison failed:
Calculated: 9f7363434bc7a1a2434ba3062500fa10b9fce5bb859899ee0424321b4ddaf742
Expected: 9b18b42e3e8e407f5e7b13f26c80172eda36d674c584e818f50843c766ebde69
Attempting to boot anyway...
entry 0x403ce000
I (48) boot: ESP-IDF v4.4-dev-2313-gc69f0ec32 2nd stage bootloader
I (49) boot: compile time 12:10:14
I (49) boot: chip revision: 3
I (49) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (55) qio_mode: Enabling default flash chip QIO
I (59) boot.esp32c3: SPI Speed : 80MHz
I (63) boot.esp32c3: SPI Mode : QIO
I (67) boot.esp32c3: SPI Flash Size : 4MB
I (71) boot: Enabling RNG early entropy source...
I (75) boot: Partition Table:
I (78) boot: ## Label Usage Type ST Offset Length
I (84) boot: 0 nvs WiFi data 01 02 00009000 00005000
I (91) boot: 1 otadata OTA data 01 00 0000e000 00002000
I (97) boot: 2 app0 OTA app 00 10 00010000 00140000
I (104) boot: 3 app1 OTA app 00 11 00150000 00140000
I (110) boot: 4 spiffs Unknown data 01 82 00290000 00170000
I (117) boot: End of partition table
I (120) boot_comm: chip revision: 3, min. application chip revision: 0
I (126) esp_image: segment 0: paddr=00010020 vaddr=3c030020 size=083f0h ( 33776) map
I (139) esp_image: segment 1: paddr=00018418 vaddr=3fc8a800 size=014dch ( 5340) load
I (142) esp_image: segment 2: paddr=000198fc vaddr=40380000 size=0671ch ( 26396) load
I (153) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=2568ch (153228) map
I (178) esp_image: segment 4: paddr=000456b4 vaddr=4038671c size=04094h ( 16532) load
I (181) esp_image: segment 5: paddr=00049750 vaddr=50000000 size=00010h ( 16) load
I (185) boot: Loaded app from partition at offset 0x10000
I (187) boot: Disabling RNG early entropy source...
=====================================
SX126x PingPong test
=====================================
MCU Espressif ESP32
BoardId: 00-00-E8-1A-C2-A1-DF-7C
Starting lora_hardware_init
<BRD> SyncWord = 0000
[21:09:23.370]收←◆Starting Radio.Rx
<RADIO> RX window timeout = 3000
[21:09:27.368]收←◆loop:0 Sending a PING
[21:09:29.368]收←◆<RADIO> RX window timeout = 3000
[21:09:33.389]收←◆loop:1 Sending a PING
[21:09:35.373]收←◆<RADIO> RX window timeout = 3000
[21:09:39.377]收←◆loop:2 Sending a PING
[21:09:41.379]收←◆<RADIO> RX window timeout = 3000
[21:09:45.383]收←◆loop:3 Sending a PING
[21:09:47.383]收←◆<RADIO> RX window timeout = 3000
@lybgo This debug output
<BRD> SyncWord = 0000
tells me that the communication with the LoRa transceiver is not working. The sync word should be 0x2414 or 0x4434
Something is wrong with the SPI communication. SPI is initialized as
SPI_LORA.begin(hwConfig.PIN_LORA_SCLK, hwConfig.PIN_LORA_MISO, hwConfig.PIN_LORA_MOSI, hwConfig.PIN_LORA_NSS);
Can you double check that your pin settings in the struct hwConfig are correct. Maybe replace the SS, SCK, MOSI, MISO
with the GPIO numbers of your ESP C3 breakout board.
@beegee-tokyo Wiring is sure to be fine. I tried to use "RadioLib" library, is able to communicate successfully. My code looks like this:
/*
RadioLib SX126x Transmit Example
This example transmits packets using SX1262 LoRa radio module.
Each packet contains up to 256 bytes of data, in the form of:
- Arduino String
- null-terminated char array (C-string)
- arbitrary binary data (byte array)
Other modules from SX126x family can also be used.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#define RADIOLIB_VERBOSE
#include <RadioLib.h>
// SX1262 has the following connections:
// NSS pin: 7
// DIO1 pin: 3
// NRST pin: 2
// BUSY pin: 0
SX1262 radio = new Module(SS, 3, 2, 0);
void setup() {
Serial.begin(115200);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
int state = radio.begin(434.0,125.0,9,7,SX126X_SYNC_WORD_PRIVATE,22,8,0.0,true);
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// some modules have an external RF switch
// controlled via two pins (RX enable, TX enable)
// to enable automatic control of the switch,
// call the following method
// RX enable: 4
// TX enable: 5
/*
radio.setRfSwitchPins(4, 5);
*/
}
uint16_t mCounter = 0;
void loop() {
Serial.print(F("[SX1262] Transmitting packet ... "));
mCounter++;
// you can transmit C-string or Arduino string up to
// 256 characters long
// NOTE: transmit() is a blocking method!
// See example SX126x_Transmit_Interrupt for details
// on non-blocking transmission method.
String str("hilyb:");
str = str + mCounter;
int state = radio.transmit(str.c_str());
// you can also transmit byte array up to 256 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);
*/
if (state == ERR_NONE) {
// the packet was successfully transmitted
Serial.println(F("success!"));
// print measured data rate
Serial.print(F("[SX1262] Datarate:\t"));
Serial.print(radio.getDataRate());
Serial.println(F(" bps"));
} else if (state == ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
Serial.println(F("too long!"));
} else if (state == ERR_TX_TIMEOUT) {
// timeout occured while transmitting packet
Serial.println(F("timeout!"));
} else {
// some other error occurred
Serial.print(F("failed, code "));
Serial.println(state);
}
// wait for a second before transmitting again
delay(1000);
}
Logs:
[22:05:15.844]收←◆[SX1262] Transmitting packet ...
[22:05:16.014]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:17.014]收←◆[SX1262] Transmitting packet ...
[22:05:17.195]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:18.188]收←◆[SX1262] Transmitting packet ...
[22:05:18.360]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:19.359]收←◆[SX1262] Transmitting packet ...
[22:05:19.530]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:20.534]收←◆[SX1262] Transmitting packet ...
[22:05:20.705]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:21.704]收←◆[SX1262] Transmitting packet ...
[22:05:21.875]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:22.879]收←◆[SX1262] Transmitting packet ...
[22:05:23.051]收←◆success!
[SX1262] Datarate: 567.35 bps
[22:05:24.049]收←◆[SX1262] Transmitting packet ...
[22:05:24.219]收←◆success!
[SX1262] Datarate: 567.35 bps
I cannot help you to solve it. I do not have the ESP32-C3 and I do not have this Semtech transceiver. From the logs, all I can say is that the communication between the two is not working.
If it works with RadioLib and you do not need LoRaWAN I propose you use that library.
@lybgo , did you manage to solve the issue - to run LLCC68 with SX126x-Arduino library..?
@beegee-tokyo , I don't think the problem is caused by ESP32-C3... I have the same problem even with "normal" ESP32 WROOM module. I use LLCC68 (that in the Ebyte E220-400M30S module) and examples don't work. Any plans for official support for LLCC68..?
@valioiv I am using the "RadioLib" library and can communicate normally. Later, I found that my LLCC68 module adapted to the frequency band of 410MHz~525MHz, which was 868MHZ in the current test with the "SX126X-Arduino" library. Maybe this problem caused the communication failure, I did not continue the test
@valioiv I have no plans to add support for LLCC68. I do not have this LoRa transceiver and cannot test anything.
You are welcome to submit a pull request if you can get it to work.
ESP32-C3 is a cost-effective, RISC-V-based MCU with Wi-Fi and Bluetooth 5 (LE) connectivity for secure IoT applications. The ESP32-C3 is a chip recently released by Espressif
When I run the following code, only the logs in the setup() and loop() methods have any output. The logs in other methods such as OnRxTimeout() have no output. I tried two C3 development boards and two LLCC68 modules.Can you help me see what's wrong?
log: