Virtualwire - Protection against connection lost

Hello!

I'm using the Virtualwire library and i would like to find out a way to have a protection when the transmitter is powered off.

Allow me to explain: I'm switching on and off a relay on the receiver whenever i press a button on the transmitter. So far so good. But i tried to turn off the transmitter when pushing the button, but the relay won't turn off.

I'd like to know if the is a way to make my outputs turn off if the transmitter is no longer transmitting, just like the example.

My transmitter code:

#include <VirtualWire.h>
 

char data_cima[4];
char data_baixo[4];
char data_esquerda[4];
char data_direita[4];
char data_frente[4];
char data_tras[4];
char data_mestre[4];

int cima1 = 11;
int baixo1 = 12;
int esquerda1 = 8;
int direita1 = 10;
int frente1 = 3;
int tras1 = 2;
int cima = 0;
int baixo = 0;
int esquerda = 0;
int direita = 0;
int frente = 0;
int tras = 0;
int mestre = 0;
int ctrl_cima = 55;
int ctrl_baixo = 83;
int ctrl_esquerda = 77;
int ctrl_direita = 17;
int ctrl_frente = 25;
int ctrl_tras = 5;


 
void setup()
{
  Serial.begin(9600);
  vw_set_tx_pin(7);
  vw_setup(2000);
  pinMode(cima1,INPUT);
  pinMode(baixo1,INPUT);
  pinMode(esquerda1,INPUT);
  pinMode(direita1,INPUT);
  pinMode(frente1,INPUT);
  pinMode(tras1,INPUT);  
  
}
 
void loop()
{
  cima = digitalRead(cima1);
  baixo = digitalRead(baixo1);
  esquerda = digitalRead(esquerda1);
  direita = digitalRead(direita1);
  frente = digitalRead(frente1);
  tras = digitalRead(tras1);
  Serial.println(cima);

  if(cima == 1 && baixo == 1){
    itoa(mestre, data_mestre, 10);
    vw_send((uint8_t *)&data_mestre, strlen(data_mestre)); 
    vw_wait_tx(); 
    delay(50);
  }

  if(cima == 1 && baixo == 0){
    itoa(ctrl_cima, data_cima, 10);
    vw_send((uint8_t *)&data_cima, strlen(data_cima)); 
    vw_wait_tx(); 
    delay(50);
  }

  if(baixo == 1 && cima == 0){
    itoa(ctrl_baixo, data_baixo, 10);
    vw_send((uint8_t *)&data_baixo, strlen(data_baixo)); 
    vw_wait_tx(); 
    
  }
  
  if(cima == 0 && baixo == 0 && esquerda == 0 && direita == 0 && frente == 0 && tras == 0){
    itoa(mestre, data_mestre, 2);
    vw_send((uint8_t *)data_mestre, strlen(data_mestre)); 
    vw_wait_tx(); 
    delay(50);
  }

}

and my receiver code:

#include <VirtualWire.h>

int cima = 2;
int baixo = 3;
int esquerda = 8;
int direita = 10;
int frente = 11;
int tras = 12;
int valor_recebido_RF;
char recebido_RF_char[4]; 
bool teste = false; 
void setup()   {
    vw_set_rx_pin(5); // Define o pino 5 do Arduino como entrada 
//de dados do receptor
    vw_setup(2000);             // Bits por segundo
    pinMode(cima,OUTPUT);
    pinMode(baixo,OUTPUT);
    pinMode(esquerda,OUTPUT);
    pinMode(direita,OUTPUT);
    pinMode(frente,OUTPUT);
    pinMode(tras,OUTPUT);
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(12, HIGH);
    Serial.begin(9600);
    vw_rx_start();              // Inicializa o receptor
 
}
 
void loop()
{ 
    uint8_t message[VW_MAX_MESSAGE_LEN];
    uint8_t msgLength = VW_MAX_MESSAGE_LEN;
        if (vw_get_message(message, &msgLength)){
          teste = true;
          int i;
        for (i = 0; i < msgLength; i++){            
          //Armazena os caracteres recebidos  
          recebido_RF_char[i] = char(message[i]);
       }
       recebido_RF_char[msgLength] = '\0';
       
       //Converte o valor recebido para integer
       valor_recebido_RF = atoi(recebido_RF_char);
         
       //Mostra no serial monitor o valor recebido
         Serial.print(vw_have_message());
       //Altera o estado do led conforme o numero recebido
      
       if (valor_recebido_RF == 55)
       {
         digitalWrite(cima, LOW);
         
       }
       if (valor_recebido_RF == 83)
       {
         digitalWrite(baixo, LOW);

         
       }

       if (valor_recebido_RF == 0)
       {
         digitalWrite(cima, HIGH);
         digitalWrite(baixo, HIGH);
         digitalWrite(esquerda, HIGH);
         digitalWrite(direita, HIGH);
         digitalWrite(frente, HIGH);
         digitalWrite(tras, HIGH);
       }
       
    }
   else if(!vw_have_message()){
       }

  
}

