nRF24 control gone wrong

Had this pair of sketches working on a previous project just fine. Now making another one (and since changed computer so libraries & drivers may have gone awol) and it just doesn’t work.

compiles and uploads no problem. Serial Monitoring the TX its correctly generating a value and reporting it as sent. Serial monitoring the RX it’s constantly reporting the received (and “position”) value as 0 and so the servo doesn’t get moved. Interestingly even if the TX isn’t powered up the RX doesn’t present the error message about loosing connection so i’m completely lost

I’ve spent a morning playing around with this and just can’t work out what i’ve screwed up so hoping someone can spot a stupid mistake i’ve made?

Both units are RF nano’s (nano with built in nRF24 hardwear) with a slide potentiometer on the TX and a simple servo on the RX. Have already tested all the physical components and they work fine (run servo sweep, etc) so it’s definitely something in the code.

// TX CODE

#include "SPI.h"

#include "RF24.h"

#include "nRF24L01.h"

#define CE_PIN 9

#define CSN_PIN 10

RF24 radio(CE_PIN, CSN_PIN);

const byte address[6] = "00001";

//NRF24L01 buffer limit is 32 bytes (max struct size)

struct payload {

byte pot;

};

payload payload;

int previousPotValue = 0;

void setup()

{

cli();  // This next section of code is timing critical, so interrupts are disabled

// Start the timed Sequence for configuring the clock prescaler

CLKPR = 0x80;

CLKPR = 0x01;

sei();        // Enable interrupts

Serial.begin(115200);

radio.begin();

//Append ACK packet from the receiving radio back to the transmitting radio

radio.setAutoAck(true); //(true|false)

//Set the transmission datarate

radio.setDataRate(RF24_1MBPS); //(RF24_250KBPS|RF24_1MBPS|RF24_2MBPS)

//Greater level = more consumption = longer distance

radio.setPALevel(RF24_PA_HIGH); //(RF24_PA_MIN|RF24_PA_LOW|RF24_PA_HIGH|RF24_PA_MAX)

//Default value is the maximum 32 bytes

radio.setPayloadSize(sizeof(payload));

//Act as transmitter

radio.openWritingPipe(address);

radio.stopListening();

}

void loop()

{

payload.pot = map(analogRead(A0), 0, 1024, 0, 90);  //read the pot, map value to servo needs

if (abs(previousPotValue - payload.pot) >3) {

radio.write(&payload, sizeof(payload));

Serial.print("Pot Value:");

Serial.println(payload.pot);

Serial.println("Sent");

previousPotValue = payload.pot;

delay(10); //interval of transmition

}

}


//RX CODE

#include "SPI.h"

#include "RF24.h"

#include "nRF24L01.h"

#include <VarSpeedServo.h>

VarSpeedServo servo;

#define CE_PIN 9

#define CSN_PIN 10

#define INTERVAL_MS_SIGNAL_LOST 1000

#define INTERVAL_MS_SIGNAL_RETRY 250

RF24 radio(CE_PIN, CSN_PIN);

const byte address[6] = "00001";

//NRF24L01 buffer limit is 32 bytes (max struct size)

struct payload {

byte pot;

};

payload payload;

unsigned long lastSignalMillis = 0;

void setup() {

cli();  // This next section of code is timing critical, so interrupts are disabled

// Start the timed Sequence for configuring the clock prescaler

CLKPR = 0x80;

CLKPR = 0x01;

sei();  // Enable interrupts

Serial.begin(115200);

servo.attach(2);

radio.begin();

//Append ACK packet from the receiving radio back to the transmitting radio

radio.setAutoAck(true);  //(true|false)

//Set the transmission datarate

radio.setDataRate(RF24_1MBPS);  //(RF24_250KBPS|RF24_1MBPS|RF24_2MBPS)

//Greater level = more consumption = longer distance

radio.setPALevel(RF24_PA_HIGH);  //(RF24_PA_MIN|RF24_PA_LOW|RF24_PA_HIGH|RF24_PA_MAX)

//Default value is the maximum 32 bytes1

radio.setPayloadSize(sizeof(payload));

//Act as receiver

radio.openReadingPipe(0, address);

radio.startListening();

}

void loop() {

delay(2);

unsigned long currentMillis = millis();

if (radio.available() > 0) {

radio.read(&payload, sizeof(payload));

Serial.print("received: ");

Serial.println(payload.pot);



if (payload.pot <= 200) {

  servo.write(payload.pot, 200, false);  //moving servo according to pot

}



else {

  Serial.println("WARNING - ERRONEOUS Position (not written to Servo)");

}

Serial.print("Position: ");

Serial.println(payload.pot);

}

lastSignalMillis = currentMillis;

if (currentMillis != 0 && currentMillis - lastSignalMillis > INTERVAL_MS_SIGNAL_LOST) {

lostConnection();

}

}

