NR24L01 problem when uses signal

Robin2:
Sending data only when there is a change (without any repeats) is a risky strategy.

Not with acknowledgements enabled and proper handling of failed sends. :wink:

In case of multicasts, repeated sends are a simple and good strategy and useful as a heartbeat signal.

[OT]

I favour multicasts for information distribution, so I normally set up a timed send function,
if the data changes, I shorten the current wait to expire on the next tick, pushing the new data out.
A lazy way to keep the distributed information current if changes happen.

[/OT]

From the beginning, again I have a car that can do a few things, like turn on lights, shoot some darts, etc. The problem that I have is whenever it loses the signal (because it is out of range) it simply does it's last "order" from its previous message. So basically if it was going forward it will go forward forever. What I intended to do is to make it stop in case it does not receive any message. What I tried to do is to use the .available() function from the RF24 library. I programmed it to stop if radio.available was false, but, I have no idea why, it stops and goes forward over and over again (it would also blink one of the LEDs if radio.available() == False). The code that I am using right now does not react at all if it loses range, so I currently have the first issue (it does its last "order").

In a nutshell:

-When loses signal:
-It does its last task (if it was go forward, it will go forward forever)

-I want to stop it by:
-Writing a way in which if it does not receive any signal, it should stop the robot

One more thing

I am sorry for not putting the code in here. I did this, because it says that I cannot write more than 9000 characters and I thought that it would more practical to put the software in website than to split it in multiple posts (because I need 5 minutes for each part).

First part:

//this is for the arduino mega

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

//ALL the functions that are necessary

/********************************************************************************/

//this function has the objective to control a dc motor attached to a wheel in order
//make it move forward or backward or even stop it

void wheelControl(int velocity, int forwardPin, int backwardPin) {
  //velocity will control if it moves forward, backward or to not move
  //if 1 = forward
  //if -1 = backward
  //if 0 = won't move
  //the forwardPin will be digital pin responsible for moving it forward, the backwardPin to make
  //it move backward

  //this statement will test if a valid number has been given in the velocity variable
  if (velocity > 1 || velocity < -1) {
    return 0;
  }
  //this if else statement will make the dc motor move according to the number given
  //if 1 = forward
  //if -1 = backward
  //if 0 = won't move
  if (velocity == 1) {
    digitalWrite(forwardPin, 1);
    digitalWrite(backwardPin, 0);
  }
  else if (velocity == -1) {
    digitalWrite(forwardPin, 0);
    digitalWrite(backwardPin, 1);
  }
  else if (velocity == 0) {
    digitalWrite(forwardPin, 0);
    digitalWrite(backwardPin, 0);
  }

  return 0;
}


/******************************************************************************/

//this function measures distances with a ultrasonic sensor
float soundSensorDistanceMeasuring(int echo, int trig, float soundSpeed) {
  //this is for the HC-SR04
  //echo and trig represent the pins on the sensor
  //soundSpeed represent the the sound speed (standard = 341.88034188 m/s)
  /*************************************************************************/
  //this is for the pin definitions. Basically it will only be activated
  //when the function in called
  pinMode(echo, INPUT);
  pinMode(trig, OUTPUT);
  float Time;
  //signal analysis

  digitalWrite(trig, 0);
  delayMicroseconds(2000);
  digitalWrite(trig, 1);
  delayMicroseconds(15);
  digitalWrite(trig, 0);
  delayMicroseconds(10);

  //time reading

  Time = pulseIn(echo, 1);

  //Distance calculation
  Time = Time / 2;
  Time = Time / 1000000;

  float distance;
  distance = Time * soundSpeed;
  //returning the distance in meters
  return distance;
}


/*******************************************************************/

//INPUT values
typedef struct data{
  int trigger;
  int reverse;
  int buzzer;
  int lights;
  int xAxis;
  int yAxis;
  int securityMode;
  int automaticMode;
  int RangeAlertMode;
  int RangeScale;
    void print(){
    Serial.print(trigger);
    Serial.print(",");
    Serial.print(reverse);
    Serial.print(",");
    Serial.print(buzzer);
    Serial.print(",");
    Serial.print(lights);
    Serial.print(",");
    Serial.print(xAxis);
    Serial.print(",");
    Serial.print(yAxis);
    Serial.print(",");
    Serial.print(securityMode);
    Serial.print(",");
    Serial.print(automaticMode);
    Serial.print(",");
    Serial.print(RangeAlertMode);
    Serial.print(",");
    Serial.print(RangeScale);
    Serial.print("\n");
  }
}dataSend;

dataSend dataSendFinal;

