Help with RC to autonomous operation

Hi everyone!

I hacked a small rc car transmitter and I am now controlling the car using my arduino UNO R3.

This is the program that I have written for the rc car, it basically controls the car autonomously.

How my program currently works:

You press a push button to start the program. After you pressed the button, the 3 LED's count down and then the car starts moving by setting the different OUTPUT's to a HIGH or LOW STATE. This is really hard to program as you will see below.

I would like not to use the digitalWrite function everytime I tell the car in which direction it should go. If possible, could you rewrite the program for me so that programming a route for the rc car would be easy.

Hi,

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

also go back and edit the subject of this thread to something like.

"Help with RC to autonomous operation"

You may get more interest, the members of the forum do not read every new post, you have to attract the attention of those that can help you..

Tom... :slight_smile:

THE SKETCH:

const int Button = 8;
int ButtonState = 0;

int Forward = 9;
int Backward = 10;
int Right = 11;
int Left = 12;

int green = 3;
int yellow = 4;
int red = 5;



void setup(){
  
  Serial.begin(9600);
 
  pinMode(Button, INPUT);
  pinMode(Forward, OUTPUT);
  pinMode(Backward, OUTPUT);
  pinMode(Right, OUTPUT);
  pinMode(Left, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(red, OUTPUT);
}

void loop(){
  
ButtonState = digitalRead(Button);
 
 if (ButtonState == HIGH) {
 
 digitalWrite(green, HIGH);
 delay(600);
 digitalWrite(green, LOW);
 delay(600);
 digitalWrite(yellow, HIGH);
 delay(600);
 digitalWrite(yellow, LOW);
 delay(600);
 digitalWrite(red, HIGH);
 delay(600);
 digitalWrite(red, LOW);
 delay(600);
   
 digitalWrite(Forward, HIGH);
 Serial.println("Forward");
 digitalWrite(green, HIGH):
 delay(1000);                  //Forward
 digitalWrite(Forward, LOW);

 digitalWrite(Right, HIGH);
 digitalWrite(Forward, HIGH);
 Serial.println("Right Turn");
 delay(3000);                  //Right
 digitalWrite(Right, LOW);
 digitalWrite(Forward, LOW);
 Serial.println("STOP");
 digitalWrite(green, LOW);
 digitalWrite(red, HIGH);
 delay(1000);
 digitalWrite(red, LOW);

 digitalWrite(Backward, HIGH);
 Serial.println("Backwards");
 digitalWrite(yellow, HIGH);
 delay(1000);                   //Backwards
 digitalWrite(Backward, LOW);
 digitalWrite(yellow, LOW);
 Serial.println("STOP");
 digitalWrite(red, HIGH);
 delay(500);
 digitalWrite(red, LOW);
 digitalWrite(Left, HIGH);
 
 digitalWrite(Backward, HIGH);
 digitalWrite(yellow, HIGH);

 Serial.println("Backward Left");
 delay(3000);                     //Backwards Left
 digitalWrite(Left, LOW);
 digitalWrite(Backward, LOW);
 Serial.println("STOP");
 
 
  digitalWrite(Right, HIGH);
 digitalWrite(Backward, HIGH);

 Serial.println("Backward Right");
 delay(3000);                     //Backwards Left
 digitalWrite(Right, LOW);
 digitalWrite(Backward, LOW);
 Serial.println("STOP");
 digitalWrite(yellow, LOW);
 

 
 digitalWrite(Left, HIGH);
 digitalWrite(Forward, HIGH);
 Serial.println("Left Turn");
 digitalWrite(green, HIGH);
 delay(4000);                   //Forward Left
 digitalWrite(Left, LOW);
 digitalWrite(Forward, LOW);
 Serial.println("STOP");
 
 

 
 digitalWrite(Right, HIGH);
 digitalWrite(Forward, HIGH);
 Serial.println("Right Turn");
 delay(3000);                   //Forward Left
 digitalWrite(Left, LOW);
 digitalWrite(Forward, LOW);
 Serial.println("STOP");

 digitalWrite(Right, HIGH);
 digitalWrite(Forward, HIGH);
 Serial.println("Right Turn");
 delay(3000);                  //Right
 digitalWrite(Right, LOW);
 digitalWrite(Forward, LOW);
 Serial.println("STOP");
 
 
 digitalWrite(Forward, HIGH);
 Serial.println("Forward");
 delay(1000);                  //Forward
 digitalWrite(Forward, LOW);
 digitalWrite(green, LOW);
 digitalWrite(red, HIGH);
 Serial.println("STOP");
 delay(1000);
 digitalWrite(red, LOW);
 delay(500);
 digitalWrite(red, HIGH);
 delay(500);
 digitalWrite(red, LOW);
 delay(500);
 digitalWrite(red, HIGH);
 delay(500);
 digitalWrite(red, LOW);
 delay(500);
 digitalWrite(red, HIGH);
 delay(500);
 digitalWrite(red, LOW);
 delay(500);
 
 
 }
}

Hi,
How have you got the motors wired to the arduino and how are you powering the project?

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:

Hi Tom

What I did is; I wired 2 wires in parallel to each of the 4 push buttons on the transmitter (Forward, Backwards, Right, Left) I then connected each pair of wires to it's own relay output.(Whenever the two wires touch each other the transmitter gives the signal) I first tried to hook each of them directly to an OUTPUT of the arduino and GND, that did not work, there was some sort of interference with the signals. Now I'm using a 5v relay for each push button.(2 wires to each relay OUTPUT and the relay then gets connected to the arduino) When the relay gets activated by the arduino it closes the transmitter circuit and gives the signal to go Forward, Backwards, Left, Right.

There is also 3 LED's wired to the arduino, they just indicate whether the car is moving forward backwards or standing still. And act as a "TIMER" before the program starts running.

I am currently powering the whole circuit directly from the USB port. But my project is built on a breadboard so I can pretty much power it from any power source.

I think the answer is to just pack it into nice functions.

something like
driveForward();
driveStop();
driveRight();
driveLeft();
driveBack();
driveBackLeft();
driveBackRight();

And take the necessary steps inside there.

And while you're at it, try to avoid the delay. In the meantime the Arduio does nothing. For now it appears to be okay but if you want to do more you run into trouble. See Blink without delay.

Hi,
If its autonomous, why have you got a transmitter.

Can you post a picture of your project and a diagram of your circuit please.

Tom...... :slight_smile:

He just has an Arduino wired to the transmitter. It autonomous as in, no interaction from a human. It does not mean it can't use a transmitter. A automatic lawnmower often needs a fence wire as well :smiley:

Yes!! The plan was to build a programmable transmitter. It does what I wanted it to do, but I would like a better program, where I can just call a certain function and then it performs the task. Here is a picture:

file:///C:/Documents%20and%20Settings/User/Desktop/Photo0112.jpg

You can't like a local photo, you need to upload it to dropbox, Gdrive or any other photo site first.

But have you read my command about making functions?

Hi Septallion, yes, I read your command. How exactly will it work?

How to write and use functions for the Arduino.

Can't make it any easier ::slight_smile:

Does this go in the setup part?:

Void Setup(){

driveForward();
driveStop();
driveRight();
driveLeft();
driveBack();
driveBackLeft();
driveBackRight();

And then I call the functions in the loop?:

Void Loop(){

driveForward;
delay(1000)
driveBackward;
delay(1000);

Thanks!

Just keep on reading....

Finally! I found the perfect solution:

/*

Car Test
Makes the modified RC car go in a figure 8.
Plug the striped white wires into the Arduino pins as
*/
int forward = 12; // forward pin
int reverse = 11; // reverse pin
int left = 10; // left pin
int right = 9; // right pin
// The setup() method runs once, when the sketch starts
void setup() {
// initialize the digital pins as an outputs:
pinMode(forward, OUTPUT);
pinMode(reverse, OUTPUT);
pinMode(left, OUTPUT);
pinMode(right, OUTPUT);
}
void go_forward()
{
digitalWrite(forward,HIGH); // turn forward motor on
digitalWrite(reverse,LOW); // turn revers motor off
}
void go_reverse()
{
digitalWrite(reverse,HIGH); // turn reverse motor on
digitalWrite(forward,LOW); // turn forward notor off
}
void stop_car()
{
digitalWrite(reverse,LOW); // turn revers motor off
digitalWrite(forward,LOW); // turn forward motor off
digitalWrite(left,LOW);
digitalWrite(right,LOW);
}
void go_left()
{
digitalWrite(left,HIGH); // turn left motor on
digitalWrite(right,LOW); // turn right motor off
}
void go_right()
{
digitalWrite(right,HIGH); // turn right motor on
digitalWrite(left,LOW); // tune left motor off
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
go_forward();
delay(1000);
go_right();
delay(3000);
go_forward();
delay(1000);
go_left();
delay(3000);
go_forward();
delay(1000);
go_right();
delay(3000);
}

Well done on getting it working.

Finally! I found the perfect solution:

You found a solution, which is a good thing because it is important to have success, but is it perfect ?

Suggestions for improvemts that might not matter in your current program but would be good to know about and use in more complicated ones.

int forward = 12; // forward pin
int reverse = 11; // reverse pin
int left = 10; // left pin
int right = 9; // right pin

Change the names of the variables slightly so that they obviously refer to pins then there is no need for the comments and it will be more obvious what is going on in your functions. Use byte instead of int as the data type unless you are planning to use use an Arduino with more that 16,000 pins. This saves memory which is a precious resource on an Arduino. Make the pin variables into const values. They are not going to change in the program and making them const will prevent that happening anyway. So the code above would become something like.

const byte forwardPin = 12;
const byte reversePin = 11;
const byte leftPin = 10;
const byte rightPin = 9;

Consider turning the program into a "state machine". It sounds scary but isn't. At any time the program will be in one of several states, forward, right, left, stop etc. Have a variable, let's call it state that holds a number corresponding to the current state. Use switch/case to execute the code appropriate to the current state until the required period for that state has elapsed. This means that you cannot use delay() for timekeeping and must use millis() to determine whether the period has elapsed.

Save the start time of the state, set the state number variable, then each time through loop() check whether the required period has elapsed by subtracting the start time from the time now (millis()) and comparing the result with the period. If the period has not elapsed keep going round loop() until it has. When the period elapses change the state number, save the state start time and move to the next state.

Why bother with making such a massive change ? Well, you will learn how to use a state machine which is a very common way to program microcontrollers and learn how to use millis() for timing which allows you to have free running code which the use of delay() precludes. Suppose you wanted to put and emergency stop button on your vehicle or have it continuously look ahead for obstacles. Your current code would mean that it could do that only between calls to delay() which may not be frequently enough. Using mills() for timing means that you could read the stop button or forward distance each time through loop(), perhaps thousands of times per second.

Go on. Give it a go. You know that you want to and you will get plenty of help here.

Note that there are other ways to achieve the same thing using even neater code such as a for loop and arrays of values, but you can move on to that later and learn even more useful techniques.

Yes, that's indeed the way to do it :wink: But now work on your skills.

  1. Make code indentations! They don't cost a damn think and makes code wayyyyy more readable. Same goes for blank lines.
  2. Variable names like forward is kind of vague. Better would be forwardPin. (And it will never change so make it "const byte ForwardPin = 12;" )
  3. It's more default to give functions names as goForward (instead of go_forward).
  4. Next step, Blink without delay :wink:

Thanks guys for the help! I will definitely bring some changes in my program.