IR controled car

Hello!

I connected an IR sensor to my Arduino, which controls an RC car. Using a rudimentary sketch I was able to get the car to move forward, backward, turn left, right, have speed control and some other things. Now I’m programming a new sketch with more advanced control features.

I use the numerical keys (1-6) from a IR remote to set different speeds to the car. The arrow keys are used to move forward or backward, turn left or right. When the move forward or backward keys are pressed the car starts moving until another stop key is pressed. However I wanted the turn left or right keys to work differently. The car turns left and keeps turning left while I’m pushing the left key (same goes to turn right). When I stop pushing the left key, it automatically stops turning left.

I used the IRremote library. My remote sends 32bit signals, so I use long variables to store my pre-defined key codes (in HEX format) and compare them later. When I press a key the remote sends that key’s code, but if I keep pushing it, it sends a repeat code common to all keys (which in this case is FFFFFFFF).

So, for example, if i press the left key and keep pushing it i will get:
10EF906F
FFFFFFFF
FFFFFFFF
FFFFFFFF

So, my problem: the turn left and right feature doesn’t work. The Arduino receives the left code but completely ignores the repeat code (or so I think). Everything else works as intended and with the first sketch all the features worked, so I know there is nothing wrong with my setup (on the car itself).

Here’s my code:

#include <IRremote.h>

int irPin = 11;
IRrecv irrecv(irPin);
decode_results results;

int fwdPin = 9; //PWM, pin to set the car moving forward
int backPin = 10; //PWM
int leftPin = 2; //pin to turn left
int rightPin = 3;
int turboPin = 4; //not being used

//variable definition to IR signals
long one = 0x10EF38C7; //button 1
long two = 0x10EFB847; //button 2
long three = 0x10EF7887; //buttono 3
long four = 0x10EFF807; //button 4
long five = 0x10EF02FD; //button 5
long six = 0x10EF827D; //button 6

long up = 0x10EF609F; //move forward button
long down = 0x10EFB04F; //move backward button
long left = 0x10EF906F; //turn left button
long right = 0x10EF50AF; //turn right button
long ENTER = 0x10EF9867; //stop the car
long repeat = 0xFFFFFFFF; //repeat signal

//initial car speed
int currentSpeed = 0;

//receives an IR signal and compares it with the input value. Returns true if they match and prepares to receive a new IR signal with irrecv.resume()
boolean check(long hex){
  if (irrecv.decode(&results)){
    Serial.println(results.value, HEX);
    if (results.value == hex){
      irrecv.resume();
      return true;
    }
  }
}

//changes the speed of the car
void changeSpeed(){
  if (irrecv.decode(&results)){
    if (results.value == ENTER){
      currentSpeed=0;
      analogWrite(fwdPin, 0);
      analogWrite(backPin, 0);
      Serial.println("Car stoped and speed set to 0.");
    }
    if (results.value == one){
      currentSpeed=100;
      Serial.println("Speed changed to 100.");
    }
    if (results.value == two){
      currentSpeed=130;
      Serial.println("Speed changed to 130.");
    }
    if (results.value == three){
      currentSpeed=160;
      Serial.println("Speed changed to 160.");
    }
    if (results.value == four){
      currentSpeed=190;
      Serial.println("Speed changed to 190.");
    }
    if (results.value == five){
      currentSpeed=220;
      Serial.println("Speed changed to 220.");
    }
    if (results.value == six){
      currentSpeed=255;
      Serial.println("Speed changed to 255.");
    }
    irrecv.resume();
  }
}

void setup()
{
  pinMode(fwdPin, OUTPUT);
  pinMode(backPin, OUTPUT);
  pinMode(leftPin, OUTPUT);
  pinMode(rightPin, OUTPUT);
  pinMode(turboPin, OUTPUT);
  
  Serial.begin(9600);
  
  irrecv.enableIRIn(); // Start the IR receiver
}