typedef struct sensorData{
  int distance;
  int luminosity;
  void print(){
    Serial.print(distance);
    Serial.print(",");
    Serial.println(luminosity);
  }
}DataOut;

DataOut DataOutFinal;


//defining everything that is required to the RF communication
const uint64_t pipes[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};

RF24 radio(48, 49);

//for the cannon
Servo       pointer;
int   shotFired = 0;

I will post the void loop and the void setup in 5 minutes

2nd part: void setup and void loop

void setup() {
  //for the cannon
  pointer.attach(5);
  /***************************/
  Serial.begin(115200);
  //setup of the radio communication
  radio.begin();
  radio.powerUp();
  //definition of the pipes that are going to be used to stablish the communication between both devices NOTE: the one with the 1 has to change in the one with the receiver
  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1, pipes[1]);
  //definition of the conection
  //conection speed
  radio.setDataRate(RF24_250KBPS) ;
  //energy setup
  radio.setPALevel( RF24_PA_MAX ) ;
  //set channel to 105
  radio.setChannel(105);
  //other setups
  radio.enableDynamicPayloads();
  radio.enableAckPayload();
  //number of atemps that will use in order to send a message
  radio.setRetries(5, 15);

  radio.setAutoAck( true );
  radio.writeAckPayload(1, &DataOutFinal, sizeof(DataOutFinal));
  radio.startListening();

   //wheel
  pinMode(26,OUTPUT);
  pinMode(27,OUTPUT);
  pinMode(28,OUTPUT);
  pinMode(29,OUTPUT);
  //lights
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  //buzzer
  pinMode(2,OUTPUT);
  pinMode(8,OUTPUT);
  digitalWrite(8,0);
}

