Making transceiver from 2 TX and 2 RX modules, code problem help !

hello guys,
hope you all doing well

what i am doing here is a small RC car which i had, so I decided to build a speedometer by attaching a hall effect switch sensor and add some LEDs to the bottom, the top leds are controlled by a shift register
and controlling these by a controller which has 2 push buttons, an LCD 16x2, a TX RF module for 315mhz and a RX RF module for 433mhz

on the car side alongside the LEDs and hall effect switch sensor I have a RX RF module for 315mhz and a TX RF module for 433mhz

what i am doing is reading the data from the hall effect switch convert it to Speed then send this value by the RF to the controller and see this value on the LCD 16x2 and from the controller i can turn the LEDs on and off on the car

I attached every component now and i tested everything individually while everything is attached together

For the codes i write codes in which i am sending and receiving on every part (car and controller) so each one is sending and receiving, the codes compiled but did not work means nothing happened so i need your help to identify the problem.

I made some suggestion that might be the problem but still didn't get anything :
first i assumed these 2 lines should be put at the end of the void loop() function

 vw_send((uint8_t*) & TransmittingArray, sizeof(TransmittingArray));
 vw_wait_tx();

then i thought about this line of code might be making some problem by the wait

vw_wait_tx();

here are the codes for the Controller part :

//Sketch of the Controller of the RC car - Firas Helou
//Version September 6 2015

// include the libraries code for LCD and wireless RF Links :
#include <LiquidCrystal.h>
#include <VirtualWire.h>


const byte Red_LED = 2; //Top LEDs ON/OFF indicator
const byte Blue_LED = 4; //Bottom LEDs ON/OFF indicator

const byte TX_Pin = 3; //TX that sends data from the controller to the car
const byte RX_Pin = 5; //RX that receives data sent from the car

const byte RedLeds_Button = 6; //Push Button that turns the Top red LEDs on
const byte BlueLeds_Button = 7; //Push Button that turns the Bottom blue LEDs on

//String TopLed = "";
//String BottomLed = "";

LiquidCrystal lcd(8, 9, 10, 11, 12, 13); //defining the LCD pins

//controlling transmitter initially 12 - TX
int transmittingArray[5];

boolean lastRedLed = LOW;
boolean currentRedLed = HIGH;
boolean RedLedOn = false;

boolean lastBlueLed = LOW;
boolean currentBlueLed = HIGH;
boolean BlueLedOn = false;

byte valRedLedButton = 0;  
byte valBlueLedButton = 0;

//controlling receiver - RX
int receivingArray[5];

//letter O
byte letter_O[8] = { 
 0b01110,
 0b10001,
 0b10001,
 0b10001,
 0b10001,
 0b10001,
 0b01110,
 0b00000
};

//letter N
byte letter_N[8] = {
 0b10001,
 0b10001,
 0b11001,
 0b10101,
 0b10011,
 0b10001,
 0b10001,
 0b00000
};

//letter F
byte letter_F[8] = {
 0b11111,
 0b10000,
 0b10000,
 0b11110,
 0b10000,
 0b10000,
 0b10000,
 0b00000
};

//empty
byte empty[8] = {
 0b00000,
 0b00000,
 0b00000,
 0b00000,
 0b00000,
 0b00000,
 0b00000,
 0b00000
};

void setup() {
  lcd.createChar(0,letter_O); // define our characters into the sketch as variables
  lcd.createChar(1,letter_N);
  lcd.createChar(2,letter_F);
  lcd.createChar(3,empty);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  
  lcd.setCursor(3, 0);
  lcd.print("KM/H:");
  
  //Transmitter setup
  vw_set_tx_pin(TX_Pin); //RF sending pin 
  vw_setup(2000); // Bits per sec
  
  vw_set_rx_pin(RX_Pin);
  vw_rx_start(); 
  
  pinMode( RedLeds_Button, INPUT_PULLUP ); //RedLeds Button
  pinMode( BlueLeds_Button, INPUT_PULLUP ); //BlueLeds Button
  pinMode( Red_LED, OUTPUT ); //Red Led indicator Top LEDs
  pinMode( Blue_LED, OUTPUT ); //Blue Led indicator Bottom LEDs
    
}

//Debouncing function
boolean debounce(boolean last, int button)
{
  boolean current = digitalRead(button);
  if(last != current)
  {
    delay(5);
    current = digitalRead(button);
  }
  return current;
}

