NRF24L01+ noisy data

Hello,
I want to transmit analog data (from an hall sensor) to another Arduino via an NRF24L01+ module. My problem is that the incoming data on the receiver is noisy and has some big spikes. Since I want to use the data to control an ESC it isn´t working. I already testet the data that is direcly coming from the hall sensor but that isn´t as noisy.
How do I fix this?

//Transmitter
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define hall_pin A3

const uint64_t pipeOut = 0xE8E8F0F0E1LL;  //Address to which data will be send

RF24 radio(9, 8);             //( CE , CSN )

void setup() {
  Serial.begin(9600);          //Setting baudrate of Serial Port to 9600
  pinMode(hall_pin,INPUT);
  radio.begin();                   //Activate the modem
  radio.setPALevel(RF24_PA_HIGH);
  radio.openWritingPipe(pipeOut);   //Sets the address of transmitter from which program will send the data
}

void loop() {
  radio.stopListening ();
  int value = analogRead(hall_pin);
  int data = map( value , 228 , 772 , 0 , 250 );
  
  Serial.println(data);
  radio.write(&data, sizeof(data));
}

//Receiver
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

RF24 radio(9,8);             //( CE , CSN )  

const uint64_t pipeIn = 0xE8E8F0F0E1LL; //Address from which data to be received

int Position;

Servo ESC;

void setup() {
Serial.begin(9600);            //Setting baudrate of Serial Port to 9600
radio.begin();                   //Activate the modem
radio.setPALevel(RF24_PA_LOW);
radio.openReadingPipe(1, pipeIn); //Sets the address of receiver from which program will receive the data
ESC.attach(5);
}

void loop() {
radio.startListening();

int rx_data = 0 ;
radio.read(&rx_data, sizeof(rx_data));

Serial.println(rx_data);
Position = map(rx_data, 248, 0, 180, 0);
ESC.write(Position);
delay(100);
}

How do you determine that? Data is ONLY 0 and 1 made into bytes. All digital, not analog which is what you are describing.

I have an hall sensor which is analog and sends out different values depending on how far the magnet is away from it. So the value send to the receiver is a value between 0 and 250. This value at the receiver is noisy and got some big spikes. So there is something happening in the transmition.

This module use 'a lot' of current while sending. It's smart to add a capacitor (10uF) to radio modules power supply pins.

I have already added 47μF capacitors to both.

Why do you use deprecated addressing (uint64_t)?

Does not belong into loop on transmit-only nodes.

It would be clever to moderate the packet frequency.

Does not belong into loop for a receive-only node.

Reading without checking for an available packet is not clever, and will inject many zeros.

There is no place for a delay in a receiving program.

1 Like

So I put the radio.startListening and radio.stopListening into void setup() but it did not change anything in the received numbers.

How do I do that? Iam new to coding...

I deleted it

  if (radio.available()) {
    int rx_data;
    radio.read(&rx_data, sizeof(rx_data));
    Serial.println(rx_data);
    Position = map(rx_data, 248, 0, 180, 0);
    ESC.write(Position);
  }

You are aware that map does not check any bounds?

Ok but the spikes are still there...

What is the new code, what is the output?

What Arduinos are you using?

If there are spikes in the received data, they are put there by the transmitter end. Look for the source of the spikes in your analog data and eliminate them at their source.

I cant upload pictures here but you can compare the transmitter values and the receiver values here: Album — Postimages

I don't watch pictures of code/output.

Print what you send, start with one or a couple of packets a second,
post the code and both results.

What Arduinos are you using?

Transmitter output:
123
124
123
123
124
125
124
123
124
123

Receiver output:
121
120
165
118
154
119
121
123
118
120

2 nanos

Transmitter code

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define hall_pin A3

const uint64_t pipeOut = 0xE8E8F0F0E1LL;  //Address to which data will be send

RF24 radio(9, 8);             //( CE , CSN )

void setup() {
  Serial.begin(9600);          //Setting baudrate of Serial Port to 9600
  pinMode(hall_pin,INPUT);
  radio.begin();                   //Activate the modem
  radio.setPALevel(RF24_PA_HIGH);
  radio.openWritingPipe(pipeOut);   //Sets the address of transmitter from which program will send the data
  radio.stopListening ();
}

void loop() {

  int value = analogRead(hall_pin);
  int data = map( value , 228 , 772 , 0 , 250 );
  
  Serial.println(data);
  radio.write(&data, sizeof(data));
} 

Receiver code

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

RF24 radio(9,8);             //( CE , CSN )  

const uint64_t pipeIn = 0xE8E8F0F0E1LL; //Address from which data to be received

int Position;

Servo ESC;

void setup() {
Serial.begin(9600);            //Setting baudrate of Serial Port to 9600
radio.begin();                   //Activate the modem
radio.setPALevel(RF24_PA_LOW);
radio.openReadingPipe(1, pipeIn); //Sets the address of receiver from which program will receive the data
radio.startListening();
ESC.attach(5);
}

void loop() {
if (radio.available()) {
    int rx_data;
    radio.read(&rx_data, sizeof(rx_data));
    Serial.println(rx_data);
    Position = map(rx_data, 248, 0, 180, 0);
    ESC.write(Position);
  }
}

The spikes are not there if I just analog.read(); the data at the transmitter but at the receiver they are there so I think its a problem with the wireless comunication.

Not possible to change the message text after it has been sent and before it has been received. Look for other reasons for the problem.

Hard to believe that not a single integer made it.

There is still no moderation of the packet frequency.

I would suggest changing the data format to a struct
that contains a packet number to identify the packets.

Something like this (uncompiled/untested)

struct Packet {
  uint id;
  int data;
  bool send(int value) {
    id++;
    data = value;
    return radio.write(this, sizeof(Packet);
  }
  void display() {
    Serial.print(id);
    Serial.print(F(": "));
    Serial.println(data);
  }
} dPack;

void loop() {
  static uint32_t lastSend;
  uint32_t currMillis = millis();
  if (currMillis - lastSend >= 1000) {
    lastSend = currMillis;
    dPack.send(map(analogRead(hall_pin), 228, 772, 0, 250));
    dPack.display();
  }
}

On the receiving side

struct Packet {
  uint id;
  int data;
  bool send(int value) {
    id++;
    data = value;
    return radio.write(this, sizeof(Packet);
  }
  void display() {
    Serial.print(id);
    Serial.print(F(": "));
    Serial.println(data);
  }
} dPack;

void loop() {
  if (radio.available()) {
    radio.read(&dPack, sizeof(Packet));
    dPack.display();
    // use dPack.data just like data before
  }
}

It's perfectly normal for a radio packet to be corrupted every now and then. I don't remember what is default mode of nRF24 library - it may not use CRC at all, or use a short one so corruption still can occur.
A simple way to check vs this case is to send a packet with, say, 5 numbers in it. On the receiver end, you should check if all 5 are equal - if yes, then almost certainly the packet is fine. If any of them is different from the others - the packet was corrupted and should be ignored (it's possible to send data with higher redundancy and extract actual value from corrupted packet, but due to the nature of this error, it's not really simple)

The default CRC is 16 bits over the full packet with 32 byte data part.

I see - then it's something else, with 16-bit CRC error may occur only once per close to 65k packets, OP clearly gets it more often