Looking for any help.

Thank you guys!

How do you have your buttons wired up? Your code would demand that they have a pull-up or pull-down resistor installed? Do you have them installed?

if your first if() condition is true, your last if() condition can never be true since cima and baixo can never be 0 and 1 in the same iteration through loop()

blh64:
How do you have your buttons wired up? Your code would demand that they have a pull-up or pull-down resistor installed? Do you have them installed?

if your first if() condition is true, your last if() condition can never be true since cima and baixo can never be 0 and 1 in the same iteration through loop()

First of all, thanks for helping me.
All the buttons in the transmitter have pulldown resistors. And in this case, i'm having trouble with making se second if() true when the first one is not.

Also, when i turn off the transmitter while pressing a button, outside the first if() of the receiver code the value of the button that i last pressed will be there. I checked by printing with the serial monitor.

the receiver will know if the transmitter is dead only if there is some sort of heartbeat going on all the time and it stops receiving it.

if you only send commands when buttons are pressed, then the absence of chatter can mean the emitter is dead or just that no-one pressed anything.

==> can't tell which is which

i'm trying this in the receiver code:

void loop()
{ 
        uint8_t message[VW_MAX_MESSAGE_LEN];
        uint8_t msgLength = VW_MAX_MESSAGE_LEN;
     
        if(vw_get_message(message, &msgLength)){
          teste = 0;
          int i;
        for(i = 0; i < msgLength; i++){            
          
          recebido_RF_char[i] = char(message[i]);
          teste = 0;
       }
       recebido_RF_char[msgLength] = '\0';
       
       //Converte o valor recebido para integer
       valor_recebido_RF = atoi(recebido_RF_char);
     
       if (valor_recebido_RF == 55)
       {
         teste = 0;
         digitalWrite(cima, LOW);
         digitalWrite(esquerda,HIGH);
         
       }
       if (valor_recebido_RF == 83)
       {
         teste = 0;
         digitalWrite(baixo, LOW);
         digitalWrite(esquerda,HIGH);
         
       }

       if (valor_recebido_RF == 0)
       {
         teste = 0;
         digitalWrite(cima, HIGH);
         digitalWrite(baixo, HIGH);
         digitalWrite(esquerda, HIGH);
         digitalWrite(direita, HIGH);
         digitalWrite(frente, HIGH);
         digitalWrite(tras, HIGH);
       }
      delay(100); 
    }
    
 Serial.println(teste);
  if(teste == 1){
    digitalWrite(esquerda,LOW);
  }
  teste = 1; 
}

using int teste to activate the last if() whenever the first if() is not true, but the int teste keep changing between 1 and 0, when the transmitter is off, it will keep 1 as expected, but won't keep in 0 when the transmitter is sending data.

I don't get what you are doing. if you don't get a message your loop will conceptually look like this

void loop()
{
  Serial.println(teste);
  if (teste == 1) {
    digitalWrite(esquerda, LOW);
  }
  teste = 1;
}

so you'll set teste to 1 and you'll put esquerda LOW. as your loop spin really fast, in between 2 messages you'll keep esquerda LOW all the time.

Again, without an heart beat you can't know if the emitter is down. You only know you did not receive anything.

May be you can do a timeout: if you have not received a message in the last x seconds then put esquerda LOW

J-M-L:
so you'll set teste to 1 and you'll put esquerda LOW. as your loop spin really fast, in between 2 messages you'll keep esquerda LOW all the time.

This worked fine:

int teste = 0;
int x = 1;
int a = 0;
void setup() {
  Serial.begin(9600);

}

void loop() {
  if(x == 1){
    teste = 1;
  }
  Serial.println(teste);
  if(teste == 0){
    a = 2;
  }
  teste = 0;
  
}

Even if the loop spins really fast.
But, how can i set a "heartbeat", or a timeout?
Because, the last value received from the emitter will be saved, and i can't use it, since it won't change if the emitter is down.

For as long as there have been local area networks, they have used a message giving date and time sent once a second or so as a "heart beat" type message.
Paul

If you continuously send, you can add a millis() based timeout in the receiver.

Use a variable to store the last time that a message was received (miliis()). Compare that time with millis() and if a certain time has lapsed, do what needs to be done.

If you only send occasionally, start sending dummy commands.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.