//Main Loop
void loop()
{  
  currentRedLed = debounce(lastRedLed, RedLeds_Button);
  currentBlueLed = debounce(lastBlueLed, BlueLeds_Button);
  
  if(lastRedLed == HIGH && currentRedLed == LOW){
    
    RedLedOn = !RedLedOn;
    valRedLedButton = 1;
  }else if(lastRedLed == LOW && currentRedLed == HIGH){
    valRedLedButton = 0;
  }
    
  lastRedLed = currentRedLed;
  digitalWrite(Red_LED, RedLedOn);
  
  lcd.setCursor(0, 1);
  lcd.print("T-L:");
  if(RedLedOn == HIGH){
    //TopLed = "ON ";
    lcd.setCursor(4, 1);
    lcd.write(3);
    lcd.setCursor(5, 1);
    lcd.write((byte)0);
    lcd.setCursor(6,1);
    lcd.write(1);
    
  }else if(RedLedOn == LOW){
    //TopLed = "OFF";
    lcd.setCursor(4, 1);
    //lcd.print(TopLed);
    lcd.write((byte)0);
    lcd.setCursor(5,1);
    lcd.write(2);
    lcd.setCursor(6,1);
    lcd.write(2);
  }
  

  if(lastBlueLed == HIGH && currentBlueLed == LOW){
    
    BlueLedOn = !BlueLedOn;
    valBlueLedButton = 1;
  }else if(lastBlueLed == LOW && currentBlueLed == HIGH){
    valBlueLedButton = 0;
  }
    
  lastBlueLed = currentBlueLed;
  digitalWrite(Blue_LED, BlueLedOn);
  
  lcd.setCursor(9, 1);
  lcd.print("B-L:");
  if(BlueLedOn == HIGH){
    //BottomLed = "ON";
    lcd.setCursor(13, 1);
    lcd.write(3);
    lcd.setCursor(14, 1);
    
    lcd.write((byte)0);
    lcd.setCursor(15,1);
    lcd.write(1);
    
  }else if(BlueLedOn == LOW){
    lcd.setCursor(13, 1);
    lcd.write((byte)0);
    lcd.setCursor(14,1);
    lcd.write(2);
    lcd.setCursor(15,1);
    lcd.write(2);
  }
  
  
  
  transmittingArray[0] = valRedLedButton;
  transmittingArray[1] = valBlueLedButton;
  
  vw_send((uint8_t*) & transmittingArray, sizeof(transmittingArray));
  vw_wait_tx(); 
  
}// --- end of main Loop

Codes for the car are in the first comment

here are the codes for the car part

//RC car sketch 
//Version 7 September 2015
// -- By Firas Helou


//include library
#include <VirtualWire.h>

//Defining the Shift Register Data
byte latchPin = 4;
byte clockPin = 5;
byte dataPin = 6;

byte serialbit;
byte pickabit;
byte intensitybyte;
byte dwellReps;  // fewer dwellReps == faster
byte line;

byte frame [9][8] = {
                      {0b00000001,0,0,0,0,0,0,0},
                      {0b00000001,0b00000010,0,0,0,0,0,0},
                      {0b00000001,0b00000010,0b00000011,0,0,0,0,0},
                      {0,0b00000001,0b00000010,0b00000011,0,0,0,0},
                      {0,0,0b00000001,0b00000010,0,0,0,0},
                      {0,0,0,0b00000011,0,0,0,0},
                      {0,0,0b00000011,0b00000010,0,0,0,0},
                      {0,0b00000011,0b000000010,0b00000001,0,0,0,0},
                      {0b00000010,0b00000001,0,0,0,0,0,0}
                      
                      
                    };

byte intensity [20] = {0b00111110,0b00111100,0b00111100,0b00111100,
                       0b00111000,0b00111000,0b00111000,0b00111000,
                       0b00111000,0b00110000,0b00100000,0b00100000,
                       0b00100000,0b00100000,0b00100000,0b00100000,
                       0b00100000,0b00100000,0b00100000,0b00100000
                     };
                     
                     
//Defining the Hall Effect Data
byte HallEffectPin = 2;

const unsigned long wheel_circumference = 1500UL * 2UL * 31416UL;

unsigned long Speed = 0;
unsigned long PrevSpeed = 0;

volatile byte hall_rising = 0; // interrupt flag
volatile unsigned long irqMicros;

unsigned long startMicros;
unsigned long elapsedMicros;

