Wireless communication problem

Hi!

I have a 2 part problem:

  1. My arduinos are not able to communicate realiably.

  2. Each node does one extra iteration through the program after they’ve sent the off-signal back to node 00.

The project:
I’m using 1 Uno and 3 Nanos wirelessly connected through nRF24L01 modules. At each node, when given the correct signal, it will activate a servo. At each node there is a tilt sensor to determine when to reverse the servos action and send a signal back to node 00. All nodes work at least once every time I run the test. However, it often breaks down after only a few iterations around the program. I do get confirmation that the message are received, but it seems as though this is false.

For the nRF24L01, it gets its current from 3v3-pin. those connected to the Nanos have a 100μf capacitor, as I don’t have 10μf. The one at the Uno has 0.3μf. Not ideal, but it’s what I have right now.
Power requirements are set to LOW, and datarate to 250KBPS. All grounds are common. One thing that helped was to transmit the signal continously for 50ms, and in the beginning I hade the modules transmit and receive all the time. That worked well, but drained the batteries.

The code from node 00 and 01 are posted below. Node 02 and 03 have the same code as node 01.

Code from node 00:

// Program Main Wall 00

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>

#include <RF24Network.h>
#include <RF24Network_config.h>
#include <Sync.h>

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

RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t this_node = 00;
const uint16_t node01 = 01;
const uint16_t node02 = 02;
const uint16_t node03 = 03;

// Variables
int x = 0;
int prev_x = 0;
int prev2_x = 0;
int sign = 0;
int incomingData;
int sensor_current_pin = 5;
Servo servo;

void setup() {
  // put your setup code here, to run once:
  // Starting serial
  Serial.begin(9600);

  // Beginning radio network  
  SPI.begin();
  radio.begin();
  network.begin(124, this_node);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);

  //Setting inputs
  pinMode(A1, INPUT);

  //Setting outputs
  pinMode(7, OUTPUT);
  pinMode(sensor_current_pin, OUTPUT);

  // Attaching servo;
  servo.attach(7);

  // Seeding random function
  randomSeed(analogRead(A1));

  // Ready signal
  servo.write(0);
  delay(500);
  servo.write(180);
  delay(500);
}

void loop() {
  // put your main code here, to run repeatedly:
  prev2_x = prev_x;
  prev_x = x;
  x = random(0, 4);                                      // Pick a random wall
  if ((x == prev_x) && (prev_x == prev2_x)){    // But not the same more than twice
    return;
    }

  // Activate node 00
  if (x == 0) {
    digitalWrite(sensor_current_pin, HIGH);
    servo.write(0);
    Serial.println("00 activated");
    delay(100);
    while (analogRead(A1) > 200){}
    servo.write(180);
    delay(100);
    digitalWrite(sensor_current_pin, LOW);
  }


  // Activate node 01
  if (x == 1){
    sign = 11;
    uint32_t then = millis();
    uint32_t now = then;
    while ((now - then) < 50){  // Transmit sign for 50ms
      RF24NetworkHeader header(node01);
      bool ok = network.write(header, &sign, sizeof(sign));
      if (ok){                  // Check if transmition is received
        Serial.println("ok.");
      }
      else {
        Serial.println("failed.");
      }
      now = millis();
    }
    Serial.println("01 activated");
    while (sign != 10){         // while signal is active
      network.update();         
      while ( network.available() ){  // If signal is incoming, read the signal
        RF24NetworkHeader header2;
        network.read(header2, &incomingData, sizeof(incomingData));
        sign = incomingData;
        Serial.print("Signal from 01: ");
        Serial.print(sign);
        Serial.print("\n");
      }
    }
  }

  // Activate node 02
  if (x == 2){
    sign = 21;
    uint32_t then = millis();
    uint32_t now = then;
    while ((now - then) < 50){
      RF24NetworkHeader header3(node02);
      bool ok = network.write(header3, &sign, sizeof(sign));
      if (ok){
        Serial.println("ok.");
      }
      else {
        Serial.println("failed.");
      }
      now = millis();
    }
    Serial.println("02 activated");
    while (sign != 20){
      network.update();
      while ( network.available() ){
        RF24NetworkHeader header4;
        network.read(header4, &incomingData, sizeof(incomingData));
        sign = incomingData;
        Serial.print("Signal from 02: ");
        Serial.print(sign);
        Serial.print("\n");
      }
    }
  }

  // Activate node 03
  if (x == 3){
    sign = 31;
    uint32_t then = millis();
    uint32_t now = then;
    while ((now - then) < 50){
      RF24NetworkHeader header5(node03);
      bool ok = network.write(header5, &sign, sizeof(sign));
      if (ok){
        Serial.println("ok.");
      }
      else {
        Serial.println("failed.");
      }
      now = millis();
    }
    Serial.println("03 activated");
    while (sign != 30){
      network.update();
      while ( network.available() ){
        RF24NetworkHeader header6;
        network.read(header6, &incomingData, sizeof(incomingData));
        sign = incomingData;
        Serial.print("Signal from 03: ");
        Serial.print(sign);
        Serial.print("\n");
      }
    }
  }
  delay(100);
}

Code from node 01:

// Program Child Wall 01

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>

#include <RF24Network.h>
#include <RF24Network_config.h>
#include <Sync.h>

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

