RF remote-controlled robot car

hello everyone
i’m working on a project to make an rc car controlled by a RF remote controller. my remote controller has 4 buttons (forward, backward, right turn and left turn) to make the robot move, the required button has to be kept pressed and it stops when the button is released. however, i’m having a small problem currently; the car should be moving continuously unless i release my finger from the button but each time i switch it on, it behaves differently, for example if i keep pressing forward button, it moves forward discontinuously, in other words it keeps stopping for a while and moves again like being interrupted. i checked the electronic circuit and the antennas for both transmitter and receiver and both seemed fine.
so can you guys help me out?

transmitter code:

#include <VirtualWire.h>
char *controller;
int forward = 4;
int backward = 3;
int rightTurn = 5;
int leftTurn = 2;
int L = 13; 

int buttonStateForward = 1; 
int buttonStateBackward = 1; 
int buttonStateRightTurn = 1; 
int buttonStateleftTurn = 1; 

void setup() {

Serial.begin (9600);         // Debugging only
Serial.println ("Setup");
pinMode(13,OUTPUT);
pinMode(forward, INPUT);
pinMode(backward, INPUT);
pinMode(rightTurn, INPUT);
pinMode(leftTurn, INPUT);



vw_set_ptt_inverted(true); //
vw_set_tx_pin(9);
vw_setup(2000);// speed of data transfer Kbps
}

void loop(){
buttonStateForward = digitalRead(forward);
buttonStateBackward = digitalRead(backward);
buttonStateRightTurn = digitalRead(rightTurn);
buttonStateleftTurn = digitalRead(leftTurn);

if (buttonStateForward == LOW) {
controller="1" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}
else if (buttonStateForward == HIGH) {
controller="5" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}

if (buttonStateBackward == LOW) {
controller="2" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}
else if (buttonStateBackward == HIGH){
controller="5" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}
if (buttonStateRightTurn== LOW) {
controller="3" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}
else if (buttonStateRightTurn== HIGH) {
controller="5" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}


if (buttonStateleftTurn == LOW) {
controller="4" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}

else if (buttonStateleftTurn == HIGH) {
controller="5" ;
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13,1);
}
  }

receiver code:

#include <VirtualWire.h>

const int IN1 = 5;
const int IN2 = 4;
const int IN3 = 2;
const int IN4 = 3;


void setup()
{
Serial.begin (9600);            // Debugging only
Serial.println ("Setup");
vw_set_ptt_inverted(true); // Required for DR3100
vw_set_rx_pin(12);
vw_setup(2000); // Bits per sec
pinMode(13, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);

vw_rx_start(); // Start the receiver PLL running
}
void loop() {
 uint8_t buf[VW_MAX_MESSAGE_LEN];
 uint8_t buflen = VW_MAX_MESSAGE_LEN;

 if (vw_get_message(buf, &buflen)) { // Non-blocking
   int i;

   digitalWrite(13,HIGH);
   for (i = 0; i < buflen; i ++) {
     Serial.print (buf [i]);
      
     if(buf [i] == '1') {
       forward ();
       Serial.println (" = forward");
      }
      
     if(buf [i] == '2') {
       backward ();
       Serial.println (" = backward");
      }
      
     if(buf [i] == '4') {
       right ();
       Serial.println (" = right");
      }
      
     if(buf [i] == '3') {
      left ();
       Serial.println (" = left");
      }
     if(buf [i] == '5') {
       Stop ();
       
      }
     
      Serial.print(" ");
    }  
    
    Serial.println("");
    digitalWrite(13,LOW);
  }
}
void forward () {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, HIGH);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, HIGH);
}

void backward () {
  digitalWrite (IN1, HIGH);
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, HIGH);
  digitalWrite (IN4, LOW);
}

void right () {
  digitalWrite (IN1, HIGH);
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, HIGH);
}

void left () {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, HIGH);
  digitalWrite (IN3, HIGH);
  digitalWrite (IN4, LOW);
}

void Stop () {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, LOW);
  digitalWrite (IN3, LOW);
  digitalWrite (IN4, LOW);
}

I think you have a logic error in your sending algorithm.

Suppose you have the forward button pressed and none of the other buttons. Each time through the loop, you will send a '1' and a '5' and a '5' and a '5'. The receiving program will then go and then stop and then stop and then stop.

Maybe you should implement some sort of state system so you only send a '1' when the forward button gets pressed, and then wait until it gets released before you send any '5' commands.

Jimmus:
I think you have a logic error in your sending algorithm.

Suppose you have the forward button pressed and none of the other buttons. Each time through the loop, you will send a '1' and a '5' and a '5' and a '5'. The receiving program will then go and then stop and then stop and then stop.

Maybe you should implement some sort of state system so you only send a '1' when the forward button gets pressed, and then wait until it gets released before you send any '5' commands.

I think you are right, that did not come across my mind!
So how to do that? Which function i should use? Or is there any way to replace the '5' command with any other way that stops the car when any button is released?

You're using all the right functions, and sending characters just fine. What you need is different logic to determine when to send the command characters.

There are several ways to do it. They have various advantages and disadvantages. And what are you going to do if two buttons are pressed at the same time?

Here's the easy way:

void loop(){
  if (digitalRead(forward) == LOW) {
    controller="1" ;                      // 1 means forward
    vw_send((uint8_t *)controller, strlen(controller));
    vw_wait_tx();                         // Wait until the whole message is gone
    digitalWrite(13,HIGH);                // Turn on the on-board LED
    while (digitalRead(forward) == LOW)   // Loop here until the button is released
      ;                                   // Do nothing
    controller="5" ;                      // 5 means stop
    vw_send((uint8_t *)controller, strlen(controller));
    vw_wait_tx();                         // Wait until the whole message is gone
    digitalWrite(13, LOW);                // Turn off the on-board LED
  }
...
}

You'll have to do the other three buttons, of course, but they'll be similar.

Jimmus:
You're using all the right functions, and sending characters just fine. What you need is different logic to determine when to send the command characters.

There are several ways to do it. They have various advantages and disadvantages. And what are you going to do if two buttons are pressed at the same time?

Here's the easy way:

void loop(){

if (digitalRead(forward) == LOW) {
    controller="1" ;                      // 1 means forward
    vw_send((uint8_t *)controller, strlen(controller));
    vw_wait_tx();                        // Wait until the whole message is gone
    digitalWrite(13,HIGH);                // Turn on the on-board LED
    while (digitalRead(forward == LOW))  // Loop here until the button is released
      ;                                  // Do nothing
    controller="5" ;                      // 5 means stop
    vw_send((uint8_t *)controller, strlen(controller));
    vw_wait_tx();                        // Wait until the whole message is gone
    digitalWrite(13, LOW);                // Turn off the on-board LED
  }
...
}



You'll have to do the other three buttons, of course, but they'll be similar.

Did not work, it does not stop when i release my finger

Rats. Well, couple of debug questions, then.

The on-board light on the sending Arduino -- does it go on when you press the button? Does it go off when you release?

Is the receiving Arduino connected to a serial monitor? If so, what comes up on the serial monitor screen?