NRF24l01 network causes servo stutter?

Hello everyone.

Im working on a project with a NRF24l01 network. Everything is controlled by 3.3V 8mhz pro micro arduinos because of a lack of space.

The situation is as following:

1 arduino is the transmitter and has 3 pot meters attached to it, it controls 3 nodes wirelessly. Each node has another arduino. 2 control an rc ESC, 1 controls a set of 8 Servo's.

I wrote (read: copy pasted and moved things around) the following codes:

this is the code for the Transmitter:

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
 == Example 01 - Servo Control / Node 00 - Potentiometer ==
  by Dejan, www.HowToMechatronics.com
  Libraries:
  nRF24/RF24, https://github.com/nRF24/RF24
  nRF24/RF24Network, https://github.com/nRF24/RF24Network
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>

RF24 radio(8, 7);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;   
const uint16_t node02 = 02;   
const uint16_t node03 = 03;   
   
void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
}

void loop() {
  network.update();
  unsigned long potValue1 = analogRead(A0);  // Read the potentiometer value
  unsigned long angleValue1 = map(potValue1, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header1(node01);     // (Address where the data is going)
  bool ok1 = network.write(header1, &angleValue1, sizeof(angleValue1)); // Send the data

  unsigned long potValue2 = analogRead(A1);  // Read the potentiometer value
  unsigned long angleValue2 = map(potValue2, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header2(node02);     // (Address where the data is going)
  bool ok2 = network.write(header2, &angleValue2, sizeof(angleValue2)); // Send the data

  unsigned long potValue3 = analogRead(A2);  // Read the potentiometer value
  unsigned long angleValue3 = map(potValue3, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header3(node03);     // (Address where the data is going)
  bool ok3 = network.write(header3, &angleValue3, sizeof(angleValue3)); // Send the data
}

This is the code for the receiver:

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
  == Example 01 - Servo Control / Node 01 - Servo motor ==
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include <Servo.h>

RF24 radio(8, 7);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 01;   // Address of our node in Octal format ( 04,031, etc)

Servo myservo;  // create servo object to control a servo

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
  myservo.attach(4);   // (servo pin)
}

void loop() {
  network.update();
  while ( network.available() ) {     // Is there any incoming data?
    RF24NetworkHeader header;
    unsigned long incomingData;
    network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data
    myservo.write(incomingData);  // tell servo to go to a particular angle
  }
}

The problem is that my servos stutter. It seems as if the code loop takes about 1/10th of a second to run and causes the servo position to be updated as infrequently.

I want to be able to control the servo position and speed of the motors attached to the ESC simultaneously through the 3 potmeters though.

Could I send all potmeter positions in 1 batch to all 3 nodes at the same time and each node filters out the info it needs to make the loop more frequent?
Can I use a 16mhz arduino UNO for the transmitter to speed it all up?
Should I use millis() (I've tried reading into it but, as far as I understand it, it shouldnt make a difference since the transmitting is causing the problem/delay)

Or am I missing out on something completely because of my lack of arduino experience?

Thanks you all in advance, help a noob out!

The symptoms point to power problems. Both the servos and NRF2401 take a lot of current in the short time they are operating.

Paul

SenD1990:
The problem is that my servos stutter. It seems as if the code loop takes about 1/10th of a second to run and causes the servo position to be updated as infrequently.

The servo should not stutter even if the value is never updated. The command myservo.write() just updates the servo library's data. The library will be sending servo pulses every 50 millisecs based on the most recent value it received.

How far apart are the Arduinos? Do you really need the Network library? It adds considerable overhead to the basic RF24 library. I have never used it myself.

...R
Simple nRF24L01+ Tutorial

Paul_KD7HB:
The symptoms point to power problems. Both the servos and NRF2401 take a lot of current in the short time they are operating.

Paul

The Servo's are running on an external power supply. This shouldnt be a problem!

Robin2:
The servo should not stutter even if the value is never updated. The command myservo.write() just updates the servo library's data. The library will be sending servo pulses every 50 millisecs based on the most recent value it received.

How far apart are the Arduinos? Do you really need the Network library? It adds considerable overhead to the basic RF24 library. I have never used it myself.

...R
Simple nRF24L01+ Tutorial

Maybe I the term 'stutter' isn't quite the right term. What I mean is that it moves to the next position in a jagged manner. When I turn the pot meter from 0 tot 180 degrees, it moves towards that position in pulses if you know what I mean. Instead of one fluent rotation it moves there in 5 short pulses of the 1/10th of a second mentioned above.

SenD1990:
When I turn the pot meter from 0 tot 180 degrees, it moves towards that position in pulses if you know what I mean. Instead of one fluent rotation it moves there in 5 short pulses of the 1/10th of a second mentioned above.

You could modify the code that moves the servo so that it sweeps the servo from the present position to the next position rather than jumping straight to it at full speed.

For my own projects I have found updates of about 5 per second are responsive enough - even without smoothing of the servo movement.

Set up a small test project with the servo and pot on the same Arduino (i.e. no wireless) and experiment with the update interval.

...R

Robin2:
You could modify the code that moves the servo so that it sweeps the servo from the present position to the next position rather than jumping straight to it at full speed.

For my own projects I have found updates of about 5 per second are responsive enough - even without smoothing of the servo movement.

Set up a small test project with the servo and pot on the same Arduino (i.e. no wireless) and experiment with the update interval.

...R

I have tested the servo and pot on the same arduino using the example servo sweep code. This worked as it should. Only after I tried to reënact the servo sweep through the wireless connection the servo started stuttering. As soon as I added the 2nd and 3rd node control through the network in the loop, the stuttering got worse (with the 10 pulses per second being the worst)

the code below provided smooth control of the servo through the wireless connection.

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
 == Example 01 - Servo Control / Node 00 - Potentiometer ==
  by Dejan, www.HowToMechatronics.com
  Libraries:
  nRF24/RF24, https://github.com/nRF24/RF24
  nRF24/RF24Network, https://github.com/nRF24/RF24Network
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>

RF24 radio(8, 7);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;   
const uint16_t node02 = 02;   
const uint16_t node03 = 03;   
   
void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
}

void loop() {
  network.update();
  unsigned long potValue1 = analogRead(A0);  // Read the potentiometer value
  unsigned long angleValue1 = map(potValue1, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header1(node01);     // (Address where the data is going)
  bool ok1 = network.write(header1, &angleValue1, sizeof(angleValue1)); // Send the data
}

As soon as I add the following bit of code for the 2nd and 3rd node (as in my first example) the servo on node 1 starts to move irregularly.

  network.update();
  unsigned long potValue1 = analogRead(A0);  // Read the potentiometer value
  unsigned long angleValue1 = map(potValue1, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header1(node01);     // (Address where the data is going)
  bool ok1 = network.write(header1, &angleValue1, sizeof(angleValue1)); // Send the data

SenD1990:
I have tested the servo and pot on the same arduino using the example servo sweep code. This worked as it should.

Did you include an interval (such as 100 millisecs) between readings of the Pot?

...R

You have no moderation in your sending loop,

void loop() {
  network.update();
  unsigned long potValue1 = analogRead(A0);  // Read the potentiometer value
  unsigned long angleValue1 = map(potValue1, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header1(node01);     // (Address where the data is going)
  bool ok1 = network.write(header1, &angleValue1, sizeof(angleValue1)); // Send the data
}

or worded differently, you are sending as fast as possible, probably around 500 times each second.
This as fast as possible forces the receiver also to receive as fast as possible,
but if it has to do more than an analogRead it will be slower than the transmitter,
filling the fifos, dropping packets, ...

Servos need time to move, but they also need time to read the desired position.
IIRC the frequency of the used signal is 50 Hz,
so you try to adjust the target position ten times before one such target position can be transfered.

If the pulse train is restarted each time you adjust the position, this will lead to trouble.

Changing the boundery registers of the underlying timer ten times in each cycle does not seem sensible to me.

BTW. I would only transmit the position if it changed, or if half a second expired without changes.
Besides that, a sampling rate of ten times a second should work quite well.