// Set up network
RF24 radio(10, 9);
RF24Network network(radio);
const uint16_t node00 = 00;
const uint16_t this_node = 01;

// Define variables
int sign = 0;
int incomingData;
int out = 10;
int pulse = 0;
int servo_signal_pin = 7;
int sensor_signal_pin = A1;
int sensor_current_pin = 5;
uint32_t now = 0;
uint32_t then = 0;

// Define servo
Servo servo;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  SPI.begin();
  radio.begin();
  network.begin(124, this_node);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);

  // Setting inputs
  pinMode(sensor_signal_pin, INPUT);  

  // Setting outputs
  pinMode(servo_signal_pin, OUTPUT);
  pinMode(sensor_current_pin, OUTPUT);

  // Attaching servo
  servo.attach(servo_signal_pin);

  // Ready signal
  servo.write(0);
  delay(500);
  servo.write(180);
  delay(500);
}

void loop() {
  // put your main code here, to run repeatedly:  
  network.update();

  // Receiving
  while ( network.available() ){
    RF24NetworkHeader header;
    network.read(header, &incomingData, sizeof(incomingData));
    sign = incomingData;
    Serial.println("Signal received");
  }

  // Executing
  if (sign == 11){
    int t = millis();
    if (t < (now + 75)){ // If the unit has sent a signal within
      sign = 10;         // 75ms, return.
      return;
    }
    digitalWrite(sensor_current_pin, HIGH);
    servo.write(0);
    delay(100);
    while (sign == 11){
      pulse = analogRead(sensor_signal_pin);
      Serial.println(pulse);
      if (pulse < 200){   // If switch is triggered
        digitalWrite(sensor_current_pin, LOW);
        servo.write(180);
        delay(100);
        then = millis();
        now = then;
        while ((now - then) < 50){ // Transmit signal back for 50ms
          RF24NetworkHeader header2(node00);
          bool ok = network.write(header2, &out, sizeof(out));
          now = millis();
        }
        sign = 10;
        Serial.println("Signal sent");
        delay(50);
      }
    }
  }
}

What do you expect this code to do when it detects a duplicate twice?

void loop() {
  // put your main code here, to run repeatedly:
  prev2_x = prev_x;
  prev_x = x;
  x = random(0, 4);                                      // Pick a random wall
  if ((x == prev_x) && (prev_x == prev2_x)){    // But not the same more than twice
    return;
    }

Additionally, i don’t see the need for the network library, this should nave been implemented with the standard NRF24 library. There are some significant issues with the program structure as-is.

Unless the nRF24s are far apart it the code will be much easier if you don't use the Network library.

Have a look at this Simple nRF24L01+ Tutorial.

The Tutorial includes an example for a master and 2 slaves that can easily be extended to a larger number of slaves.

Wireless problems can be very difficult to debug so get the wireless part working on its own before you start adding any other features.

The examples are as simple as I could make them and they have worked for other Forum members. If you get stuck it will be easier to help with code that I am familiar with. Start by getting the first example to work

There is also a connection test program to check that the Arduino can talk to the nRF24 it is connected to.

A common problem with nRF24 modules is insufficient 3.3v current from the Arduino 3.3v pin. This seems to be a particular problem with the nano. The high-power nRF24s (with the external antenna) will definitely need an external power supply. At least for testing try powering the nRF24 with a pair of AA alkaline cells (3v) with the battery GND connected to the Arduino GND.

If you are using the high-power nRF24s (with the external antenna) make sure there is sufficient distance between the two nRF24s so that the signal does not overwhelm the receiver - try 3 metres separation. If you are new to nRF24s it may be better to start with a pair of low power modules with the pcb antenna.

...R

WattsThat:
What do you expect this code to do when it detects a duplicate twice?

void loop() {

// put your main code here, to run repeatedly:
  prev2_x = prev_x;
  prev_x = x;
  x = random(0, 4);                                      // Pick a random wall
  if ((x == prev_x) && (prev_x == prev2_x)){    // But not the same more than twice
    return;
    }




Additionally, i don’t see the need for the network library, this should nave been implemented with the standard NRF24 library. There are some significant issues with the program structure as-is.

Thanks for the reply! I expect it to begin the loop over again and pick a new number, so that it can only set x as the same number twice. Does the standard RF24 library make it perform more consistently? How would you suggest that I change my program structure?

Robin2:
Unless the nRF24s are far apart it the code will be much easier...

Thank you! I will check out that tutorial and test the codes with the current setup.

I think I did a little break through. The modules works perfectly when I'm running the "helloworld"-code that comes with the network library. Then I made the transmitter transmit a random number from 0 to 1023. The receiver would then map this to a value between 0 and 180 for the angle of the servo. This worked for max 3 iterations, then the program freezed and every transmition failed.

However, when I did not use the payload that was received directly, and instead initiated the sequence above on only the receiver, it worked perfectly. Is it a known bug that of you transmit and use ints, the program will freeze?

henrissl:
Is it a known bug that of you transmit and use ints, the program will freeze?

No. There must be something wrong with the programs you did not post.

...R

    uint32_t now = then;
    while ((now - then) < 50){

is equivalent to

    uint32_t now = then;
    while (0 < 50){