void loop() {
  unsigned long topLoop = millis();
  static unsigned long lastMeasure;
  static unsigned long lastPacket;
  if (topLoop - lastPacket >= 500) {
    lastPacket = topLoop; // block direct reoccurrence
    radio.stopListening();
    radio.startListening();
    radio.writeAckPayload(1, &DataOutFinal, sizeof(DataOutFinal));
    
    //Serial.print(F("P: ")); // preload
    //DataOutFinal.print();
  }
  
  if (topLoop - lastMeasure >= 150) {
    lastMeasure = topLoop;
    DataOutFinal.distance = int(soundSensorDistanceMeasuring(13, 12, 341.88034188 )*100);
    DataOutFinal.luminosity = analogRead(A1);
    if (DataOutFinal.distance > 300) {
      DataOutFinal.distance = -1;
      
    }

    Serial.print(F("M: ")); // modify
  //DataOutFinal.print();
  //trying to receive a signal and if so receive and process the info
  if (radio.available()) {
   radio.read(&dataSendFinal, sizeof(struct data));
   radio.writeAckPayload(1, &DataOutFinal, sizeof(DataOutFinal));
   Serial.println("Command:");
   dataSendFinal.print();
   Serial.println("Sensors");
   DataOutFinal.print();
  }
  /*else{
    wheelControl(0, 26, 27); //rignt wheel
    wheelControl(0, 28, 29); //left wheel
    digitalWrite(3,1);
    delay(25);
    digitalWrite(3,0);
    delay(25);
    digitalWrite(3,1);
    delay(25);
    digitalWrite(3,0);
    delay(25);
  }
*/
//in case the communication gets problematic
    if(dataSendFinal.trigger < 0 || dataSendFinal.trigger > 1 || dataSendFinal.reverse < 0 || dataSendFinal.reverse > 1 ||  dataSendFinal.lights < 0 || dataSendFinal.lights > 1023 || dataSendFinal.xAxis < 0 || dataSendFinal.xAxis > 1023 || dataSendFinal.yAxis < 0 || dataSendFinal.yAxis > 1023 || dataSendFinal.securityMode < 0 || dataSendFinal.securityMode > 1 || dataSendFinal.automaticMode < 0 || dataSendFinal.automaticMode > 1 || dataSendFinal.RangeAlertMode < 0 || dataSendFinal.RangeAlertMode > 1  || dataSendFinal.RangeScale < 0 || dataSendFinal.RangeScale > 51 ){
      radio.powerDown();
      wheelControl(0, 26, 27); //rignt wheel
      wheelControl(0, 28, 29); //left wheel
      digitalWrite(2,0); 
      delay(100);
      radio.powerUp();      
    }
    
    
    //light controll
    if(dataSendFinal.automaticMode == 1){
      if(DataOutFinal.luminosity < 200){
        digitalWrite(3,1);
        digitalWrite(4,1);  
      }
      else if(DataOutFinal.luminosity > 200){
        digitalWrite(3,0);
        digitalWrite(4,0);  
      }
    }
    else {
      analogWrite(3,dataSendFinal.lights/4);
      analogWrite(4,dataSendFinal.lights/4);
    }
    //wheel control
    //to go forward, backward, right and left
    
    if(dataSendFinal.yAxis < 400){
      wheelControl(1, 26, 27); //rignt wheel
      wheelControl(1, 28, 29); //left wheel
      
      
      
    }
    else if(700 < dataSendFinal.yAxis){
      
      wheelControl(-1, 26, 27); //rignt wheel
      wheelControl(-1, 28, 29); //left wheel
     
        
    }
    else{  
    
    if(dataSendFinal.xAxis < 400 && dataSendFinal.reverse == 0){
      
      wheelControl(0, 26, 27); //rignt wheel
      wheelControl(1, 28, 29); //left wheel
            
    }
    else if(dataSendFinal.xAxis > 600 && dataSendFinal.reverse == 0){
      
      wheelControl(1, 26, 27); //rignt wheel
      wheelControl(0, 28, 29); //left wheel
           
    }
    else if(dataSendFinal.xAxis < 400 && dataSendFinal.reverse == 1){
      
      wheelControl(0, 26, 27); //rignt wheel
      wheelControl(-1, 28, 29); //left wheel
           
    }
    else if(dataSendFinal.xAxis > 600 && dataSendFinal.reverse == 1){
      
      wheelControl(-1, 26, 27); //rignt wheel
      wheelControl(0, 28, 29); //left wheel
           
    }
    else{
      wheelControl(0, 26, 27); //rignt wheel
      wheelControl(0, 28, 29); //left wheel
         
    }
    }

    if(dataSendFinal.RangeAlertMode == 1){
      if( DataOutFinal.distance < dataSendFinal.RangeScale && DataOutFinal.distance != -1){
        digitalWrite(2,1); 
        
      }
      else{
        digitalWrite(2,0); 
      }
    }
    else{
      digitalWrite(2,0); 
    }
    if(dataSendFinal.buzzer == 1 && dataSendFinal.RangeAlertMode != 1){
      digitalWrite(2,1);
    }
    else{
      
    }
    
    if(dataSendFinal.securityMode == 1){
      
    }else if(dataSendFinal.securityMode == 0){
    if(dataSendFinal.trigger == 1){
      if(shotFired == 1){
        
      }
      else if(shotFired != 1){
        radio.stopListening();
        wheelControl(0, 26, 27); //rignt wheel
        wheelControl(0, 28, 29); //left wheel
        //start the engine
        pinMode(7,OUTPUT);
        digitalWrite(7,1);
        delay(3000);
        //TAKE THE SHOT DAMMIT, FINISH IT HAVE NO MERCY!!!
        pointer.write(0);
        delay(500);
        pointer.write(70);
        //stop the engine and start the communication
        digitalWrite(7,0);
        radio.startListening();
      }
    }
    }
    shotFired = dataSendFinal.trigger;
  }
}

Whandall:
Not with acknowledgements enabled and proper handling of failed sends. :wink:

I know you know how to do it. I have been assuming the OP does not, but I don't propose to write a whole textbook on reliable communication :slight_smile:

...R

ddmdavid01:
I am sorry for not putting the code in here. I did this, because it says that I cannot write more than 9000 characters

Thanks for posting the code. For the future you can add a long .ino file as an attachment if you use the full editor.

Where does the code you have just posted fit into the chronology of this Thread? What is the most recent Reply that you have taken into account?

I had rather hoped that you would have made an attempt to add some code to create a timeout for failed messages?

That is the next task for you to attempt. Of course it will also require a change to the code on the "transmitter" Arduino.

...R

As I stated this code i s a code without any attempt to fix the issue. I haven't changed yet, because I can't currently test it and I am checking the documentation in order to see if I can use something. By the way, is there any way the .isackpayloadavailable() useful, I tried to use it, but it does not work.

ddmdavid01:
is there any way the .isackpayloadavailable() useful, I tried to use it, but it does not work.

There are some pitfalls in using it, but it works reliably on up to three pipes at a time if done correctly.

Ok thanks. One thing is there a function that detects when a channel is empty? I think if there is, it will solve the problem.

ddmdavid01:
As I stated this code i s a code without any attempt to fix the issue. I haven't changed yet,

Your last Post was Reply #25 #27.

I made a suggestion in Reply #4 which I still think will solve the problem. It seems a bit pointless making suggestions when you don't make any use of them.

