27 June, 2010

Wifi RC Car Howto Using WRT54G Openwrt and Arduino

I am currently  (re)working on this project at the moment so watch this space
last updated 3rd March 2011
This post describes how I build a WiFi remote control car using an Arduino, a WRT54G(L/v2) running OpenWRT.

 I found a website that contained information about how remote control cars worked. A guy named Jon has a blog and explains how most remote control cars contain an IC that is responsible for controlling the H Bridge to make the car go backwards forwards left and right.

A lot of the content in this post is inspired by his design.  I however plan to improve the car client software and port the Arduino firmware to the  Arduino MEGA.
This is the drive circuit of my first WiFi Car.  It's RX2 chip is a 'blob' module that has been soldered in.
This second RC car features a RX2 chip exactly the same as Jon's. Much better than my original!


My original car did not use the RX2 chip but it was an alternative chip so some guess work was need to find out which pins did what.  It was pretty much the same except some minor differences.

After poking around sending a HIGH signal and grounding the arduino to the GND pin you can establish what each pin does to the car.  Or you can search the code of the IC to get the PIN layout.
After that I drew a picture of the circuit board to remember which pins where which.

The next problem I faced was getting the Arduino and the WRT54GL router to communicate through serial. Jon only explains how to do this with RS232 serial which is NOT what the USB Arduino uses.

EDIT: Same applies for an Arduino MEGA.

This was a problem because the Arduino uses a 5 V transistor to transistor logic a.ka TTL and the router uses 3.3 V TTL serial communication. I contacted mindkits (an NZ supplier of arduino goodies) to see if they sold any logic level converters but they didn't have any, so I bought them off a an Australian website.  This device is available on SparkFun.com search 'logic level converter'

OpenWRT's wiki explains the pin layout of the serial connection pads on the router.
http://wiki.openwrt.org/oldwiki/OpenWrtDocs/Hardware/Linksys/WRT54GL

My Final Wiring Diagram

Electrical engineers will enjoy this diagram. It follows strict conventions as set in /dev/null.


I used telephone cable to connect the Arduino and soldered over the top of the blob integrated circuit pins. Then I added two LED lights for debugging purposes.




Same thing here but with the better car.


Setting up the Router and Arduino. Old car

A close look of the Arduino and level converter. (Not Really)


Once I had it all wired up and working that night, I was smart enough (in the morning) to connect the SLA battery for the router round the wrong way.  The end result was a WRT54GL with sparks and a hole in the tiny voltage regulator chips plus other unknown to the rest of the board.

After giving up trying to fix the router, I purchased a WRT54G v2 off Trademe and had no trouble installing openwrt and Jon Bennett's car software.


I had also purchased a new remote control car that was half price at 'The Warehouse' because of broken headlights!

Sorry about the quality of the photos as they have been taken with my one and only phone camera.

The stylish interior.



I have then soldered the driving signals to the pins.


The logic level converter is soldered in. Not a good place for it but I was just testing it.

The boot

 Since theses photos I have added a horn and headlights using super bright LEDs that are connected to the remaining Arduino pins.  I still need to purchase a network camera to see where the car is going.  There is a huge wireless network covering the whole school area were I live that would be a cool place to drive it once I have got the camera.


Another big issue is power.  The NiCad batteries supplied with the car struggle to last 20 minutes and need to be replaced with high Lithium Polymer or decent MiMH batteries.

UPDATE 09 June 2011


I can't believe i forgot to include the code in this post.  It is written by Jon Bennett i have simply changed a pin or two and added more comments. 

/*******************************************************************
 * Car WiFi Firmware for Arduino
 * Created By Jon Bennet (http://jbprojects.net)
 * Edited By Tim Sullivan (http://timsarduino.blogspot.com)
 * September, 2010
 * =Arduino Hookup Guide=
 * ---------------------
 * Forward: Digital Pin 8
 * Backward: Digital Pin 9
 * Left: Digital Pin 10
 * Right: Digital Pin 11
 * Green LED: Digital Pin 7
 * Red LED: Digital Pin 6
 * Horn: Digital Pin 5
 * LIGHTS: pin 4
 *
 *******************************************************************/
//debugging is useful to check if the car is reieving a signal from the router.
//this will make the car not operate correctly if enabled though
#define DEBUG 0
//stops program until a starting byte is sent to the arduino
#define WAIT_FOR_START 1

unsigned char incomingByte = 0;
unsigned long loop_count = 0;
unsigned char horn = 32;
unsigned char redLED = 64;
unsigned char greenLED = 128;

unsigned char forward = 1;
unsigned char backward = 2;
unsigned char left = 4;
unsigned char right = 8;

