Hello,i have make this rx for small rc car.It work well.Now i need to add a failsafe that stop the motor if the nrf24l01 lost signal with tx.Can you help me to add it?I don't know how i can implement it on rx.I enclose the code.Thanks for you help!Ivan
//Ricevitore 2.4ghz per automodello proporzionale.Autore:Ivan Pepe-(Giugno 2016)-Versione 1
//Aggiunto potenziometro digitale 64 step;
//H-bridge -avanti 100%-indietro 60%
//Aggiunta uscita accensione fari anteriori.
//Aggiunte luci Freno;
//Aggiunte luci Fari;
//Aggiungere reverse servo???
//Collegamenti del modulo RF24L01 ad Arduino:
// 1 - GND
// 2 - VCC 3.3V !!! NOT 5V
// 3 - CE to Arduino pin 9
// 4 - CSN to Arduino pin 10
// 5 - SCK to Arduino pin 13
// 6 - MOSI to Arduino pin 11
// 7 - MISO to Arduino pin 12
// 8 - UNUSED
#include <HCMotor.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
int r; int y; int n;
Servo servo;
/* Pins used to drive the motors */
#define MOTOR_PINA 5
#define MOTOR_PINB 6
#define DEADZONE 20
#define POT_REV_MIN 0
#define POT_REV_MAX (250 - DEADZONE)
#define POT_FWD_MIN (251 + DEADZONE)
#define POT_FWD_MAX 510
#define LuciFreno 4
//FARI
#define LED 3 // Led collegato al pin digitale 3
int val = 0; // Si userà val per conservare lo stato del pin di input
int vecchio_val = 0; //Si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0; //Ricorda lo stato in cui si trova il led,stato =0 led spento,stato =1 led acceso;
#define CE_PIN 9
#define CSN_PIN 10
/* Create an instance of the library */
HCMotor HCMotor;
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
RF24 radio(CE_PIN, CSN_PIN);
int joystick[3];
void setup(void)
{
/* Initialise the library */
HCMotor.Init();
HCMotor.attach(0, DCMOTOR_H_BRIDGE, MOTOR_PINA, MOTOR_PINB);
HCMotor.DutyCycle(0, 100);
Serial.begin(9600);
delay (1000);
Serial.println("Nrf24L01 Receiver Starting");
radio.begin();
radio.setChannel(80);
radio.setDataRate(RF24_2MBPS);
//radio.setDataRate(RF24_1MBPS);
//radio.setDataRate(RF24_250KBPS);
// optionally, increase the delay between retries & # of retries
radio.setRetries(12, 12);
// optionally, reduce the payload size. seems to
// improve reliability
radio.setPayloadSize(5);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1, pipes[0]);
radio.startListening();
servo.attach(2);
pinMode(3, OUTPUT);
pinMode(LuciFreno, OUTPUT);
}
void receiveOrder()
{
if ( radio.available() )
{
bool done = false;
// while (!done)
{
// Fetch the payload, and see if this was the last one.
//radio.read( &message, sizeof(unsigned long) );
// Fetch the payload, and see if this was the last one.
radio.read( joystick, sizeof(joystick) );
servo.write(joystick[0]);
Serial.print("X = ");
Serial.print(joystick[0]);
int Speed, Pot;
Pot = joystick[1];
/* Is the pot in the reverse position ? */
if (Pot >= POT_REV_MIN && Pot <= POT_REV_MAX)
{
HCMotor.Direction(0, REVERSE);
Speed = map(Pot, POT_REV_MIN, POT_REV_MAX, 60, 10);
/* Is the pot in the forward position ? */
} else if (Pot >= POT_FWD_MIN && Pot <= POT_FWD_MAX)
{
HCMotor.Direction(0, FORWARD);
Speed = map(Pot, POT_FWD_MIN, POT_FWD_MAX, 0, 100);
/* Is the pot in the dead zone ? */
} else
{
Speed = 0;
}
/* Set the on time of the duty cycle to match the position of the pot. */
HCMotor.OnTime(0, Speed);
if ((Pot >= 170) && (Pot <= 245) )
{
digitalWrite(LuciFreno, HIGH);
}
else
{
digitalWrite(LuciFreno, LOW);
}
Serial.print(" Y = ");
Serial.print(joystick[1]);
Serial.print(" z = ");
Serial.println(joystick[2]);
val = joystick[2]; //legge il valore del pulsante sul joystick2
//controlla se è accaduto qualcosa
if ((val == HIGH) && (vecchio_val == LOW)) {
stato = 1 - stato;
delay(15); //attesa di 15 millisendi
}
vecchio_val = val; //ricordiamo il valore precedente di val
if (stato == 1) {
digitalWrite(3, HIGH); //accende il led
}
else {
digitalWrite(3, LOW);//spegne il led
}
// First, stop listening so we can talk
radio.stopListening();
// Send the final one back.
radio.write( joystick, sizeof(joystick) );
//Now, resume listening so we catch the next packets
radio.startListening();
}
}
else
{
Serial.println("No radio available");
delay(50);
}
}
void loop(void)
{
receiveOrder();
}
J-M-L:
Robin - that is my question indeed. If the Tx is not supposed to send a heartbeat then it's difficult to set the timeout in a meaningful way
Yes, a regular message from the Tx was implicit in my Reply #2 and I should have made that clear. In my own model train project a message is sent every 100 millisecs even if it has the same data as the previous message.
//Telecomando 2.4ghz per modellismo.
//Collegamenti del modulo RF24L01 ad Arduino:
// 1 - GND
// 2 - VCC 3.3V !!! NOT 5V
// 3 - CE to Arduino pin 9
// 4 - CSN to Arduino pin 10
// 5 - SCK to Arduino pin 13
// 6 - MOSI to Arduino pin 11
// 7 - MISO to Arduino pin 12
// 8 - UNUSED
#include <Servo.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
//#include "printf.h"
//Telemetria
// Led Pins
int red = 7;
int green = 6;
// Print battery voltage
// with Voltage Divider R1=22k R2=10k
#define Bled_pin 8
#define CE_PIN 9
#define CSN_PIN 10
#define JOYSTICK_X A1
#define JOYSTICK_Y A0
#define JOYSTICK_Z A2
int y;
int x;
int z;
// this is not the channel address, but the transmitter address
//const uint64_t pipe = 0xE8E8F0F0E1LL;
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
RF24 radio(CE_PIN, CSN_PIN);
int joystick[3];
void setup (void)
{
pinMode(Bled_pin, OUTPUT);
digitalWrite(Bled_pin, LOW);
Serial.begin(9600);
radio.begin();
radio.setChannel(80);
radio.setDataRate(RF24_2MBPS);
//radio.setDataRate(RF24_1MBPS);
//radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
// optionally, increase the delay between retries & # of retries
radio.setRetries(12, 12);
// optionally, reduce the payload size. seems to
// improve reliability
radio.setPayloadSize(5);
//radio.openWritingPipe(pipe);
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1, pipes[1]);
radio.startListening();
// Configure the LED
pinMode(green, OUTPUT);
pinMode(red, OUTPUT);
digitalWrite(green, LOW);
digitalWrite(red, LOW);
}
void sendOrder()
{
{
printVolts(); }
x = analogRead(JOYSTICK_X);
x = map(x , 0, 1023, 30, 150);
joystick[0] = x;
Serial.print(" ");
Serial.print(x);
y = analogRead(JOYSTICK_Y);
y = map(y , 0, 1023, 0, 255 * 2);
joystick[1] = y;
Serial.print(" ");
Serial.print(y);
z = digitalRead(JOYSTICK_Z);
joystick[2] = z;
Serial.print(" ");
Serial.print(z);
// First, stop listening so we can talk.
radio.stopListening();
// Take the time, and send it. This will block until complete
radio.write( &joystick, sizeof(joystick) );// radio.write (joystick, sizeof(joystick) );
// Now, continue listening
radio.startListening();
// Wait here until we get a response, or timeout (10ms)
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > 35 )
timeout = true;
// Describe the results
if ( timeout )
{
// At this point the ACK did not arrived so the red LED has to be on
digitalWrite(green, LOW);
digitalWrite(red, HIGH);
}
else
{
// Grab the response, compare, and send to debugging spew
unsigned long response;
radio.read( &response, sizeof(unsigned long) );
// At this point the ACK did arrived so the green LED has to be on
digitalWrite(green, HIGH);
digitalWrite(red, LOW);
}
}
void printVolts()
{
int sensorValue = analogRead(A3); //read the A3 pin value
float voltage = sensorValue * (2.3 / 1023.00) * 2; //convert the value to a true voltage.//2.3
if (voltage < 4.5 ) //set the voltage considered low battery here//4.2
{
digitalWrite(Bled_pin, HIGH);
}
}
void loop(void)
{
sendOrder();
}
OK so you do send 6 bytes very often, so the proposal from Robin will work for you.
Basically if you don't get something for - say 0.2 second - then you definitely have something wrong happening.
There is an interrupt system also available on many NRF24 but this seems to not work too well. So the time-out is probably the easiest way to do what you want.
Hello I have make the change but the failsafe don't work.Can you help me on solve the problem?Thanks
//Ricevitore 2.4ghz per automodello proporzionale.Autore:Ivan Pepe-(Giugno 2016)-Versione 1
//Aggiunto potenziometro digitale 64 step;
//H-bridge -avanti 100%-indietro 60%
//Aggiunta uscita accensione fari anteriori.
//Aggiunte luci Freno;
//Aggiunte luci Fari;
//Aggiungere reverse servo???
//Collegamenti del modulo RF24L01 ad Arduino:
// 1 - GND
// 2 - VCC 3.3V !!! NOT 5V
// 3 - CE to Arduino pin 9
// 4 - CSN to Arduino pin 10
// 5 - SCK to Arduino pin 13
// 6 - MOSI to Arduino pin 11
// 7 - MISO to Arduino pin 12
// 8 - UNUSED
#include <HCMotor.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
int r; int y; int n;
Servo servo;
/* Pins used to drive the motors */
#define MOTOR_PINA 5
#define MOTOR_PINB 6
#define DEADZONE 20
#define POT_REV_MIN 0
#define POT_REV_MAX (250 - DEADZONE)
#define POT_FWD_MIN (251 + DEADZONE)
#define POT_FWD_MAX 510
#define LuciFreno 4
//FARI
#define LED 3 // Led collegato al pin digitale 3
int val = 0; // Si userà val per conservare lo stato del pin di input
int vecchio_val = 0; //Si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0; //Ricorda lo stato in cui si trova il led,stato =0 led spento,stato =1 led acceso;
#define CE_PIN 9
#define CSN_PIN 10
/* Create an instance of the library */
HCMotor HCMotor;
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
RF24 radio(CE_PIN, CSN_PIN);
int joystick[3];
void setup(void)
{
/* Initialise the library */
HCMotor.Init();
HCMotor.attach(0, DCMOTOR_H_BRIDGE, MOTOR_PINA, MOTOR_PINB);
HCMotor.DutyCycle(0, 100);
Serial.begin(9600);
delay (1000);
Serial.println("Nrf24L01 Receiver Starting");
radio.begin();
radio.setChannel(80);
radio.setDataRate(RF24_2MBPS);
//radio.setDataRate(RF24_1MBPS);
//radio.setDataRate(RF24_250KBPS);
// optionally, increase the delay between retries & # of retries
radio.setRetries(12, 12);
// optionally, reduce the payload size. seems to
// improve reliability
radio.setPayloadSize(5);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1, pipes[0]);
radio.startListening();
servo.attach(2);
pinMode(3, OUTPUT);
pinMode(LuciFreno, OUTPUT);
}
void receiveOrder()
{
static unsigned long lastRecvTime = 0;
if ( radio.available() )
{
bool done = false;
// while (!done)
// Fetch the payload, and see if this was the last one.
//radio.read( &message, sizeof(unsigned long) );
// Fetch the payload, and see if this was the last one.
radio.read( joystick, sizeof(joystick) );
lastRecvTime = millis();
if (millis() - lastRecvTime > 500) { // bring all servos to their middle position, if no RC signal is received for 0.5s!
joystick[0] = 250;//FAILSAFE motor stop
joystick[1] = 510; // (Steering for car)
//joystick[2] = 0;
receiveOrder();
}
servo.write(joystick[0]);
Serial.print("X = ");
Serial.print(joystick[0]);
//Motore Bidirezionale!
int Speed, Pot;
Pot = joystick[1];
/* Is the pot in the reverse position ? */
if (Pot >= POT_REV_MIN && Pot <= POT_REV_MAX)
{
HCMotor.Direction(0, REVERSE);
Speed = map(Pot, POT_REV_MIN, POT_REV_MAX, 60, 10);
/* Is the pot in the forward position ? */
} else if (Pot >= POT_FWD_MIN && Pot <= POT_FWD_MAX)
{
HCMotor.Direction(0, FORWARD);
Speed = map(Pot, POT_FWD_MIN, POT_FWD_MAX, 0, 100);
/* Is the pot in the dead zone ? */
} else
{
Speed = 0;
}
/* Set the on time of the duty cycle to match the position of the pot. */
HCMotor.OnTime(0, Speed);
//Luci Freno
if ((Pot >= 170) && (Pot <= 245))
{
digitalWrite(LuciFreno, HIGH);
}
else if ((Pot >= 170) && (Pot <= 0))
{
digitalWrite(LuciFreno, LOW);
}
else
{
digitalWrite(LuciFreno, LOW);
}
Serial.print(" Y = ");
Serial.print(joystick[1]);
Serial.print(" z = ");
Serial.println(joystick[2]);
val = joystick[2]; //legge il valore del pulsante sul joystick2
//controlla se è accaduto qualcosa
if ((val == HIGH) && (vecchio_val == LOW)) {
stato = 1 - stato;
delay(15); //attesa di 15 millisendi
}
vecchio_val = val; //ricordiamo il valore precedente di val
if (stato == 1) {
digitalWrite(3, HIGH); //accende il led
}
else {
digitalWrite(3, LOW);//spegne il led
}
// First, stop listening so we can talk
radio.stopListening();
// Send the final one back.
radio.write( joystick, sizeof(joystick) );
//Now, resume listening so we catch the next packets
radio.startListening();
}
}
void loop(void)
{
receiveOrder();
}
void receiveOrder()
{
static unsigned long lastRecvTime = 0;
if ( radio.available() ) {
// deal with incoming info and set lastRecvTime to mills() at the end
}
else if (millis() - lastRecvTime > 500UL) {
// deal with timeout
}
}
you might have a condition at the very start of the program where your Tx is not started before your Rx and so Rx will see the timeout. You'll need to handle that case, but if the only thing you do in the timeout section is park the motors somewhere safe then you are all OK, the next Tx will get things back in order