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

}




14 June, 2010

My alarm clock

I have tested using a transistor to power a loud speaker louder than what the arduino can do itself. Here is the code I made it's very simple.  I simple set it on with the reset button and 8 hours later its time to get up.


unsigned long time = 28800000; // this is eight hours in ms (1000*60*60*8)
int alarm = 12;  //the toneMeoldy library is udes so that the speaker makes a noise audible to human ear


void setup(){
  pinMode (alarm, OUTPUT);
}
void loop(){
  delay(time);
  digitalWrite(alarm, HIGH);
}