Wi-Fi Car

The Wi-Fi Car is an open source robotic device controlled by a terminal, such as a smartphone, PC, or tablet. It provides a video stream of what the car sees through its camera.

The project combines what we have learned about OpenWrt routers, Arduino, remote control, MJPG streaming and HTML.

The car was featured in a report by Global Times on May 31, 2012 ("The Robot Cookbook").

Media

闪开small.jpg

If you are interested our Wi-Fi Car and want make your own, watch the videos in this Youku playlist (instructions in Chinese).

  • Part 1: Making the Body
  • Part 2: Installing the DFRduino RoMeo (requires Arduino IDE
  • Part 3: Communicating with the Arduino (requires this code)
  • Part 4: Controlling the Wi-Fi Car via Amarino (required this code)
  • Part 5: About the Android App
  • Part 6: Making the Android App Control the Wi-Fi Car
  • Part 7: About OpenWrt

Hardware

There are a few current versions of the hardware:

Mini Wi-Fi Car

  • Chasis
  • DFRduino
  • Battery
  • TP-Link WR703N
  • A camera (most cheap webcams will do)
  • Wire

Normal Wi-Fi Car

  • Chasis or Rover 5 Tank
  • Romeo (or Motor Shield and DFRduino)
  • TP-Link WR703N
  • Camera
  • Wire
  • USB hub

This version connects the Arduino via USB instead of direct serial. You will need two batteries, or a more powerful battery. Its difficulty is mainly because of this.

Software

We have built our own OpenWrt image to flash on the router, with drivers and some required tools. It's ready to use and easy to install. Just update the firmware on your router from the menu and select our custom build.

WARNING: This will void your warranty! Make sure you want to do that before you proceed. This is a testing build. If something goes wrong, its your own problem.

Wi-Fi Car Howto

(needs review/check)

  • Connect to your router using telnet or the serial port
  • Configure networking
  • Access the video stream through your browser
  • Open minicom to connect to your Arduino's USB port
  • Issue commands to your Arduino while watching the video stream

Sample Code

Arduino

wifi-car.ino
//    Wifi-Car Code for Arduino
//    controls motors, servos and others, 
//    by commands through serial USB
//    If used with router, you need to install Drivers. 
//    for serial FTDI or ACM for newer Arduinos
//
//    This code is basically copied from examples at DFRobot and Arduino. 
//    So it is well explained and documented online.
//    
//    You will need:
//      - motors + motor driver
//      - PC speaker or something for sound ( horn )
//      - 2 Servo motors to move camera's point of view.
//
//    Open-Drone.org
 
#include <Servo.h> 
Servo twist;
Servo nod;
 
int EN1 = 6;  
int EN2 = 5;  
int IN1 = 7;
int IN2 = 4; 
 
// horn
int horn = 3; 
int hornLevel;
 
//Variable to store servor possition
int horizontal;
int vertical;
 
 
 
void setup() 
{ 
  for(int i=3;i<=7;i++) 
    pinMode(i, OUTPUT);  //set pin 3,4,5,6,7 to output mode, including the horn
 
  // Servo SetUp
  horizontal = 90;
  vertical = 90;
  twist.attach(8);  // initialize servo motors for the neck of the camera
  nod.attach(9); 
  delay(10);
 
  // Start servos Centered when Wifi-Car is turned ON
  nod.write(horizontal);
  twist.write(horizontal);              // tell servo to go to centered possition
  delay(15);        
 
  hornLevel = 100;
  Serial.begin(115200);   
} 
 
 
void loop() 
{ 
  char val;
  while(1)
  {
    val = Serial.read();
    if(val!=-1)
    {
      switch(val)   // here are all the commands i will be sending from the usb connection
      {
      case 'w'://Move ahead
        Motor1(250,true); 
        Motor2(250,true);
        delay(50); 
        Motor1(0,false);
        Motor2(0,false);
        break;
      case 'x'://move back
        Motor1(250,false);
        Motor2(250,false);
        delay(50);
        Motor1(0,false);
        Motor2(0,false);
        break;
      case 'd'://turn left
        Motor1(250,false);
        Motor2(250,true);
        delay(50);
        Motor1(0,false);
        Motor2(0,false);
        break;       
      case 'a'://turn right
        Motor1(250,true);
        Motor2(250,false);
        delay(50);
        Motor1(0,false);
        Motor2(0,false);
        break;   
      case 's'://stop
        Motor1(0,false);
        Motor2(0,false);
        break;
        // Move the neck, control servos, horizontal and vertical
      case 'e':
        if (horizontal < 1) {
          horizontal = 0;
          break;
        }
        else {
        horizontal--;
        Serial.print("Servo twist (horizontal) possition: ");
        Serial.println(horizontal);
        twist.write(horizontal);
        break;
        }
      case 'q':// for the neck of the camera
        if (horizontal > 179) {
          horizontal = 179;
          break;
        }
        else {
        horizontal++;
        Serial.print("Servo twist (horizontal) possition: ");
        Serial.println(horizontal);
        twist.write(horizontal);
        break;
        }
      case 'f':// for the neck of the camera     
        if (vertical > 127) {
          vertical = 127;
          break;
        }
        else {
        vertical++;
        Serial.print("Servo nod (vertical) possition: ");
        Serial.println(vertical);
        nod.write(vertical);
        break;
        }
      case 'r':// for the neck of the camera
        if (vertical < 32) {
          vertical = 32;
          break;
        }
        else {
        vertical--;
        Serial.print("Servo nod (vertical) possition: ");
        Serial.println(vertical);
        nod.write(vertical);
        break;
        }
      case 't':// center camera point of view
        vertical = 90;
        horizontal = 90;
        Serial.println("Centering neck .. ");
        nod.write(vertical);
        twist.write(horizontal);
        break;
      case 'h':
        //horn, like in the movie. Wifi-Car can also talk! 
        //if you have some sensors, you can use this function to let him complain. 
        //dont forget to attach the pitch library!
 
        digitalWrite(horn,HIGH);
        Serial.println("Beep Beep");
        if (hornLevel < 100) 
        {
          for(int i=1;i<=20;i++)  tone(3, random(31, 4978), 200);
        }
        hornLevel = 90;
        Serial.println("Beep Beep");
        break;
 
      } 
    }
  }                           
}
 
// Basic motor functions
void Motor1(int pwm, boolean reverse)
{
  analogWrite(EN1,pwm); //set pwm control, 0 for stop, and 255 for maximum speed
  if(reverse) digitalWrite(IN1,HIGH);  
  else digitalWrite(IN1,LOW); 
}  
 
void Motor2(int pwm, boolean reverse)
{
  analogWrite(EN2,pwm);
  if(reverse) digitalWrite(IN2,HIGH);
  else digitalWrite(IN2,LOW);    
}

Flymaple

flymaple-car.ino
//    Wifi-Car Code for FlyMaple
//    test control motors
//
//    This code is basically copied from examples at DFrobot and arduino. So it is well explained and documented online.
//    You will need:
//       flymaple + motors + motor driver
//       LED will light when serial command is entered.
//    Open-Drone.org
 
// Motors
int M1 = 5;  
int E1 = 4; 
int M2 = 6;                      
int E2 = 7;                        
 
void setup() 
{ 
  SerialUSB.begin();
  SerialUSB.println("Wifi-Car booting up");
 
  pinMode(BOARD_LED_PIN, OUTPUT);
  pinMode(E1, OUTPUT);   
  pinMode(E2, OUTPUT); 
  pinMode(M1, PWM);   
  pinMode(M2, PWM); 
 
  Motor1(0,false);
  Motor2(0,false);
  delay(50);
 
} 
 
void loop() 
{ 
  char value;
  while (SerialUSB.available()){
    digitalWrite(BOARD_LED_PIN,HIGH);
    value = SerialUSB.read();
    if(value!=-1)
    {
      switch(value)   // here are all the commands i will be sending from the usb connection
      {
      case 'w'://Move ahead
        Motor1(65000,true); 
        Motor2(65000,true);
        delay(50); 
        Motor1(0,false);
        Motor2(0,false);
        break;
      case 'x'://move back
        Motor1(65000,false);
        Motor2(65000,false);
        delay(50);
        Motor1(0,false);
        Motor2(0,false);
        break;
      case 'd'://turn left
        Motor1(65000,false);
        Motor2(65000,true);
        delay(50);
        Motor1(0,false);
        Motor2(0,false);
        break;       
      case 'a'://turn right
        Motor1(65000,true);
        Motor2(65000,false);
        delay(50);
        Motor1(0,false);
        Motor2(0,false);
        break;   
      case 's'://stop
        Motor1(0,false);
        Motor2(0,false);
        break;
      } 
    }
  }
  digitalWrite(BOARD_LED_PIN,LOW);
  delay(20);
}
 
// Basic motor functions
void Motor1(int pwm, boolean reverse)
{
  analogWrite(M1,pwm); //set pwm control, 0 for stop, and 255 for maximum speed
  if(reverse) digitalWrite(E1,HIGH);  
  else digitalWrite(E1,LOW); 
}  
 
void Motor2(int pwm, boolean reverse)
{
  analogWrite(M2,pwm);
  if(reverse) digitalWrite(E2,HIGH);
  else digitalWrite(E2,LOW);    
}