Using RF-Nano's
TX has a 10k slide potentiometer attached to A0
RX has a servo attached to D2
TX sketch -
#include <SPI.h>
#include "RF24.h"
RF24 myRadio (9, 10);
struct package
{
int msg = 0;
};
byte addresses[][6] = {"0"};
typedef struct package Package;
Package data;
void setup()
{
Serial.begin(9600);
myRadio.begin();
myRadio.setChannel(115); //115 band above WIFI signals
myRadio.setPALevel(RF24_PA_MIN); // Power
myRadio.setDataRate( RF24_250KBPS ) ; //Minimum speed
delay(500);
Serial.print("Setup Initialized");
}
void loop()
{
int Read_ADC = analogRead(A0);
char servo_value = map (Read_ADC, 0, 1024, 0,180);
if (servo_value>1)
data.msg = servo_value;
WriteData();
delay(50);
// ReadData();
//delay(200);
}
void WriteData()
{
myRadio.stopListening(); //Stop Receiving and start transminitng
myRadio.openWritingPipe( 0xF0F0F0F0AA); //Sends data on this 40-bit address
myRadio.write(&data, sizeof(data));
Serial.print("\nSent:");
Serial.println(data.msg);
delay(30);
}
void ReadData()
{
myRadio.openReadingPipe(1, 0xF0F0F0F066); // Which pipe to read, 40 bit Address
myRadio.startListening(); //Stop Transminting and start Reveicing
if ( myRadio.available())
{
while (myRadio.available())
{
myRadio.read( &data, sizeof(data) );
}
Serial.print("\nReceived:");
Serial.println(data.msg);
}
}
RX Sketch -
#include <SPI.h>
#include "RF24.h"
#include <Servo.h>
Servo myservo;
RF24 myRadio (9, 10);
struct package
{
int msg;
};
typedef struct package Package;
Package data;
byte addresses[][6] = {"0"};
void setup()
{
Serial.begin(9600);
myRadio.begin();
myRadio.setChannel(115); //115 band above WIFI signals
myRadio.setPALevel(RF24_PA_MIN); //Power
myRadio.setDataRate( RF24_250KBPS ) ; //Minimum speed
myservo.attach(2);
Serial.print("Setup Initialized");
delay(500);
}
int Servo_value;
int Pev_servo_value;
void loop()
{
ReadData();
delay(50);
Pev_servo_value = Servo_value;
Servo_value = data.msg;
while (Pev_servo_value< Servo_value)
{
myservo.write(Pev_servo_value);
Pev_servo_value++;
delay(2);
}
while (Pev_servo_value> Servo_value)
{
myservo.write(Pev_servo_value);
Pev_servo_value--;
delay(2);
}
//data.msg = "nothing to send";
//WriteData();
// delay(50);
}
void ReadData()
{
myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Which pipe to read, 40 bit Address
myRadio.startListening(); //Stop Transminting and start Reveicing
if ( myRadio.available())
{
while (myRadio.available())
{
myRadio.read( &data, sizeof(data) );
}
Serial.print("\nReceived:");
Serial.println(data.msg);
}
}
void WriteData()
{
myRadio.stopListening(); //Stop Receiving and start transminitng
myRadio.openWritingPipe(0xF0F0F0F066);//Sends data on this 40-bit address
myRadio.write(&data, sizeof(data));
Serial.print("\nSent:");
Serial.println(data.msg);
delay(300);
}
Both compile and load ok.
Serial monitor on TX gives "Sent:" and a changing numeric value when potentiometer is adjusted
Serial monitor on RX gives "Setup initialised" and then nothing. Also (obviously) the servo doesn't move in response to transmitter.
What stupid mistake have i made here - all i want is a simple remote control single servo using the most compact setup possible.
kmin
March 30, 2025, 2:34pm
2
If you comment out all servo related code on receiver, does it work (receive)?
Your structs look wrong as does the test for data being available to send
Try this (untested)
//Tx
#include <SPI.h>
#include "RF24.h"
RF24 myRadio(9, 10);
struct package //only one struct needed
{
int msg = 0;
};
byte addresses[][6] = { "0" };
package data;
void setup()
{
Serial.begin(9600);
myRadio.begin();
myRadio.setChannel(115); //115 band above WIFI signals
myRadio.setPALevel(RF24_PA_MIN); // Power
myRadio.setDataRate(RF24_250KBPS); //Minimum speed
delay(500);
Serial.print("Setup Initialized");
}
void loop()
{
int Read_ADC = analogRead(A0);
char servo_value = map(Read_ADC, 0, 1024, 0, 180);
if (servo_value > 1) //added braces to ensure that data is sent only when available
{
data.msg = servo_value;
WriteData();
delay(50);
}
// ReadData();
//delay(200);
}
void WriteData()
{
myRadio.stopListening(); //Stop Receiving and start transminitng
myRadio.openWritingPipe(0xF0F0F0F0AA); //Sends data on this 40-bit address
myRadio.write(&data, sizeof(data));
Serial.print("\nSent:");
Serial.println(data.msg);
delay(30);
}
void ReadData()
{
myRadio.openReadingPipe(1, 0xF0F0F0F066); // Which pipe to read, 40 bit Address
myRadio.startListening(); //Stop Transminting and start Reveicing
if (myRadio.available())
{
while (myRadio.available())
{
myRadio.read(&data, sizeof(data));
}
Serial.print("\nReceived:");
Serial.println(data.msg);
}
}
with this new sketch i still get the same read-outs when monitoring the TX but now the RX initialises and displays "Received 14" and the red LED on the RX turns on.
no reaction from the servo
Forget the servo control for now
Is the receiver displaying the same value that is being sent by the transmitter ?
Why does the receiver need to check for a change in servo value rather than just writing what is received to the servo ?
the receiver just displays "Received 14" regardless of what the sent value was. after about 10 seconds the LED goes out and i can repeat the process, but it's always 14
No reason, i've got no instinct for sketch writing at all so i'm researching elements and building from other examples rather than conjuring the sketch from my head. I /just/ need to create a servo remote controlled by a potentiometer that works on RF-Nano boards.
Please post both sketches as they are now
I don't have any RF Nano boards but these sketches work with Nanos and external RF24 boards so try them first and report whether data is received
// SimpleTx - the master or the transmitter
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
//not all #defines used but here for documentation
#define CE_PIN 9
#define CSN_PIN 10
#define MOSI_PIN 11
#define MISO_PIN 12
#define SCK_PIN 13
const byte slaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
char txNum = '0';
struct data
{
byte pinState;
byte temperature;
} sentData;
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000;
void setup()
{
Serial.begin(115200);
Serial.println("SimpleTx Starting");
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.setRetries(3, 5); // delay, count
radio.openWritingPipe(slaveAddress);
}
void loop()
{
currentMillis = millis();
if (currentMillis - prevMillis >= txIntervalMillis)
{
sentData.pinState = !sentData.pinState;
sentData.temperature = sentData.temperature + 1;
send();
prevMillis = millis();
}
}
void send()
{
bool rslt;
rslt = radio.write( &sentData, sizeof(sentData) );
if (rslt)
{
Serial.println(" Acknowledge received");
}
else
{
Serial.println(" Tx failed");
}
}
// SimpleRx - the slave or the receiver
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
//not all #defines used but here for documentation
#define CE_PIN 9
#define CSN_PIN 10
#define MOSI_PIN 11
#define MISO_PIN 12
#define SCK_PIN 13
const byte thisSlaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};
RF24 radio(CE_PIN, CSN_PIN);
struct data
{
byte pinState;
int temperature;
} receivedData;
bool newData = false;
void setup()
{
Serial.begin(115200);
Serial.println("SimpleRx Starting");
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.openReadingPipe(1, thisSlaveAddress);
radio.startListening();
}
void loop()
{
getData();
showData();
}
void getData()
{
if ( radio.available() )
{
radio.read( &receivedData, sizeof(receivedData) );
newData = true;
}
}
void showData()
{
if (newData == true)
{
Serial.print("Data received\tpinState : ");
Serial.print(receivedData.pinState);
Serial.print("\t");
Serial.print("temperature : ");
Serial.println(receivedData.temperature);
newData = false;
}
}
TX
//Tx
#include <SPI.h>
#include "RF24.h"
RF24 myRadio(9, 10);
struct package //only one struct needed
{
int msg = 0;
};
byte addresses[][6] = { "0" };
package data;
void setup()
{
Serial.begin(9600);
myRadio.begin();
myRadio.setChannel(115); //115 band above WIFI signals
myRadio.setPALevel(RF24_PA_MIN); // Power
myRadio.setDataRate(RF24_250KBPS); //Minimum speed
delay(500);
Serial.print("Setup Initialized");
}
void loop()
{
int Read_ADC = analogRead(A0);
char servo_value = map(Read_ADC, 0, 1024, 0, 180);
if (servo_value > 1) //added braces to ensure that data is sent only when available
{
data.msg = servo_value;
WriteData();
delay(50);
}
// ReadData();
//delay(200);
}
void WriteData()
{
myRadio.stopListening(); //Stop Receiving and start transminitng
myRadio.openWritingPipe(0xF0F0F0F0AA); //Sends data on this 40-bit address
myRadio.write(&data, sizeof(data));
Serial.print("\nSent:");
Serial.println(data.msg);
delay(30);
}
void ReadData()
{
myRadio.openReadingPipe(1, 0xF0F0F0F066); // Which pipe to read, 40 bit Address
myRadio.startListening(); //Stop Transminting and start Reveicing
if (myRadio.available())
{
while (myRadio.available())
{
myRadio.read(&data, sizeof(data));
}
Serial.print("\nReceived:");
Serial.println(data.msg);
}
}
RX
#include <SPI.h>
#include "RF24.h"
#include <Servo.h>
Servo myservo;
RF24 myRadio (9, 10);
struct package
{
int msg;
};
typedef struct package Package;
Package data;
byte addresses[][6] = {"0"};
void setup()
{
Serial.begin(9600);
myRadio.begin();
myRadio.setChannel(115); //115 band above WIFI signals
myRadio.setPALevel(RF24_PA_MIN); //Power
myRadio.setDataRate( RF24_250KBPS ) ; //Minimum speed
myservo.attach(2);
Serial.print("Setup Initialized");
delay(500);
}
int Servo_value;
int Pev_servo_value;
void loop()
{
ReadData();
delay(50);
Pev_servo_value = Servo_value;
Servo_value = data.msg;
while (Pev_servo_value< Servo_value)
{
myservo.write(Pev_servo_value);
Pev_servo_value++;
delay(2);
}
while (Pev_servo_value> Servo_value)
{
myservo.write(Pev_servo_value);
Pev_servo_value--;
delay(2);
}
//data.msg = "nothing to send";
//WriteData();
// delay(50);
}
void ReadData()
{
myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //Which pipe to read, 40 bit Address
myRadio.startListening(); //Stop Transminting and start Reveicing
if ( myRadio.available())
{
while (myRadio.available())
{
myRadio.read( &data, sizeof(data) );
}
Serial.print("\nReceived:");
Serial.println(data.msg);
}
}
void WriteData()
{
myRadio.stopListening(); //Stop Receiving and start transminitng
myRadio.openWritingPipe(0xF0F0F0F066);//Sends data on this 40-bit address
myRadio.write(&data, sizeof(data));
Serial.print("\nSent:");
Serial.println(data.msg);
delay(300);
}
as currently used.
I'll try your alternatives and report back
uploaded and whilst both monitors were giving gibberish it was identical gibberish.
modified the sketch to take the serial rate to 9600 on both and monitors are both putting out readable text. TX keeps saying "acknowledge received" and RX "data received pinstate:17 temperature 4186" though neither is reacting to my potentiometer
When you try my 2 sketches something is obviously working but not as it should be.
The transmitter is printing "Acknowledge received" as it should be but the receiver should be printing "Data received pinState : 0 temperature : 54" with the pinState value alternating between 0 and 1 and the temperature printing a number that increments by one each time. Note that the value actually has nothing to do with the real temperature.
The sketches that I posted do not read your potentiometer but until you can get my sketches working as described then it is going to be difficult to make any progress with your servo project
As I said previously I have no experience of the RF Nano but I believe that the sketches should work with them. Have you modified my sketches in any way beyond changing the baud rate ?
ah now you mention it yes the temperature increase by 1 each time, but pinstate is constant at 17. I've rebooted and reuploaded and its still behaving like that
It's good news about "temperature"
I don't understand that because, just like temperature it is a fake value and should only have a value of 0 or 1
A an experiment, in the Tx code change the loop() function to this
void loop()
{
currentMillis = millis();
if (currentMillis - prevMillis >= txIntervalMillis)
{
sentData.pinState = !sentData.pinState;
sentData.temperature = sentData.temperature + 1;
Serial.print("pinState = ");
Serial.println(sentData.pinState);
send();
prevMillis = millis();
}
}
What do you see in the Tx Serial monitor now ?
tx alternates pin state 1 / 0 received
rx still reports pin 17 and increasing temperature
Please copy the two sketches that you are running from the IDE and post them here
im not changing anything....
tx
// SimpleTx - the master or the transmitter
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
//not all #defines used but here for documentation
#define CE_PIN 9
#define CSN_PIN 10
#define MOSI_PIN 11
#define MISO_PIN 12
#define SCK_PIN 13
const byte slaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
char txNum = '0';
struct data
{
byte pinState;
byte temperature;
} sentData;
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000;
void setup()
{
Serial.begin(9600);
Serial.println("SimpleTx Starting");
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.setRetries(3, 5); // delay, count
radio.openWritingPipe(slaveAddress);
}
void loop()
{
currentMillis = millis();
if (currentMillis - prevMillis >= txIntervalMillis)
{
sentData.pinState = !sentData.pinState;
sentData.temperature = sentData.temperature + 1;
Serial.print("pinState = ");
Serial.println(sentData.pinState);
send();
prevMillis = millis();
}
}
void send()
{
bool rslt;
rslt = radio.write( &sentData, sizeof(sentData) );
if (rslt)
{
Serial.println(" Acknowledge received");
}
else
{
Serial.println(" Tx failed");
}
}
rx sketch
// SimpleRx - the slave or the receiver
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
//not all #defines used but here for documentation
#define CE_PIN 9
#define CSN_PIN 10
#define MOSI_PIN 11
#define MISO_PIN 12
#define SCK_PIN 13
const byte thisSlaveAddress[5] = {'R', 'x', 'A', 'A', 'A'};
RF24 radio(CE_PIN, CSN_PIN);
struct data
{
byte pinState;
int temperature;
} receivedData;
bool newData = false;
void setup()
{
Serial.begin(9600);
Serial.println("SimpleRx Starting");
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.openReadingPipe(1, thisSlaveAddress);
radio.startListening();
}
void loop()
{
getData();
showData();
}
void getData()
{
if ( radio.available() )
{
radio.read( &receivedData, sizeof(receivedData) );
newData = true;
}
}
void showData()
{
if (newData == true)
{
Serial.print("Data received\tpinState : ");
Serial.print(receivedData.pinState);
Serial.print("\t");
Serial.print("temperature : ");
Serial.println(receivedData.temperature);
newData = false;
}
}
I was just making sure
I don't think that I can help any more. The two sketches work on my test setup that consists of 2 Nanos each with an NRF24 module rather than RF Nanos with integrated radio modules
Just as a matter of interest, what happens of you swap the roles of your two RF Nanos ?
swapped over=
Pinstate 14 (not 17)
temperature stuck at 3584
Is the Tx Nano printing the expected values ?
Ok, finally got the transmission / reception stuff working but now got a servo issue that i don't understand.
here's the receiver sketch
#include "SPI.h"
#include "RF24.h"
#include "nRF24L01.h"
#include <Servo.h>
Servo 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()
{
Serial.begin(9600);
servo.attach(2);
radio.begin();
//Append ACK packet from the receiving radio back to the transmitting radio
radio.setAutoAck(false); //(true|false)
//Set the transmission datarate
radio.setDataRate(RF24_250KBPS); //(RF24_250KBPS|RF24_1MBPS|RF24_2MBPS)
//Greater level = more consumption = longer distance
radio.setPALevel(RF24_PA_MIN); //(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()
{
unsigned long currentMillis = millis();
if (radio.available() > 0)
{
radio.read(&payload, sizeof(payload));
Serial.println("Received");
Serial.print("Pot:");
Serial.println(payload.pot);
servo.write(map(payload.pot,0,255,0,180)); //moving servo according to 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);
}
The receiving side all works correctly, if i use serial monitor i can see it is correctly receiving the values from the transmitter. The servo only moves if the value decreases, it does not move if the value increases.
ie if i manually turn the servo to 180 then use the transmitter to send a lower value then the servo moves but if i then send a higher value it doesn't move in the opposite direction.
What have i cocked up?