unsigned long ledFlashStartMillis;
const unsigned long ledFlashWaitMillis = 10;

unsigned long displayStartMillis;
const unsigned long displayWaitMillis = 200;


//Defining receiving RX
int receivingArray[2];
//byte receivingPin = 9;

int valRedLed = 0;
int valBlueLed = 0;

//Defining trasmitter TX
int TransmittingArray[2];
//byte transmittingPin = 3;

//Blue Leds 
byte BlueLED_pin1 = 7;
byte BlueLED_pin2 = 8;
byte BlueLED_pin3 = 11;
byte BlueLED_pin4 = 12;


void wheel_IRQ()
{
  irqMicros = micros();
  hall_rising = 1;
}


void setup(){
  
  pinMode( HallEffectPin, INPUT_PULLUP );
  
  pinMode(BlueLED_pin1, OUTPUT);
  pinMode(BlueLED_pin2, OUTPUT);
  pinMode(BlueLED_pin3, OUTPUT);
  pinMode(BlueLED_pin4, OUTPUT);
  
  //Shift Register Pins
  pinMode(latchPin,OUTPUT);
  digitalWrite(latchPin,LOW);
  pinMode(clockPin,OUTPUT);
  digitalWrite(clockPin,LOW);
  pinMode(dataPin,OUTPUT);
  digitalWrite(dataPin,LOW);
  
  
  vw_set_tx_pin(3); //TX sending pin 
  vw_setup(2000); // Bits per sec
  
  vw_set_rx_pin(9); //RX receiving pin
  vw_rx_start();
  
  attachInterrupt( 0, wheel_IRQ, RISING ); // pin 2 looks for LOW to HIGH change
}

void loop(){
  
  //Hall Effect Speedometer Section
  if ( hall_rising == 1 )
    {
      elapsedMicros = irqMicros - startMicros;
      startMicros = irqMicros;
  
      ledFlashStartMillis = millis();
      hall_rising = 2;
    }
    else if  ( hall_rising == 2 )
    {
      if ( millis() - ledFlashStartMillis >= ledFlashWaitMillis )
      {
        hall_rising = 0;
      }
    }///end of first if and if else statement
  
    // print speed 1000/Wait (5 times per second)
    if ( millis() - displayStartMillis >= displayWaitMillis )
    {
      
      Speed = wheel_circumference / elapsedMicros; //speed = distance / time
  
      displayStartMillis += displayWaitMillis;
      if ( Speed != PrevSpeed )
      {
        Speed = Speed*3600/1000000; //this converts the speed from mm/s to Km/h
        
      }
  
      PrevSpeed = Speed;
   }// end of second if statement ( millis() - displayStartMillis ...
   
   
   //Trasmitting Data from the Speed data
   TransmittingArray[0] = Speed;
   vw_send((uint8_t*) & TransmittingArray, sizeof(TransmittingArray));
   vw_wait_tx(); 
   
   //Receiving Data
   uint8_t buflen = VW_MAX_MESSAGE_LEN;
   uint8_t buf[buflen];
   
   if (vw_get_message(buf, &buflen)) // Non-blocking
   {
    memcpy (& receivingArray, buf, buflen);
    valRedLed = receivingArray[0];
    valBlueLed = receivingArray[1];
    
    if(valRedLed == 1){
      
      for(line=0; line<9; line++)
      {
        for(dwellReps=0; dwellReps<45; dwellReps++)
        // fewer dwellReps == faster  
        {
          
          for(intensitybyte=0; intensitybyte<20; intensitybyte++)
          {
            for (pickabit=0; pickabit<8; pickabit++)
            {
              serialbit = bitRead(intensity[intensitybyte],frame[line][pickabit]);
              digitalWrite(dataPin,serialbit);
              clockit();
            }
            
            latchit();
          
          } // end of third for loop
        } // end of second for loop
      } // end of first for loop
      
    }//end of valRedLed if() Statement
    
    if(valBlueLed == 1){
    
      digitalWrite(BlueLED_pin1, HIGH);
      digitalWrite(BlueLED_pin2, HIGH);
      digitalWrite(BlueLED_pin3, HIGH);
      digitalWrite(BlueLED_pin4, HIGH);
      
    }else if(valBlueLed == 0){
      
      digitalWrite(BlueLED_pin1, LOW);
      digitalWrite(BlueLED_pin2, LOW);
      digitalWrite(BlueLED_pin3, LOW);
      digitalWrite(BlueLED_pin4, LOW);
      
    }//end of valBlueLed if() and else if() Statement
    
   }//end of get_message Receiving
   
  
}//----end of main loop