...R

I know and intend to try. The thing is that right now I am trying to see more than one way since I am only testing tomorrow. I am planning to use your method, I will tell how it went.

I have implemented the change you suggested me to do. I hope it works, I can't test today, I have to do it tomorrow. In the command code the lines that are responsible are from 132 to 135 and the ones in the car code are from 228 to 252. Hope you could see if I did it correctly.

codeForTheCommand.ino (3.69 KB)

codeForTheCar.ino (10.3 KB)

The command code looks reasonable - it seems to send a value every 150 msecs.

The Car code does not look right. It should be something like

if (radio.available()) {
   latestMessageMillis = millis();
   // other stuff
}
if (millis() - latestMessageMillis >= maxIntervalMillis) {
   // code to shut things down
}

Why is your Car code expecting an ackPayload? I am assuming the Command unit is the Master and it initiates communication and checks for acknowledgements including an ackPayload if the Car is sending data back to the Command unit.

Don't make the thing over complex by having both devices take their turn at being Master.

...R

Robin2:
Why is your Car code expecting an ackPayload?

Sorry you are right I changed it to radio.available:

  if(radio.available()){
    radio.read(&radioCheck, sizeof(radioCheck));
    if(radioCheck == 1){
      numberChecksConfirmed = millis();
     }

  }

Analyzing your way I came to the conclusion that it is way more effective than mine, so I am going to use it and here it is:

  if(millis() - numberChecksConfirmed >= 100){
    
      
      wheelControl(0, 26, 27); //rignt wheel
      wheelControl(0, 28, 29); //left wheel
      radio.failureDetected = 0;
      radio.begin();                       //Attempt to reconfigure the communication
      radio.powerUp();
      radio.openWritingPipe(pipes[0]);
      radio.openReadingPipe(1, pipes[1]);

      digitalWrite(2,0); //stop buzzer if it is buzzing
      
    
  }

Thank you for the help I just hope it works.

codeForTheCar.ino (10.1 KB)

codeForTheCommand.ino (3.69 KB)

ddmdavid01:

  if(millis() - numberChecksConfirmed >= 100){

That makes no sense to me.

if the variable numberChecksConfirmed is a count of messages received it will bear no useful relationship to the value of millis

If it is a badly named variable that actually holds the value of millis() from when the most recent message was received then it only provides a timeout of 100 millisecs.

...R

So update on the project:

The solution that you gave me did not work. What happened is that the wheels just started to move even with signal and I have no control on the car. I though that this was a problem with the statements that I created to control the wheels, so I created one variable which would have a number zero if it was out of range and a one in case of the opposite (code for this case is attached to the reply). What happened it was that the vehicle would not move at all.

I have no idea why this is happening. One thing is there a way to stop a void loop with a function o something like that I think that would work (I will try to find it).

codeForTheCar.ino (9.94 KB)

codeForTheCommand.ino (3.56 KB)

Great now it does not even work with the other codes, it simply does not receive any signal.

I have no idea why, but with the previous codes what is received by the car is something like this:

Sensors
143,868
M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
-1,867
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
116,867
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
141,868
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
141,868
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
140,868
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
79,868
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
80,867
M: M: Command:
0,0,0,0,0,0,0,0,0,0
Sensors
107,868

And I receive nothing from the command. There is no signal what so ever. I have no idea of what is happening and I am getting quite desperate. I checked the connection, I checked the cables, I soldered a 10 uF capacitor and nothing!!!!

codeForTheCommand.ino (3.56 KB)

codeForTheCar.ino (9.23 KB)

These comments are based on the code in Reply #36.

What are these bits supposed to achieve?

  if (topLoop - lastPacket >= 500) {
    lastPacket = topLoop; // block direct reoccurrence
    radio.stopListening();
    radio.startListening();
 if (topLoop - lastMeasure >= 150) {
    lastMeasure = topLoop;

When you run into wireless problems the first thing to do is simplify things as far as possible. Have you tried the 2nd example in my tutorial?

look right now I am not trying to solve the first problem. My modules simply stopped communicating with each other. I put the first code, the one that does not respond when it loses range, and nothing is received by both sensors. I think it is something with the hardware. Do you have any idea of what it could be?

Ok I made a test with the attached codes and here is the result:

0
0
0
0
0
0
0
0

This is just a part of it. At least now I understand why it would go forward when no signal was received, because everything would be a zero (and zero is a valid number to go forward).

What does this mean? Is it a wire, it has always worked?

testecarro.ino (1.23 KB)

testecomando.ino (1.16 KB)