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);
}

27 May, 2010

Tasks 19-30

Tasks 19 to 30

19) Write a program to get one led to increase its rate of blinking from 100ms to1 sec.

int t = 100; //set the inital value of t as 100ms.
int led = 13;

void setup(){
pinMode(led, OUTPUT);
}

void loop() {
digitalWrite(led, HIGH);
delay(t);
digitalWrite(led, LOW);
delay(t);
t = t + 100; //increment t by 100 each time that the code is run.
}

20) Same as 19 but this time ramp up the rate from 10ms to 1 sec then back down again.

int led = 13;

void setup(){
pinMode(led, OUTPUT);
}

void loop(){
for(int t = 10; t <1000; t+100){
digitalWrite(led, HIGH);
delay(t);
digitalWrite(led, LOW);
delay(t);
}

for( t= 1000; t >100; t-100){
digitalWrite(led, HIGH);
delay(t);
digitalWrite(led, LOW);
delay(t);
}
}

21) Write a program to output one led blinking at rate of 200ms that outputs the word "blink" to the screen each time it comes on.

int led = 13;
void setup() {
pinMode(led, OUTPUT);
Serial.begin(9600); //set the baud rate to 9600 bits per sec
}
void setup() {
digitalWrite(led, HIGH);
Serial.println("BLINK");
delay(200);
digitalWrite(led, LOW);
delay(200);
}

22) Same as 21 but this time use two leds of different colours and output the colour of the led to the screen each time it goes on. So you should see eg. "red yellow red yellow ..."

int ledO = 13; //orange
itn ledG = 12; //green led
void setup() {
pinMode(ledO, OUTPUT);
pinMode(ledG, OUTPUT);
Serial.begin(9600); //set the baud rate to 9600 bits per sec
}
void setup() {
digitalWrite(ledO, HIGH);
Serial.println("Orange ON");
delay(200);
digitalWrite(ledO, LOW);
delay(200);
digitalWrite(ledG, HIGH);
Serial.print("Green ON);
delay(200);
digitalWrite(ledG, LOW);
delay(200;

}

23) Look at http://wwww.wikieducator.org/User:Peterb/HowManyArduinos0

In my school this website was blocked.
 But there is a kind of arduino i saw off MindKits called the Arduino MEGA which has 54 digital I/O pins.  It uses a larger version of the ATMega Microprocessor.

24) LRD photo resistors
when the light changes in a room the LDR's resistance changes.  This can be monitored using the Arduino with the analogRead() function.

25, 26 and 28)  Making the light sensor work.

To get the arduino to read the light sensor accuratly I use a 1k ohm resistor in the circut.


Here is the code that I used:

//LDRMon by Tim Sullivan

//set varyables for stuff
int ldr = 0; //inital value of the ldr
int led = 13; //use the default led on the arduino
int ldrPin = 0; //the LDR is connected to analouge pin 0

void setup() {
  pinMode(led, OUTPUT); //because LEDs usally output light...
  Serial.begin(9600); // connect to the arduino to monitor things such as 'ldr'
  //above line was just used just for debugging
}

void loop() {
ldr = analogRead(ldrPin); //read the analog pin.
// Serial.println(ldr); //tell us what the ldr is.
if(ldr > 20){
  digitalWrite(led, HIGH);
  }
 digitalWrite(led, LOW);

}

29) Random numbers on arduino

My code

int num = 0;
void setup(){
  Serial.begin(9600);
}
void loop(){
  num = random(101); //generate random numbers 0 to 100
 Serial.print(num);
}

Screenshot (my arduino was home at the [imagine random numbers in here] )


Task 30) Random dice program

/*The DICE program
by Tim Sullivan

It hasn't actually been tested with an arduino but think
it will range the correct numbers.

*/

int num = 1;
void setup(){
  Serial.begin(9600);
}
void loop(){
  num = random(1,6); //generate random numbers 1 to 6
  //i hope thats right
 Serial.print(num);
}

25 May, 2010

PWM - Pulse Width Modulation - Arduino

Today i discovered what the digtal I/O pins labeled with a "PWM" were for.  They can be use to make a digital signal pulse instead of be on or off.  This means that you can make an LED fade on and off without using 1000's of on's and off's.

The IDE function used to do this is called analogWrite()

12 May, 2010

Tasks second set 13 - 18

Tasks - Second set

13)  mostly on than off.
[...]
digitalWrite(led1, HIGH);
digitalWrite(led2, LOW);
delay(1000);
digitalWrite(led2, HIGH);
delay(500);
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
[...]
----------------------------------------------------------------
14)  now the opposite