void lostConnection() {

Serial.println("We have lost connection, preventing unwanted behavior");

delay(INTERVAL_MS_SIGNAL_RETRY);

}

It would make reading the code easier if you did an Auto Format, and get rid of the blank lines where appropriate.
Did you change IDE from 1.x to 2.x?

In order to do this kind of TX -> RX you need two processes running. EXACTLY how did you do that. What OS, What IDE, What command for the first process and the second process?

Yes i think my old PC was running 1.x and the new one is definitely running IDE 2.3.6.

I don’t understand your question about “processes running” This pair of sketches worked last time i used them 10 months ago so everything it needs should be here in the code?

why do you do this?

I am not a coder, i don’t “understand” any of this, i get sketches by cut-n-pasting, testing, tweaking and fumbling my way through. This was something to do with the nano’s i had running at a weird speed and this was the recommended way to correct for that?

Are you going to answer post 3?

i thought i had in #4 - I don’t understand what you mean by “processes running” - last time I uploaded these sketches all this worked so I can’t even comprehend what you think i have missed out?

You did not. I still dont know what OS, but I do know which IDE.
Correct me if I am wrong, but you are runing one process with the transmitter sketch, and a second process with the receiver sketch running. If the word process is throwing you that is the same as having a word document open in one process and a web browser in another.
That is very difficult to do with IDE 1.x, but easy and very different with IDE 2.x
If you tell us how with IDE 2.x you are able to have two sketches running with two serial monitors on screen at once you will be helping. I woud ask you how you did that in IDE 1.x but I get the hint you have a bad memory, so just show us a full screen grab of two serial monitors each resized to half width so you can see two on one screen. Is that clear?

I don't understand your question there.

OP has two Nano with built in nRF24 capability and loads the TX Code on one, the RX code on the other. The Nano with the TX code has a joystick connected to A0 and you collect the value from that pot, which is sent over to the Nano with the RX code which uses that value to drive a servo.

I don't get what you mean by OS, process etc... ???

1 Like

The procedure for running two processes at the same time is different by OS and by IDE. It's actually easier in 2.x.

I’m not doing whatever it is you think i’m doing
As previous poster says i’ve got 2 RF nano’s running 2 sketches nothing more, nothing less.

My PC is running windows 11 but i don’t see what that has to do with the nano’s as they are running arduino

Do you mean to explain to OP how to use the IDE to be able to open two Serial monitors ?

As you can see OP has that under control - he gets feedback from both Arduinos

and you don't need the IDE for that - just use coolTerm or any Serial terminal

try getting rid of those lines then. May be they are needed for your non standard Arduino Nano (I've never used one with builtin nRF24 capability. Kinda cool. Where did you get that from ?)

@tommoore I give up. Good luck.

I’ve taken those lines out and its not made any apparent difference.

Scrolling back through emails there was some non-standardisation in RF nano’s and that code was what was needed to bring the ones i had at the time to cooperate.

They are all over amazon / aliexpress etc. A nano with the nRF24 stuff built in - about 1cm longer and more expensive but a nice all in one solution for these “simple” remote control situations

to be fair to @tommoore your question feels irrelevant this time...

see RF nano setup [Solved] - #2 by Robin2

seems someone got some code to work. You should try that out and then adjust for your needs.

I recall Bill over at DroneBot Workshop making a video involving two boards with some kind of radio (BT, WiFi, 433 etc) and in order to see the separate Serial monitors on my Mac I used this command

open -n /Applications/Arduino.app

to get two separate processes in IDE 1.x.
In IDE 2.x it should only be necessary to dbl click twice or you can still use the open new as above.
My questions were designed to find out what was different between then and now. If he runs the same sketches and the only thing different is the IDE then something in the IDE is affecting it. For me the big mystery is it's easy now in IDE 2, it was a power user secret in IDE 1.x
Do you now understand my line of questioning?

I understand what you are trying to say, but it is not what the OP is asking for. It's totally unrelated. The IDE does not run the code, we are not even sure OP is using the IDE's serial terminal to show the messages. We just know he can see the messages from both Arduinos.

What might have changed from the past is the core for the Nano or the nRF24L01 library.

well - having twice the same process running and possibly messing with the preferences in parallel is not a great idea... It's not because you can run the same app multiple times this way that it should be recommended.

When I've a need for multiple Arduinos connected to my Mac, I just open multiple windows in coolTerm and I don't mess around with the IDE's built-in terminal.