Closed skywodd closed 1 year ago
I was able to confirm this behavior, using Arduino Uno and 2 SX1278 transceivers. Rolling back to 4.3.0, everything started working correctly again, so the issue was introduced somewhere between 4.3.0 and 4.4.0. Tracking further, I narrowed it down to changes in #282. Finally, I got it down to the call to setAFCAGCTrigger()
in beginFSK
.
There are 4 possible AFC/AGC trigger configurations, I tried them all in 4.4.0 and here are the results:
SX127X_RX_TRIGGER_BOTH
- causes only one packet received per 2 packets sent (this is the one used in current master).SX127X_RX_TRIGGER_PREAMBLE_DETECT
- same behavior as SX127X_RX_TRIGGER_BOTH
SX127X_RX_TRIGGER_RSSI_INTERRUPT
- all packets are receivedSX127X_RX_TRIGGER_NONE
- all packets are receivedI'm not sure what exactly is the root cause here. I tried using SX127X_RX_TRIGGER_RSSI_INTERRUPT
to fix the primary issue, and that worked in 4.4.0, but stopped working at all in 5.0.0. I think that's because the bitrate/freqeuncy deviation changed in 5.0.0 from 48k/50kHz to 4k8/5kHz, while the Rx bandwidth remained the same at 125 kHz. To get thinkgs working reliably, I had to both disable AFC and use the RSSI interrupt trigger (which is honestly pretty weird).
I'll use SX127X_RX_TRIGGER_RSSI_INTERRUPT
with setAFC(false)
to fix the primary issue, but it would be good to know why are some AFC triggers only working once per every two packets. It's worth mentioning that the delay between packets doesn't matter, it looks like the first packet received triggers something that prevents the SX127x from receiving the next one.
@yeckel since you were the one to implement this feature (and the SX127X_RX_TRIGGER_BOTH
was used in your PR), do you have any idea what might be causing this behavior?
Thanks for the workaround, it's working perfectly.
Just out of curiosity, I've read the AFC chapter of the data sheet (and errata), but I don't see anything which can explain a (perfect) 50% packet lost. It's a very strange (hardware?) bug.
@skywodd I'm guessing one could try asking around on Semtech dev forums, if this is a known limitation or some misunderstanding of the AFC functionality on our part.
I will keep the workaround (i.e. disabled AFC, as it was pre-4.4.0) until we can figure out what's going on here.
I confirm the same behavior with lora esp32 board. Only one packet other two is received with the code above.
I have analyzed the signal received by an rtlsdr with urh (universal radio hacker) and it seems every packet is good but that the checksum is alternating correct/incorrect. When resetting the device between to transmission every packet has the correct checksum and is received.
transmitted data : ascii "ABCD" and 5th is an incrementing counter f2,f3,f4,...
@parlotto that's an interesting observation - looks like the last bit of the packet got flipped, from 1 to 0 - or perhaps the packet was terminated prematurely?
Is this happening with the latest release, or did you do some changes to the AFC/AGC triggers?
@jgromes I use the code out of the box downloaded from github a few weeks ago. I will try again with the official latest release.
@jgromes now tested with 5.2.0 release : same behavior. SX1278 chip ver 18 I suspect the problem is on the tx side. After every reset of the tx the first packet (byte[4]=0) is always received here is my code :
#include <RadioLib.h>
//TX
// SX1278 has the following connections:
// NSS pin: 18
// DIO0 pin: 26
// RESET pin: 23
// DIO1 pin: 33
SX1278 radio = new Module(18, 26, 23, 33);
volatile float freq = 434.0; //MHz
volatile unsigned int counter = 0;
void initFSK() {
// initialize SX1278 with default settings
Serial.print(F("[SX1278] Initializing ... "));
// freq, br, fDev, rxBw, power, preambLen, ook
int state = radio.beginFSK(freq, 2.4, 75.0, 125.0, 20, 64, false);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
Serial.print("SX1278 ver: ");
Serial.println(radio.getChipVersion());
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67};
state = radio.setSyncWord(syncWord, 4);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Unable to set configuration, code "));
Serial.println(state);
while (true);
}
radio.setDataShaping(RADIOLIB_SHAPING_0_5);
}
void setup() {
Serial.begin(115200);
initFSK();
}
// A B C D
byte byteArr[5] = {0x41, 0x42, 0x43, 0x44, 0x00};
void loop() {
int state = radio.transmit(byteArr, sizeof(byteArr));
Serial.print(byteArr[4]);
byteArr[4]++;
if (state == RADIOLIB_ERR_NONE) {
// the packet was successfully transmitted
Serial.println(F(", success!"));
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
Serial.println(F("too long!"));
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
// timeout occurred 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);
}
#include <RadioLib.h>
//RX
// SX1278 has the following connections:
// NSS pin: 18
// DIO0 pin: 26
// RESET pin: 23
// DIO1 pin: 33
SX1278 radio = new Module(18, 26, 23, 33);
volatile float freq = 434.0 ;//MHz
volatile bool receivedFlag = false;
volatile bool enableInterrupt = true;
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void IRQ_flag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void initFSK() {
// initialize SX1278 with default settings
Serial.print(F("[SX1278] Initializing ... "));
// freq, br, fDev, rxBw, power, preambLen, ook
int state = radio.beginFSK(freq, 2.4, 75.0, 125.0, 20, 64, false);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
Serial.print("SX1278 ver: ");
Serial.println(radio.getChipVersion());
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67};
state = radio.setSyncWord(syncWord, 4);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Unable to set configuration, code "));
Serial.println(state);
while (true);
}
radio.setDataShaping(RADIOLIB_SHAPING_0_5);
}
void setup() {
Serial.begin(115200);
initFSK();
// set the function that will be called
// when new packet is received
radio.setDio0Action(IRQ_flag);
int state = radio.startReceive();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("StartReceive success!"));
} else {
Serial.print(F("StartReceive failed, code "));
Serial.println(state);
while (true);
}
}
void loop() {
// check if the flag is set
if (receivedFlag) {
// reset flag
receivedFlag = false;
#define ARR_SIZE 5
// you can also read received data as byte array
byte byteArr[ARR_SIZE];
int len = 0; //= radio.getPacketLength(false);
int state = radio.readData(byteArr, ARR_SIZE);
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
//Serial.println(F("[SX1278] Received packet!"));
// print data of the packet
Serial.print("[SX1278] Data(");
Serial.print(len);
Serial.print("):");
//Serial.print(str);
for (int i = 0; i < sizeof(byteArr); i++) {
Serial.print(byteArr[i], HEX);
Serial.print(" ");
}
// print RSSI (Received Signal Strength Indicator)
Serial.print(F(", RSSI:"));
Serial.print(radio.getRSSI());
Serial.print(F(" dBm"));
// print SNR (Signal-to-Noise Ratio)
Serial.print(F(", SNR:"));
Serial.print(radio.getSNR());
Serial.print(F(" dB"));
// print frequency error
Serial.print(F(", Frequency error:"));
Serial.print(radio.getFrequencyError());
//Serial.print(radio.getAFCError());
Serial.print(F(" Hz"));
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Serial.print(F(", CRC error!"));
} else {
// some other error occurred
Serial.print(F(" Failed, code "));
Serial.println(state);
}
Serial.println();
// put module back to listen mode
radio.startReceive();
}
}
@parlotto what a rabbit hole you sent me down :)
I can confirm your code does indeed behave like this. Your point about the CRC got me interested - turns out that when CRC is disabled, the receiver gets the packet every time and every other packet seems to be a repeat of the previous one:
15:47:12.412 -> [SX1278] Data(0):41 42 43 44 9A , RSSI:-31.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
15:47:13.474 -> [SX1278] Data(0):41 42 43 44 9A , RSSI:-32.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
15:47:14.536 -> [SX1278] Data(0):41 42 43 44 9C , RSSI:-32.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
15:47:15.596 -> [SX1278] Data(0):41 42 43 44 9C , RSSI:-31.50 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
15:47:16.660 -> [SX1278] Data(0):41 42 43 44 9E , RSSI:-32.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
15:47:17.723 -> [SX1278] Data(0):41 42 43 44 9E , RSSI:-31.50 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
However, when I replaced the last byte in the packet sent by your code by a random(0xFF) | 0x1
, (which will add pseudo-random bytes and always set the last bit in the packet) something different started happening:
16:22:12.669 -> 3F, success!
16:22:13.729 -> 75, success!
16:22:14.792 -> 67, success!
16:22:15.852 -> 1B, success!
(...)
16:22:12.761 -> [SX1278] Data(0):41 42 43 44 3E , RSSI:-29.50 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
16:22:13.820 -> [SX1278] Data(0):41 42 43 44 74 , RSSI:-30.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
16:22:14.884 -> [SX1278] Data(0):41 42 43 44 66 , RSSI:-29.50 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
16:22:15.944 -> [SX1278] Data(0):41 42 43 44 1A , RSSI:-29.50 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
From this, it seems like the last bit is getting flipped to 0 - that's why it seems that in the previous example, even-numbered packets are being "received" twice. This also explaines why with CRC enabled, it seems like only every other packet is received - every CRC ending with a 1 bit will mismatch. By default, FIFO is cleared automatically when a CRC mismatch is detected, hence no packet.
So the ultimate question is why is the last bit not being sent or read correctly by the SX1278. It should be noted that this effect is random - sometimes it does see the correct bit at thte end of the packet. I then noticed you're using in your code quite strange bitrate/frequency deviation combination of 2400 bps with 75 kHz. Crunching the numbers, that gives a modulation index of 2*75/2.4 = 62.5, which is huge. IIRC from my signal processing class in university, higher modulation index means lower spectral effectivity - the most effective option, minimum shift keying, having a modulation index of 0.5.
So, I returned the values you had to the RadioLib defaults (4.8 kbps, 5.0 kHz), which happen to have modulation index of 0.48 and everything started working reliably, including the CRC:
17:04:47.085 -> [SX1278] Initializing ... success!
17:04:47.131 -> SX1278 ver: 18
17:04:47.131 -> 0, success!
17:04:48.193 -> 1, success!
17:04:49.209 -> 2, success!
17:04:50.274 -> 3, success!
17:04:51.288 -> 4, success!
17:04:52.349 -> 5, success!
17:04:53.364 -> 6, success!
17:04:54.380 -> 7, success!
17:04:55.443 -> 8, success!
(...)
17:04:47.162 -> [SX1278] Data(0):41 42 43 44 0 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:48.178 -> [SX1278] Data(0):41 42 43 44 1 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:49.240 -> [SX1278] Data(0):41 42 43 44 2 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:50.258 -> [SX1278] Data(0):41 42 43 44 3 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:51.319 -> [SX1278] Data(0):41 42 43 44 4 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:52.333 -> [SX1278] Data(0):41 42 43 44 5 , RSSI:-42.50 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:53.395 -> [SX1278] Data(0):41 42 43 44 6 , RSSI:-40.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:54.410 -> [SX1278] Data(0):41 42 43 44 7 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
17:04:55.428 -> [SX1278] Data(0):41 42 43 44 8 , RSSI:-41.00 dBm, SNR:0.00 dB, Frequency error:0.00 Hz
So in conclusion, if you want to send a 2400 bps signal, don't spread it over 150 kHz. I tried it with 4.8 kHz deviation and it works fine.
@jgromes Thank you for investigating this problem. Yes I admit 75kHz deviation is a way to much for 2400 b/s. I set this value to clearly distinguish the two symbols in URH. Then I forget to reset to the normal value. I have tried with (4.8 kbps, 5.0 kHz) and (2.4 kbps, 5.0 kHz) and I still have the same behavior : One packet received, and very often the next not. I was not able to find a value of FDEV that could give consistent result for 2400b/s baudrate for my devices. I have played a bit with FDEV et BAUDRATE and it start to work reliably at (9.6 kbps, 5.0 kHz) : every packet received. In the documentation : "No constraint applies to the modulation index of the transmitter, but the frequency deviation must be set between 600 Hz and 200 kHz." I think index should more than 1 to have reliable demodulation, the more the better (most reliable) at the price of the passband. (0.5 is a special case for GMSK coherent demodulation if I remember but I was able to have constant result at i=0.4 : (40kb/s ; 8 kHz)). POCSAG at 466MHz for example use large index to be very robust i=17,6 for 512b/s and the most common is i=7.5 at 1200b/s.
What is still strange to me is that I can't have good result at low speed whatever the index is.
EDIT : the documentation states "It is most efficient when the modulation index of the signal is greater than 0.5 and below 10" so 0.5 should be fine.
@parlotto unfortunately it seems like there is some issue with the last byte that is sent. In URH, I can see for low data rates that the last bit (if present) is a lot shorter than it should be, so I'm not sure if anything can be done on the library side. This definitely warrants further exploration. Couple of thoughts on areas that may be related:
@jgromes I have tested with version 4.3 :
To make my code work
state
after radio.startReceive()
otherwise it returns -16 error code.I confirm the same behavior at low speed. The problem arise under about 8 kb/s (at FDEV=5kHz). Changing FDEV seems no have no effect on the problem.
My main interest to be able to send at low speed is to be compatible with POCSAG 1200b/s.
@parlotto thanks for checking it out - then it seems like my original assesment was wrong and the AFC/AGC has nothing to do with the issue, or it only contributes to it and is not the root cause. In any case, this will require some digging.
I'm mainly curiuous now if the effect is gradual, or starts suddenly. For example, if there's a 100% success rate at 8 kbps and 50% at 7.9, then that would suggest some issue in bit rate configuration. If the success rate drops off gradually with decreasing bit rate, that would point more to something in the RF/demodulator chain not working correctly. I will try to get to the bottom of this (since I'm pretty curious myslef at this point), but can't guarantee I will have enough time to work exclusively on this.
@parlotto Have you tried the SX1276 Starter Kit software from Semtech? Maybe they implemented something that everyone is missing?
Use the GUI to set everything up and then export the pre configured registers. Normally this would only work for dev kits, but you can get around this: sx1276ska.exe -test
. Use the following key combinations to unlock features:
STRG + ALT + N - New View D = Debug T = Test Form P - LoRa related (dunno as i'm only interested in FSK...) B = Firmware Update (only found on RFMxx)
You can also use this on every other software from Semtech (like those for the RFMxx...). And since it's a .NET app you can easily dissect everything with dotPeek.
I know you traced the problem back to the low freq, but there is an errata for all SX12xx which mentions a broken CRC implementation:
if there's a 100% success rate at 8 kbps and 50% at 7.9
Can it be fixed by putting fractional part into register 0x5d?
@dernasherbrezon good idea - however, it seems to have no effect. The difference is actually very small (e.g., 2.40000375001 with fractional part, compared to 2.4000600015 without. which is a difference of 23 ppm). I implemented it just to scratch it off the TODO list.
The only way I can reliably trigger this problem is by using the bad AFC/AGC trigger. Without it, I can observe no significant packet loss, even with slightly different bitrates. So unless this issue can be confirmed by someone in new library releases, I will consider this resolved.
Bit flip can be caused by high SPI frequency. I did some analysis here.
Describe the bug When using an SX1276 module in FSK mode with all defaults settings (only frequency is set in
beginFSK()
), the DIO0 interrupt will only trigger half the time when a packet is sent.The hardware itself seem to be working properly, by replacing
beginFSK(868.3)
withbegin(868.3)
in both TX and RX sketch, everything work as expected in LoRa mode.To Reproduce
Test procedure:
Observed behavior:
readData()
orstartReceive()
.TX sketch :
RX Sketch :
Expected behavior An interrupt on DIO0 should be triggered after each packet is sent/received in FSK mode.
Additional info:
Debug mode output
Click to expand!
``` R 42 12 M SX127x R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R D 8 W D F R D F R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R 2 1A W 2 1A R 2 1A R 3 B W 3 A R 3 A R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R 4 0 W 4 0 R 4 0 R 5 52 W 5 51 R 5 51 R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R 13 B W 13 2 R 13 2 R 1 9 R D F W D F R D F R 1 9 R D F W D 1F R D 1F R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R 12 15 W 12 2 R 12 2 R 1 9 R 1 9 W 1 9 R 1 9 R B 2B W B 23 R B 23 R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R 25 0 W 25 0 R 25 0 R 26 3 W 26 2 R 26 2 R 1 9 R 27 93 W 27 93 R 27 93 R 27 93 W 27 91 R 27 91 W 28 12 AD R 1 9 R 30 90 W 30 90 R 30 90 R 33 0 W 33 0 R 33 0 R 34 0 W 34 0 R 34 0 R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R E 2 W E 2 R E 2 R E 2 W E 2 R E 2 R 1 9 R 30 90 W 30 90 R 30 90 R 1 9 R 30 90 W 30 90 R 30 90 R 32 40 W 32 40 R 32 40 R 10 FF W 10 FF R 10 FF W 3F 10 R 30 90 W 30 90 R 30 90 R 31 40 W 31 40 R 31 40 R 27 91 W 27 B1 R 27 B1 R 35 F W 35 8F R 35 8F R 35 8F W 35 8F R 35 8F R 20 0 W 20 0 R 20 0 R 21 0 W 21 0 R 21 0 R 22 0 W 22 0 R 22 0 R 1F 40 W 1F AA R 1F AA R 44 2D W 44 AD R 44 AD R 24 5 R 6 6C W 6 D9 R 6 D9 R 7 80 W 7 13 R 7 13 R 8 0 W 8 33 R 8 33 R 1 9 R 1 9 W 1 9 R 1 9 R 9 4F W 9 CF R 9 CF R 9 CF W 9 F8 R 9 F8 R 4D 84 W 4D 84 R 4D 84 R 1 9 R 1 9 R 1 9 W 1 9 R 1 9 R A 9 W A 9 R A 9 R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R 40 0 W 40 0 R 40 0 R 1 9 W 3E FF W 3F FF R 1 9 R 1 9 W 1 D R 1 C R 1 D R 1 D R 1 D W 1 9 R 1 9 R 1 9 R 0 8 R 30 90 R 0 1 23 45 67 89 AB CD EF R 1 9 W 3E FF W 3F FF Received packet! R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R 40 0 W 40 0 R 40 0 R 1 9 W 3E FF W 3F FF R 1 9 R 1 9 W 1 D R 1 C R 1 D R 1 D R 1 D W 1 9 R 1 9 R 1 9 R 0 8 R 30 90 R 0 1 23 45 67 89 AB CD EF R 1 9 W 3E FF W 3F FF Received packet! R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R 40 0 W 40 0 R 40 0 R 1 9 W 3E FF W 3F FF R 1 9 R 1 9 W 1 D R 1 C R 1 D R 1 D R 1 D W 1 9 R 1 9 R 1 9 R 0 8 R 30 90 R 0 1 23 45 67 89 AB CD EF R 1 9 W 3E FF W 3F FF Received packet! R 1 9 R 1 9 W 1 9 R 1 9 R 1 9 R 40 0 W 40 0 R 40 0 R 1 9 W 3E FF W 3F FF R 1 9 R 1 9 W 1 D R 1 C R 1 D R 1 D R 1 D W 1 9 R 1 9 R 1 9 R 0 8 R 30 90 R 0 1 23 45 67 89 AB CD EF R 1 9 W 3E FF W 3F FF ```