// ----------------- support functions ------------------
void clockit ()
{
  digitalWrite(clockPin,HIGH);
  digitalWrite(clockPin,LOW); 
}  

void latchit ()
{
  digitalWrite(latchPin,HIGH);  // make a function
  digitalWrite(latchPin,LOW);   // make a function  
}

No one else has ever gotten this to work, since VirtualWire is either sending or receiving. It can't be doing both at once.

You REALLY need transceivers.

PaulS:
No one else has ever gotten this to work, since VirtualWire is either sending or receiving. It can't be doing both at once.

You REALLY need transceivers.

but why? i mean the arduino is what tell which pin comes first :confused:

I have no experience of the devices you are using and I have generally found @PaulS to give good advice.

If VirtualWire can only send or receive I wonder if you could get a system to work in which there is a well defined process whereby one end transmits and the other receives and then they switch around.

Whatever I was doing (with your devices or with transceivers) I would start with some very simple code that sends something like 'A' and replies with 'AA'. Get the basic communication working reliably before asking it to handle useful data.

...R

Robin2:
I have no experience of the devices you are using and I have generally found @PaulS to give good advice.

If VirtualWire can only send or receive I wonder if you could get a system to work in which there is a well defined process whereby one end transmits and the other receives and then they switch around.

Whatever I was doing (with your devices or with transceivers) I would start with some very simple code that sends something like 'A' and replies with 'AA'. Get the basic communication working reliably before asking it to handle useful data.

...R

yes you're right i was doing that with simple code, so about that, would i get the speedometer to work fine or it will have delay between the actual speed of the car and the speed i get on the LCD 16x2 ?

firashelou:
yes you're right i was doing that with simple code, so about that, would i get the speedometer to work fine or it will have delay between the actual speed of the car and the speed i get on the LCD 16x2 ?

I have no idea. You will have to experiment to find out.

My experience is limited to 2.4GHz transceivers. The NRF24 modules are not expensive.

...R

Robin2:
I have no idea. You will have to experiment to find out.

My experience is limited to 2.4GHz transceivers. The NRF24 modules are not expensive.

...R

aha about making a mechanism for send and receive you mean like send, delay(0.1) and after receive and then start again ?

you mean like send, delay(0.1) and after receive and then start again ?

Since delay() takes a long int value, no. delay(0) is stupid.

firashelou:
aha about making a mechanism for send and receive you mean like send, delay(0.1) and after receive and then start again ?

NO. For a start, delay() only takes whole numbers.
Secondly I try never to use delay() because the Arduino can do nothing during a delay. Use millis() to manage timing as illustrated in Several Things at a Time

Thirdly, and most importantly, what I had in mind is that the business of sending and receiving would be used to inform each device to switch role. So, for example, if A is due to send and B is listening, as soon as A has sent its message it will switch to listening. And as soon as B has received a message it will know it is its turn to send. Then A will keep listening until it receives a message from B. etc etc.

In that system the switching of roles is not governed by time.

However it runs the risk of the two devices getting out of sync and both listening (or sending) at the same time and waiting forever. Perhaps you could arrange things so there should always be a message within X millisecs (X might be 200 or 2000) and if no message is received A will become a sender and B a listener. But I could see myself spending a good bit of time figuring out how to make that work reliably.

...R

Robin2:
NO. For a start, delay() only takes whole numbers.
Secondly I try never to use delay() because the Arduino can do nothing during a delay. Use millis() to manage timing as illustrated in Several Things at a Time

Thirdly, and most importantly, what I had in mind is that the business of sending and receiving would be used to inform each device to switch role. So, for example, if A is due to send and B is listening, as soon as A has sent its message it will switch to listening. And as soon as B has received a message it will know it is its turn to send. Then A will keep listening until it receives a message from B. etc etc.

In that system the switching of roles is not governed by time.

However it runs the risk of the two devices getting out of sync and both listening (or sending) at the same time and waiting forever. Perhaps you could arrange things so there should always be a message within X millisecs (X might be 200 or 2000) and if no message is received A will become a sender and B a listener. But I could see myself spending a good bit of time figuring out how to make that work reliably.

...R

ok so for example switching in the setup() function ?

and what about the wait() function after TX ?