[...]
digitalWrite(led2, HIGH);
digitalWrite(led1, LOW);
delay(1000);
digitalWrite(led1, HIGH);
delay(500);
digitalWrite(led2, LOW);
digitalWrite(led1, LOW);
[...]
----------------------------------------------------------------
15)  will send email
----------------------------------------------------------------
16) get one led to blink once then repeat the other infinitely 

//start of program
int powerOnLed = 13;
int blinkStatus = 12;
int num = 0;

void setup() {
  pinMode(powerOnLed, OUTPUT);
  pinMode(blinkStatus, OUTPUT);
  }

void loop() {
while(num = 0) {
  digitalWrite(powerOnLed, HIGH);
  delay(1000);
  digitalWrite(powerOnLed, LOW);
  num = num + 1;
  }
digitalWrite(blinkStatus, HIGH);
delay(1000);
digitalWrite(blinkStatus, LOW);
delay(1000);

}

--------------------------------------------------------------------
17) using the for loop SUCCESS!!

int ledPin1 = 13;
int ledPin2 = 12;
int t = 300;


void setup() {
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
}


void loop() {
int i = 0;
for(i=0;i<5;i++){
digitalWrite(ledPin1, HIGH);
delay(t);
digitalWrite(ledPin1,LOW);
delay(t);
}


digitalWrite(ledPin2, HIGH);
delay(t);
digitalWrite(ledPin2, LOW);
delay(t);
}








-----------------------------------------------------------------------------
18) same as above but different value

int ledPin1 = 13;
int ledPin2 = 12;
int t = 300;


void setup() {
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
}


void loop() {
int i = 0;
for(i=0;i<10;i++){
digitalWrite(ledPin1, HIGH);
delay(t);
digitalWrite(ledPin1,LOW);
delay(t);
}


digitalWrite(ledPin2, HIGH);
delay(t);
digitalWrite(ledPin2, LOW);
delay(t);
}




Tasks first set 1-12

Tasks


5) Make the blink twice as slow:
[...]
//make led blink on for 2s and off for 2s
digitalWrite(led, HIGH);
delay(2000);
digitalWrite(led, LOW);
delay(2000);
[...]
-----------------------------------------------------------

6) Make the LED blink fast
[...]
//make the led turn on for (50ms) and off (50ms)

digitalWrite(led, HIGH);
delay(50); //this is quite fast but still visible.
digitalWrite(led, LOW);
delay(50);

/*if the program was delayed for 9 milli seconds it would look like the led is solid on. */
[...]
-------------------------------------------------------------

7) Get led to stay on mostly then flash off.
[...]
digitalWrite(led, HIGH);
delay(10000); //stay on for 10 seconds
digitalWrite(led, LOW);
delay(100); //flash off for 100ms
[...]
-------------------------------------------------------------
8) Now the other way around from '7'
[...]
digitalWrite(led, HIGH);
delay(100); // illuminate for 100ms
digitalWrite(led, LOW);
delay(10000); //stay off for 10 sec
[...]
-------------------------------------------------------------
9) What has LEDs
iPods, computers (eg HDD activity), the arduino, network hubs/switches, tv.

Some cordless phones detect whether there is a message and makes a LED light up for 500ms every 4 seconds.
-------------------------------------------------------------
10) I have downloaded Fritzing
-------------------------------------------------------------
11) I have made a Fritzing diagram for the 7-Segment LED display
-------------------------------------------------------------
12) Fritzing project
A RGB colour mixer looks interesting by getting different colours to change by using a potentiometer. 

06 May, 2010

Another cool idea

http://www.youtube.com/watch?v=ATnnMFO60y8&NR=1&feature=fvwp

LDR Robot

Here is a video of something I would like to make using a Light Dependent Resistor: http://www.youtube.com/watch?v=wLAjnOWO8mU

Getting 2 reds and 1 green flashing!

15 minutes after the video conference on Thursday me and Nich got 2 LEDs that were red and 1 green to oscillate.

Here is the code


int green = 12;
int red1 = 11;
int red2 = 10;
int t = 1000;

void setup() {
pinMode(green, OUTPUT);
pinMode(red1, OUTPUT);
pinMode(red2, OUTPUT);
}

void loop() {
digitalWrite(red1, HIGH);
digitalWrite(red2, HIGH);
digitalWrite(green, LOW);
delay(t);

digitalWrite(red1, LOW);
digitalWrite(red2, LOW);
digitalWrite(green, HIGH);
delay(t);
}