when using rfm9x to transfer sensor data to another rfm9x to forward to AIO, I have observed something strange.
EDIT 4/14/2022
Throughout working this issue myself, I have found some interesting things.
- The corruption is limited to the flag position of the header. There is never another place in the package that is corrupted.
- The transmit is done using CRC enabled, and 'with header' so ACK should be working. I never receive a 'no ack' unless the receiver program is not running or the radios are too far apart.
- Could it be that the CRC and ACK are limited to the payload and not the entire packet?
- The program worked better when I did not use asyncio. I needed a way to keep the data acquisition going because I needed nearly continuous monitoring of the wind speed. I worked this into the program using asyncio, but failures began to get worse.
- Not only is the flag byte the only one that gets corrupted, it is always (I think) corrupted the same way. For example, if rfm9x.flags is set to 5, and the flag byte gets corrupted, this is what it looks like in hex.
Received raw packet: ['0x2', '0x3', '0x5e', '0x45', '0x31', '0x2e', '0x34', '0x33']
Note that the fourth byte has the value of 0x45, which is the insertion of the number 4 before the flag value of 5. Every corrupt flag is the same, the flag value is preceded by a 4.
several examples: corrupted byte /
Received raw packet: ['0x2', '0x3', '0x64', '0x42', '0x39', '0x39', '0x36', '0x2e', '0x32']
Received raw packet: ['0x2', '0x3', '0x56', '0x42', '0x39', '0x39', '0x36', '0x2e', '0x33']
Received raw packet: ['0x2', '0x3', '0x3e', '0x45', '0x32', '0x2e', '0x31', '0x34']
Received raw packet: ['0x2', '0x3', '0x19', '0x43', '0x35', '0x30', '0x2e', '0x31', '0x33']
Received raw packet: ['0x2', '0x3', '0x11', '0x43', '0x34', '0x39', '0x2e', '0x36', '0x34']
Received raw packet: ['0x2', '0x3', '0xf7', '0x43', '0x34', '0x38', '0x2e', '0x33', '0x31']
Received raw packet: ['0x2', '0x3', '0xf3', '0x44', '0x34', '0x2e', '0x34', '0x31']
Received raw packet: ['0x2', '0x3', '0xf1', '0x43', '0x34', '0x38', '0x2e', '0x39', '0x32']
The above examples were the output of the following code
elif flag != 1 or 2 or 3 or 4 or 5 or 6: print("Received raw packet:", [hex(x) for x in packet[:]])
I am attempting to use rfm9x.flags as a way to distinguish up to 6 different streams of sensor data. Since these packets were corrupted in the flag byte, they get printed out at the end.
here are sections of code that are t
while True:
temperature = (bme280.temperature)
temperature=str(temperature)
rfm9x.flags=1
print(rfm9x.flags, temperature)
if not rfm9x.send_with_ack(temperature.encode("utf-8")):
#ack_failed_counter += 1
print(" No Ack T: ", ack_failed_counter)
time.sleep(1)
await asyncio.sleep(interval)
async def get_pressure(interval):
while True:
pressure = (bme280.pressure)
pressure = str(pressure)
rfm9x.flags=2
print(rfm9x.flags, pressure)
#time.sleep(.1)
if not rfm9x.send_with_ack(pressure.encode("utf-8")):
#ack_failed_counter += 1
print(" No Ack T: ", ack_failed_counter)
time.sleep(1)
await asyncio.sleep(interval)
the serial monitor then prints:
1 24.8129
2 997.658
When the receiver gets these packets however, using the following pertinent section of code:
while True:
# Look for a new packet: only accept if addresses to my_node
packet = rfm9x.receive(with_ack=True, with_header=True)
# If no packet was received during the timeout then None is returned.
if packet is not None:
flag=packet[3]
print(flag)
print("received (raw bytes):{0}".format(packet))
if flag==1:
print(flag)
temperature = str(packet[4:], "utf-8")
temperature = (float(temperature)*1.8 + 32)
temperature=round(temperature, 2)
print("temperature = ", temperature, "F")
#print("Received RSSI: {0}".format(rfm9x.last_rssi))
if adafruit.is_active:
aio.send(temperature_feed.key, str(temperature))
else:
print("wifi not ready")
if flag==2:
print(flag)
pressure = str(packet[4:], "utf-8")
print("pressure = ", pressure, "mB")
#print("Received RSSI: {0}".format(rfm9x.last_rssi))
if adafruit.is_active:
aio.send(pressure_feed.key, str(pressure))
else:
print("wifi not ready")
The serial monitor then prints the following:
1
received (raw bytes):bytearray(b'\x02\x01\x02\x0124.8129')
1
temperature = 76.66 F
66
received (raw bytes):bytearray(b'\x02\x01\x03B997.658')
the first packet received is correct in that the four byte header contains the appropriate information, 02= this node, 01 = sending node, x02 is an 'identifier' and the fourth is x01, meaning the flag was set and received as 1.
The second packet was sent with rfm9x.flags = 2 (shown above in the serial output)
but the received flag was printed as '66' and thus missed by the "if rfm9x.flags ==2 test and pases through without sending the data on to AIO. Note that the payload 997.658 is correct.
This is one example. The CRC is enabled, and the 'with header' is enabled. there is no 'no ack' sent back to the sending node. This I assume means that the header was received, correctly? But parsed or decoded incorrectly.
I really need to be able to use the rfm9x.flags in the header to filter and sort the 6 different data streams I am using (only showed 1,2)
I do not know if this is due to using asyncio and really typing up the processor (RPI PICO), or if it may be a hardware issue.
One final thing. The error is not always on the same flagged packets, meaning sometime flag=2 is passed and parsed correctly. However, the failure is not random, the payload with flags = 2 is corrupted much more frequently.
Any help would be appreciated.