unsigned char PORTB_val;
unsigned char PORTD_val;

unsigned char in_char = 0;

void setup(){
  //PORTD = digital I/O 0-7
  //horn, redLED, greenLED

  pinMode(5, OUTPUT);      // Horn attached to the arduino
  pinMode(6, OUTPUT);      // Red WAIT/DEBUG led
  pinMode(7, OUTPUT);      // Green router ALIVE led
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH); //turn on the headlights.

  //PORTB = digital I/O 8 - 13 


  pinMode(8, OUTPUT);      // Forward signal to car Driver chip.
  pinMode(9, OUTPUT);      // Reverse signal to the car.
  pinMode(10, OUTPUT);     // Left signal
  pinMode(11, OUTPUT);     // Right signal

  Serial.begin(9600);      // set up Serial library at 9600 bps

  PORTD = redLED;           // turn on the red LED

#if DEBUG
    flash_led(3,500);
#endif

  wait_for_start();  //Waits for startup message from router serial port
  //continues after receiving it.
}


void flash_led(unsigned int count, unsigned int rate){
  // debug routine that flashes an LED
  int n_count = 0;

  while (n_count < count)
  {
    n_count++;
    digitalWrite(13, HIGH);       // sets the LED on
    delay(rate);                  // waits for a bit
    digitalWrite(13, LOW);        // sets the LED off
    delay(rate);                  // waits for a bit
  }
}

char get_char(){
  //Function that waits for a character from the serial port
  //If none are received, it returns 0.
  //The timeout is so that if the router stops sending data to the microcontroller,
  //the micrcontroller will stop driving the car, rather than just going forever with
  //the last command.  Timeout is around 250mS.

  while (loop_count < 30000){
    loop_count++;

    if (Serial.available() > 0){
      incomingByte = Serial.read();
      loop_count = 0;
      return incomingByte;
    }
  } 

  loop_count = 0;

#if DEBUG
  Serial.print('X', BYTE);
#endif

  return 0;
}

unsigned char wait_for_start(){
  //Waits for startup message from router serial port
#if WAIT_FOR_START

#if DEBUG
  Serial.println("Waiting...");
#endif

  while(1){
    if (get_char() == 'j' && get_char() == 'b' && get_char() == 'p' && get_char() == 'r' && get_char() == 'o')
    {

#if DEBUG
      Serial.print("Passcode Accepted");
#endif

      return 0;
    }
  }
#endif
}

void loop(){ 
  //Function that processes input from serial port and drives the car based
  //on that input.

  in_char = get_char();

  //Split byte received in to upper and lower halves.
  PORTB_val = in_char & 0x0F;
  PORTD_val = in_char & 0xF0;

  //Make sure the greenLED is turned on now.
  if ((PORTD_val & greenLED) == 0)
  {
    PORTD_val = PORTD_val + greenLED;         
  }

  //The following IF statements are sanity checks to make sure that FORWARD and BACKWARD cannot be on at the same time
  //and that LEFT and RIGHT can't be on at the same time.
  if ((PORTB_val & (left + right)) == (left + right))
  {   
    PORTB_val = PORTB_val - right;   
  }

  if ((PORTB_val & (forward + backward)) == (forward + backward))
  {
    PORTB_val = PORTB_val - backward;
  }

  //Write the processed values to the ports.
  PORTD = PORTD_val;
  PORTB = PORTB_val;

#if DEBUG
  Serial.print(PORTD, HEX);
  Serial.print(PORTB, HEX);
#endif

}




7 comments:

  1. Thanks for the wiring diagram. I'm doing something similar and was looking into ways to connect my arduino to the wrt54g. Do you have the arduino sketch? Would like to see how you interface with the serial via the router. What's new in the project?

    ReplyDelete
  2. I've wired up my logic converter between my Arduino Tx/Rx and my WRT54GL, but I'm unable to get anything out of my serial port on the router... Did you have to do anything special after installing openwrt on the router? I'm trying to use /dev/tty/1 on Serial port 9600.

    ReplyDelete
  3. hi,i have WRT54G v8 and i have logic level converter,i want to connect rhe router to arduino,i installed dd-wrt on the router but the router doesn't support ssh but the router has serial port and jtag,after that adon't know what to do so please help me!!!

    ReplyDelete
    Replies
    1. sorry i forget to write my email:zhiran.taha@yahoo.com

      Delete
  4. without logic level converter can we use another way of max232 max233 ?

    ReplyDelete
  5. awesome blog. thanks for sharing this here. it's really nice to see this awesome blog. it's nice to see this whole diagram. it will help alto of beginners to build their own rc bil.

    ReplyDelete