void loop() {
  changeSpeed(); //checks for changeSpeed signal from remote
  
  if (irrecv.decode(&results)){
    
    //car moving forward with currentSpeed
    if (results.value == up){
      Serial.print("The car is moving forward with speed: ");
      Serial.println(currentSpeed, DEC);
      analogWrite(backPin, 0); //to make sure the car doesn't try to move forward and backward at the same time
      analogWrite(fwdPin, currentSpeed);
    }
    
    //car moving backward with currentSpeed
    if (results.value == down){
      Serial.print("The car is moving backward with speed: ");
      Serial.println(currentSpeed, DEC);
      analogWrite(fwdPin, 0); //to make sure the car doesn't try to move forward and backward at the same time
      analogWrite(backPin, currentSpeed);
    }
    
    //turns left when left signal is received and continues turning left while left or repeat signal is received
    if (results.value == left){
      Serial.println("The car is turning left.");
      digitalWrite(rightPin, LOW); //to make sure the car doesn't try to turn left and right at the same time
      do{
        digitalWrite(leftPin, HIGH);
      } while(check(repeat)==true || check(left)==true);
      digitalWrite(leftPin, LOW);
    }
    
    //turns left when right signal is received and continues turning right while right or repeat signal is received
    if (results.value == right){
      Serial.println("The car is turning right.");
      digitalWrite(leftPin, LOW); //to make sure the car doesn't try to turn left and right at the same time
      do{
        digitalWrite(rightPin, HIGH);
      } while(check(repeat)==true);
      digitalWrite(rightPin, LOW);
    }    
  }  
}

I attached both my current and first sketch. The first sketch has Portuguese commentaries, but that sketch is of no relevance.

Any sugestions?

Thanks in advance,
Chiroptera

rc_ir.pde (2.56 KB)

rc_ir_v3.pde (3.95 KB)

We can't see the serial output that you are seeing. Do you indeed get the repeat code?

In loop(), the code for turning left and right is not identical, except for pin. Shouldn't it be?

You call irrecv.decode() and irrecv.resume() in multiple places. I would think that calling them exactly once each, at the start and at the end of loop, would be better.

In this sketch I’m not receiving that output. That output is from the example sketch in the IRremote library that receives the IR signals.

The left and right code are a bit different but it shouldn’t make a difference, and yes they should be identical. I was trying out different things to see if the problem was on the loop condition. What I did on the left code was to make it continue in the loop in case it received a left IR code.

The problem with calling only once those methods is that I can’t make a loop the force the car to keep turning left (or right) until I release the button. That is also the reason I created the subroutine check() to receive and compare IR codes. So in the beginning of loop() I check for an initial IR signal, and if it happens to be a left or right code it stays “trapped” inside those loops while it receives the left/right or repeat signal. But what really happens is that the car turns left a bit, but then stops. When I push the left button I only get 1 IR left code on my Serial monitor (which corresponds to the first time it goes through the loop condition), instead of receiving a stream of codes (repeat mostly).

I’m gonna try to think on a different way to accomplish that…

You didn't answer the question about whether you actually receive the repeat code.

You could simply set the pin HIGH for a left or right turn, then press another button to stop turning, and not worry about the repeat bit.

With this sketch I didn’t get that output. That is the output I receive with another sketch that only receives IR signals.

What you suggested was what my previous sketch did. But to control an RC car it’s not really practical to do that.

I do not understand what is wrong with that do while loop. It should work.

With this sketch I didn't get that output.

Does this mean that you do not receive the repeat code?

If you don't, then nothing you do in the code is going to make it appear.

The FFFFFF is the remote its not a problem specific to your setup most controllers will give this the second time. The best option is what PaulS has suggested

You could simply set the pin HIGH for a left or right turn, then press another button to stop turning, and not worry about the repeat bit.

I have made a similar program here if u want it as an example to setup the library

void loop () {
  //ir receiver bit
  if (irrecv.decode(&results)) {
    switch (results.value) {
   
    case Button_1:
      Serial.write("Button 1 pressed\n");
       scrollthroughled ();
       break;
    

    case Button_2:
      Serial.write("Button 2 pressed\n");    
       scrollupanddown ();
    break;
   
    case Button_3:
      Serial.write("Button 3 pressed\n");    
       spinthroughlayers ();
       break;
    
    
       case OFF:
      Serial.write("ON/OFF pressed\n");    
        allOff();
        break;
    
    default :
   Serial.println(results.value, HEX);
    }
    irrecv.resume(); // Receive the next value

  }
  
}

Ive only included the loop void here the rest is irrelevant to your project, but the full code is here.. http://pastebin.com/VwihmR13

Here u could replace each case with ur functions.. or code then use off as ur cancel left... or cancel right