nRF24 / RF24

OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
https://nrf24.github.io/RF24
GNU General Public License v2.0
2.22k stars 1.02k forks source link

[Question] Check for corrupted data (RPi/Arduino) #767

Closed PCov3r closed 3 years ago

PCov3r commented 3 years ago

Hello, I'm using nrf24l01+PA+LNA modules to transmit data from arduino to raspberry. All works great, I receive data from arduino and print them on my raspberry.

If my arduino fails to transmit, it shows an error message. And if there is some lost data on the way, it shows the error too. But my raspberry, even if the data are corrupted, he still shows it.

I was wondering what would be the more effective/fastest way to check if received data got corrupted. I first thought about sending the sum of all variables and check on the receiver side if we get the same sum, but I don't know if it's a good idea.

Please, let me know what you think. Thanks !

Here are the two scripts :

Arduino

#include "printf.h"
#include "RF24.h"

RF24 radio(9, 10); // CE, CSN
const uint64_t pipeA = 0xF0F0F0F0E1LL;
const uint64_t pipeB = 0xF0F0F0F0D2LL;

typedef struct __attribute__((packed)) VALUES{
  float TempDHT = 9.0;
  uint16_t Pressure = 0;
  float TempBME = 2.0;
  uint16_t ir = 0;
  uint32_t  lux = 0;
  float UVA = 0.0;
  float UVB = 0.0;
  float UVI = 0.0;
  uint8_t HumDHT = 0;
  uint8_t HumBME = 0;
}
values;
values data;

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    // some boards need to wait to ensure access to serial over USB
  }

  printf_begin();
  radio.begin();
  radio.enableAckPayload();
  radio.enableDynamicPayloads();
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(pipeA);
  radio.openReadingPipe(1, pipeB);
  radio.stopListening();
  radio.printDetails();       // (smaller) function that prints raw register values

} // setup

void loop() {

    if (!radio.write( &data, sizeof(data) )){
        Serial.println(F("failed"));
     }
     delay(1000);

} // loop

RPi

#include <iostream>
#include <sstream>
#include <string>
#include <unistd.h>
#include <RF24/RF24.h>

RF24 radio(22,0);
const uint64_t pipeA = 0xF0F0F0F0E1LL;
const uint64_t pipeB = 0xF0F0F0F0D2LL;

int main(int argc, char** argv) {
  uint32_t debut;
  bool timeout;

typedef struct __attribute__((packed)) VALUES{
  float TempDHT = 9.0;
  uint16_t Pressure = 0;
  float TempBME = 10.0;
  uint16_t ir = 0;
  uint32_t  lux = 0;
  float UVA = 0.0;
  float UVB = 0.0;
  float UVI = 0.0;
  uint8_t HumDHT = 0;
  uint8_t HumBME = 0;
}
values;
values data;

  printf("Go go go!\n");

  radio.begin();
  radio.enableAckPayload();
  radio.enableDynamicPayloads();
  radio.setPALevel(RF24_PA_LOW);
  radio.openWritingPipe(pipeB);
  radio.openReadingPipe(1,pipeA);

  radio.printDetails();
  radio.startListening();
while(1) {

  radio.startListening();
  debut=millis();
  timeout = false;

  while(!radio.available()){
    if(millis()-debut > 800) {
      timeout=true;
      break;
    }
  }

  if(timeout) {
    printf("Erreur: timeout \n");
  } else {
    radio.read(&data, sizeof(data));
    printf("reponse: %f\n",data.TempBME);
  }
  sleep(1);
 }
return(0);
}
2bndy5 commented 3 years ago

I was wondering what would be the more effective/fastest way to check if received data got corrupted.

You automatically use CRC16 bit provided by the radio firmware. you could dedicate part of the payload to do a larger CRC scheme, and then reduce the radios builtin CRC to 8 bits (for better speed -- can't disable CRC when using ACK packets).

If I had to guess: one of your wires is loose or too long. Try lowering the SPI speed on the unit(s) experiencing currupted data.

RF24 radio(22, 0, 4000000); // uses 4MHz; defaults to 10MHz

I'm using nrf24l01+PA+LNA modules

Have you read the section about PA/LNA modules in our COMMON_ISSUES.md?

PCov3r commented 3 years ago

Thank you for your response.

I did all the things recommended in the common issues part. Think that's why I don't get that much corrupted data (something like 1/300 which is more than decent for my application).

My question was more about the receiver side. On the transmitter, I get "failed transmission" if the rpi didn't receive any data, or if the data got corrupted. But the RPi in itself doesn't know that he is copying corrupted data. radio.read() copy the data and it looks like sometimes there is a bit flipping.

Could be hardware related. But as the 2 modules are wrapped in electrical tape and tin foil inside antistatic bags + powered via an external power supply using adapters, I doubt it. In any case, as I plan to store the received data in a database, I would like to find a way to avoid copying these value with flipping bit.

I will try to change my configuration tomorrow, especially the power supply part and I'll tell you if it changes anything.

Thanks.

PCov3r commented 3 years ago

After a bit of trial and errors, the lowering of the SPI speed on RPi + changing to another channel did the trick !