one more thing, do you think this would work if i need to make a speedometer sending data from the car and reading live feed
and if i need to click a button on the controller at the same time ?

Robin2:
NO. For a start, delay() only takes whole numbers.
Secondly I try never to use delay() because the Arduino can do nothing during a delay. Use millis() to manage timing as illustrated in Several Things at a Time

I like your example very simple and nice to understand :smiley: thanks for that :slight_smile:

and what about the wait() function after TX ?

If you mean this line
vw_wait_tx();
I have no idea what it is for - I presume it is part of the library you are using.
My guess is that it waits until the stuff is transmitted - but you need to read the library documentation

one more thing, do you think this would work if i need to make a speedometer sending data from the car and reading live feed
and if i need to click a button on the controller at the same time ?

You need to explain this in a great deal more detail before I can make sense of it. You are making the common mistake of assuming I know all the stuff that you know about your project.

I can't overstate what I said in Para 3 of Reply #4. Build your project in small pieces and get each piece working before you move to another part. See Planning and Implementing a Program

...R

Robin2:
If you mean this line
vw_wait_tx();
I have no idea what it is for - I presume it is part of the library you are using.
My guess is that it waits until the stuff is transmitted - but you need to read the library documentation
You need to explain this in a great deal more detail before I can make sense of it. You are making the common mistake of assuming I know all the stuff that you know about your project.

I can't overstate what I said in Para 3 of Reply #4. Build your project in small pieces and get each piece working before you move to another part. See Planning and Implementing a Program

...R

what i am doing is :
i have an RC car small 20 cm which has a controller of forward/backward and left/right
what i did is i made a box from cardboard on which i have 2 push buttons and 1 LCD 16x2 and in it there is 1 arduino that sends data after i click the push buttons,
on the car i will have a standalone arduino, 1 hall effect sensor on 1 rear wheel, 4 LEDs red controlled by shift register, 4 LEDs blue connected directly to the arduino

now when i click 1 of the buttons the red LEDs should go on or off
and if i click second push buttons blue LEDs should go on or off
the LCD on the controller should receive live feedback of the speed of the car when in action and when not it's 0 of course

great Thread by the way thanks for that :slight_smile:

firashelou:
what i am doing is :
i have an RC car small 20 cm which has a controller of forward/backward and left/right
what i did is i made a box from cardboard on which i have 2 push buttons and 1 LCD 16x2 and in it there is 1 arduino that sends data after i click the push buttons,
on the car i will have a standalone arduino, 1 hall effect sensor on 1 rear wheel, 4 LEDs red controlled by shift register, 4 LEDs blue connected directly to the arduino

I have used colours to identify what I see as 7 different things that you need to learn how to do - one at a time. When you can do each of them on its own it will be time to bring them together into a single program.

And there is an eighth thing - communication between the Arduinos.

...R

Robin2:
I have used colours to identify what I see as 7 different things that you need to learn how to do - one at a time. When you can do each of them on its own it will be time to bring them together into a single program.

And there is an eighth thing - communication between the Arduinos.

...R

yes i did learn each one, now the problem is with the combination

i checked your post the one that explains how to organize it's quite amazing and helpful

thanks for that :smiley:

firashelou:
yes i did learn each one, now the problem is with the combination

Good. That was not clear from earlier Posts.

However I don't think you have got the simple communications working yet ? If you have, please post the working code.

...R

Robin2:
Good. That was not clear from earlier Posts.

However I don't think you have got the simple communications working yet ? If you have, please post the working code.

...R

if you mean only 1 TX and 1 RX yes sure i did even from last year but i posted other post and it was a hardware problem i don't know why i did not see it before, now i am using different colors for wires and making a check many times

about 2 TX and 2 RX well not yet i am still thinking about it and still reading and understanding your post
nevertheless i know these basics but the problem i don't have the habit to use them the functions and this method so now i am starting to program my head to think this way :slight_smile:

so thanks for posting that and if you have more posts like these ones please point at it here :slight_smile:

firashelou:
about 2 TX and 2 RX well not yet

That's what I was thinking about.

I have not used VirtualWire so I don't know how it compares to Serial I/O. However the concept of enclosing data between start- and end-markers in the 3rd example in Serial Input Basics will probably be applicable. It will significantly reduce the probability of mis-interpreting data.

...R

Hi,
What TX and Rx units are you using and what is the Tx/Rx baud rate between them?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom.... :slight_smile: