Introduction: Arduino RC Car With FPV Camera

Picture of Arduino RC Car With FPV Camera

This Instructable describes a remote control car I've put together. The car has no real purpose - it was just a challenge, to see what could be made with commonly available hardware. It has the following features:

- 4x4 rock crawler chassis

- PC Based Control - The car is controlled through a custom Windows application (C#)

- "Analog" throttle (electronic speed control) and steering, using an XBox 360 controller

- Controller vibration / force feedback effects based on the car's accelerometer

- First Person View Digital video stream

- Movable camera

- Configurable RGB lights (Adafruit NeoPixels)

Watch the embedded YouTube video to see the car in action.

Or, click the direct link: https://www.youtube.com/watch?v=FwRHbJV4zV0

All of the Arduino and C# code is provided within this Instructable. The software has been written specifically to work with the hardware items (eg IP camera) I've used. If you would like to make your own car with different hardware, you will probably need to make minor changes to the C# and/or Arduino code.

Note: This project has a lot of software content in it, and is a long read! (I've tried to add detailed comments into the code, but beginner programmers might find it a little challenging to follow)

Note 2: Skip to the conclusion to see the upgraded version of the car (Raspberry Pi 2 camera + pan/tilt servos)

Step 1: Hardware Overview

Picture of Hardware Overview

The car consists of the following hardware components:

- RC 1/10 scale rock crawler chassis

- Axial Racing Electronic Speed Controller (ESC)

- Steering Servo motor

- Aluminium base plate and aluminium angle for mounting other parts

- Arduino Mega (you will need a Mega for this project)

- Sparkfun Arduino XBee shield

- XBee Series 1 Pro (60mW) wireless module

- Adafruit ADXL335 Accelerometer

- Adafruit NeoPixel stick

- IP camera with Pan/Tilt and IR Night Vision

- Portable Wi-Fi router

- 7.2V NiMH battery (power supply for ESC and steering servo motor)

- 11000mAH dual USB power bank (power supply for Arduino Mega, Wi-Fi router, IP camera, NeoPixel stick)

A laptop is required to communicate with and control the car. The laptop must have the following:

- Windows 7 / 8

- At least 2 USB ports

- Wi-Fi

- Optional - Ethernet port (but if the laptop doesn't have one, you need access to a computer with an Ethernet port)

The following hardware components are also required on the PC side:

- XBox 360 controller (wired)

- XBee Series 1 Pro (60mW) wireless module

- XBee USB Explorer

A full parts list is attached below.

Step 2: RC Car Selection and Physical Modifications

Picture of RC Car Selection and Physical Modifications

The type of RC vehicle I've chosen for the platform is a 1/10 scale Electric Rock Crawler. RC Rock crawlers are 4x4, have locked diffs, (relatively) high ground clearance and large suspension articulation, so they are less likely to get stuck when driving over obstacles. However, they are generally not as fast as regular RC cars (geared for high torque instead of high speed). The specific model I chose is a HSP Pangolin because it was cheap. It is also a knock-off of the Axial Racing AX10, so it is easy to find compatible spare parts :-P .

The car came with a 7.2V NiMH battery, electronic speed controller (ESC) and a brushed motor. The original ESC had no documentation on how to calibrate it, or program its features. Since I intended to control the ESC through an Arduino, I needed an ESC that could be calibrated and programmed. I found that the Axial AE-2 ESC would be the most suitable replacement, since they have clear instructions for setup and configuration (see http://www.axialracing.com/blog_posts/787000000).

To mount all of the parts, I removed the original plastic battery/ESC tray. I then used some aluminium angle and large aluminium plates to create a flat mounting surface.

The various parts are either screwed to the aluminium plates or cable-tied. For electronic components such as the Arduino, some plastic was placed on the aluminium plate for insulation.

After mounting most of the components onto the car, I found that the original suspension did not cope well with the added weight - the car dropped about 4cm from its original height. To fix this, I purchased and installed four super-firm springs. These springs are much better than the original springs (the car only drops 0.5cm), but are still a little too soft - mashing the throttle will cause the car to list like a sinking boat!

Step 3: Power and Wiring Configuration

Picture of Power and Wiring Configuration

The car has two batteries - a 7.2V NiMH battery and a 11000mAh powerbank. The NiMH battery provides power for the ESC and steering servo. Note that the steering servo is powered by the ESC's Battery Eliminator Circuit (BEC), which provides regulated 5V DC output. Also, the drive motor is powered / controlled by the ESC.

The powerbank provides power for the Arduino, WiFi router, IP camera and NeoPixel stick (all of these devices operate on 5V DC power). The specific model I chose is the Cygnett 11000mAh Charge Up Pro because it has dual USB ports - one port can provide up to 2A, and the other port can provide up to 1A. It is also one of the highest capacity powerbanks currently available, so I don't need to worry about it dying before the car battery dies.

Since the powerbank needs to power four items with only two USB ports, I built some USB power splitters. These can be considered to be USB power double adapters. The USB power splitter for the NeoPixel stick also has some female 0.1" headers in addition to the USB ports, to allow the use of stripped 22 AWG solid core wire to connect power to the NeoPixel stick.

Also, since two batteries are involved, the grounds for devices attached to these batteries should be common, so that all signal voltages are based on the same reference value. To do this, I connected the ground pin for the ESC Battery Eliminator Circuit (BEC) to the Arduino GND. There is also a connection between a USB power splitter and the Arduino GND. This common ground is required so that the steering servo and throttle signals sent from the Arduino are received at the correct voltages.

The last diagram shows a full overview of the wires / cables on the car, including the Arduino Mega pins that were used.

Step 4: Software Overview

Picture of Software Overview

The software in this project includes a PC-based C# program and an Arduino sketch. The program is a WinForms application, with a Graphical User Interface (GUI). The C# program performs a lot of functionality and handles a diverse range of inputs and outputs. A summary of these is below:

C# program

- receives XBox 360 controller input

- receives mouse / keyboard input for some functions

- receives video data from IP camera (via http)

- receives telemetry/status data from Arduino (via serial)

- sends instructions to Arduino (via serial)

- sends instructions to IP camera (via http)

- sends vibration instructions to XBox 360 controller

- GUI - displays status of controller, serial communications, video stream.

The Arduino sketch is not as complex as the C# program, but still does many things:

- receives instructions from C# program (via serial)

- receives telemetry data from accelerometer module (via analog inputs)

- sends control signal to Electronic Speed Controller

- sends control signal to Steering Servo

- sends control data to NeoPixel stick (digital output)

-sends status/telemetry data to C# program (via serial)

I've attached the C# project and the Arduino sketch below. For the next few steps, I recommend downloading the files, and leaving them open so you can switch between the steps and code. The steps aren't very useful without the code, and the code can be a bit confusing without the steps!

Note: You may need to manually recreate the C# project from the source files if the project doesn't load successfully in your version of Visual Studio.

Step 5: Software Development Environments and Utilities

The C# program was developed using Visual Studio Express 2012. This is a free version of Visual Studio, but provides enough features to develop complex C# applications.

Unfortunately, Microsoft doesn't include native support for its own XBox 360 controller when developing C# applications. Luckily, I'm not the only one to encounter this problem, so someone has made a C# wrapper around "xinput" (the API that allows developers to communicate with the XBox 360 controller). The particular version I've used is attached below. The current version of the wrapper can be downloaded from github:https://github.com/speps/XInputDotNet. Refer to the github page or the readme file for detailed installation / configuration instructions. My summary of the instructions is: Add "XInputDotNetPure.dll" as a reference in the C# project, and put "XInputInterface.dll" in the same folder as the .exe file.

The Arduino sketch was developed using the Arduino IDE. Two additional libraries were required in order to use the NeoPixel stick and two servo outputs (for steering and throttle), simultaneously. These libraries are the Adafruit "TicoServo" library and the Adafruit "NeoPixel" library. These libraries can be downloaded from github:

https://github.com/adafruit/Adafruit_TiCoServo

https://github.com/adafruit/Adafruit_NeoPixel

Installation instructions are provided in each library. For a generic Arduino library installation guide, refer to: https://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use/how-to-install-a-library

Note: The standard Arduino servo library couldn't be used due to the NeoPixel stick. An explanation for this incompatibility is provided by Adafruit: https://learn.adafruit.com/neopixels-and-servos

Step 6: C# Application Threading and XBox 360 Controller Input

Picture of C# Application Threading and XBox 360 Controller Input

The first bit of software I wrote for this project was for the XBox 360 controller (you may have noticed that the original Visual Studio project name has carried through to the end!). You will find the XBox controller code in the first part of the "Form1.cs" file. As mentioned in the previous step, this code only works if the Xinput dotnet wrapper has been configured (i.e. "XInputDotNetPure.dll" has been added as a reference in the C# project, and "XInputInterface.dll" is in the same folder as the .exe file).

The code works by repeatedly polling the controller to retrieve the status of the buttons and analog controls. Due to this polling, I realised that the program would need multiple threads, in order to work at all. This was a bit of a challenge, as I hadn't actually written a multi-threaded application before this one. After looking at some examples and tutorials, I decided that there would be a main application thread for the graphical user interface (GUI), a separate thread for handling the XBox 360 controller, and several more threads for other things. Multiple threads allow all these things to work in parallel, without any noticeable lag in the GUI.

In the Xbox controller thread, the controller status is polled at about 50Hz, so it always has very current data. This controller data is also echoed on the GUI, and button presses are highlighted in orange. To do this, cross-thread data transfers were needed. I used the concept of "delegates" to allow threads to "affect" each other. You'll also notice a number of "shared_...." variables that are used across multiple threads.

This section of code also has a counter that keeps track of controller "frames". In the context of my code, the frames refer to when the controller status has been read. The counters "samplecount" and "oldsamplecount" are used so that long button presses are handled correctly. As an example, I have assigned some digital buttons so that one press activates a function, and the next press deactivates that function. If a long press isn't handled correctly, the program will toggle that function on and off continuously. The code correctly handles a long press as a single press by comparing the value of oldsamplecount against samplecount. If the difference between the two variables is too small, it is detected as a long press.

Step 7: Serial Communication (Part 1)

I considered several options for sending control data between the laptop and the car. Wi-Fi or bluetooth seemed to be the obvious solutions, but neither can provide the range I would like. Most wireless arduino projects seem to use XBee modules, which rely on serial communication, so I decided to use a serial interface.

The car/laptop communication works like this:

1. The car sends a serial string (with a fixed structure), with known start and end of message characters.

2. The C# program continuously polls the laptop's serial interface. When it receives a serial string, containing both the expected start and end characters, the C# program prepares its own serial string (with a fixed structure), and sends it to the car.

3. The car receives the serial string, does a quick check (based on an end of message character and message length), pulls out and processes the information if the message is "valid", and waits for a specified delay before preparing and sending another message - and the cycle repeats.

Note: If the received message is not considered "valid" at the Arduino, the Arduino sketch will stop the car and centre the steering.

The message structure for messages sent to the car, from the C# program, is:

500,500,F,D00,Z

The meaning of this string is:

First field: Throttle (centred around 500)

Second field: Steering (centred around 500)

Third field: Slowmode - F: Fast, S: Slow (max throttle is halfspeed)

Fourth field: Headlights

First character: D: Dark (lights off), L: Lights on

Second character: brightness (0 - 9)

Third character: light sequence (0 - 9)

Final field: End of message character (Z)

More details about some fields will be provided in later steps

The message structure for messages sent from the car, to the C# program, is:

A,500,500,F,D00,R ,Z

First field: Start of message character (A)

Second Field: Throttle (centred around 500)

Third Field: Steering (centred around 500)

Fourth field: Slowmode - F: Fast, S: Slow (max throttle is halfspeed)

Fifth field: Headlights

First character: D: Dark (lights off), L: Lights on

Second character: brightness (0 - 9)

Third character: light sequence (0 - 9)

Sixth field: rumble (R - rumble, O - off)

Final field: End of message character (Z)

Most of these fields are just echoing what was received by the Arduino. This was done as a visual indicator of the health of the serial interface. If the interface is working properly, the output and input strings displayed in the C# program should match.

This serial communication method was initially developed using a cabled serial connection (i.e. using the Arduino USB cable). I was able to set the delay on the Arduino side to 20ms, so that the message frequency was about 50Hz. With the USB cable, I had no problems with communication, and could get stable message receipt at both ends. The baud rate was set to 38400.

Step 8: Serial Communication (Part 2) - Wireless Serial

Picture of Serial Communication (Part 2) - Wireless Serial

For wireless serial communication, I initially bought some XBee Series 1 1mW modules, just to try them out. An XBee shield is required for the Arduino, and an XBee USB Explorer (or equivalent) is required on the laptop side. Since I used an Arduino Mega, I connected the relevant pins on the XBee shield into the Arduino Mega pins for the second hardware serial interface.

I found that the Series 1 modules were pretty easy to setup using the XCTU application (see the Sparkfun guide: https://learn.sparkfun.com/tutorials/exploring-xbees-and-xctu). However, I ran into some limitations. The first one is an obvious one - with 1mW modules, the usable range was extremely limited, and for no dropped messages, I could only go as far as about 3m! I could get better range with a long USB cable. The second one is a more important limitation and seems to be hardware based. I found that I could not get reliable communication at 50Hz, even with the XBees configured to a baud rate of 38400. I increased the delay, so that the message rate would be about 25Hz, and I had much better success. At 25Hz, I could get stable communication within 3m. I also found that when I went out of range, the messages would be dropped, but would recover straight away when brought back in range. To check if the serial communication was working properly, I watched the serial input / output textboxes on the C# program GUI. The serial input box should show a very stable string of characters, that matches the serial output box. If the serial input box started flashing with blank or corrupted data, that meant that the messages weren't getting through.

After getting these modules working, I ordered some higher powered modules. Seeing that both high powered Series 1 and Series 2 modules were available, I went for the slightly cheaper XBee Series 2 Pro (63mW) modules, rather than the XBee Series 1 Pro (60mW) modules. I had read that they were harder to setup, but could be used in transparent (AT) mode, just like the Series 1 modules. I configured the modules and got them to talk to each other at 38400 baud (note: one module has to be flashed as a "coordinator" and the other module has to be a "router"). I then installed one into the Arduino shield, and immediately ran into problems. At 25Hz, I could not get reliable communication at all. To check what was happening, I echoed the Arduino's received messages through the Arduino's first serial port (i.e. USB cable). Using the Arduino serial monitor on my laptop, I found that the Series 2 XBees were chopping messages in half or mashing consecutive messages together. So, the Arduino would sometimes receive the end half of a string stuck to the first half of the next string. I had to increase the delay, so that the frequency dropped to about 13Hz before I could get seemingly reliable serial communication over short ranges. The downside of the lower frequency message is that it introduces more lag between controller input, and the car's movement. Unfortunately, the lower frequency did not resolve the problems completely. Over longer distances, the serial data corruption still happened, and the interface did not recover when brought back in to close range.

So, with all these problems, I ended up buying a pair of Series 1 Pro 60mW modules. In terms of the serial interface, they work just as well as the 1mW Series 1 modules - there is no data corruption or strange message behaviour when in range. Their range is also much better than the 1mW modules (as expected).

In summary, if you're using XBees in a project for simple point to point communication, STAY AWAY from the Series 2 XBee modules! The Series 1 modules perform infinitely better and are less problematic (that probably explains their popularity and higher price).

(On a related note, is there anyone in Australia who wants to buy some lightly used XBee Series 2 Pro 63mW modules? :-P)

Step 9: Car Throttle and Steering

Picture of Car Throttle and Steering

The throttle and steering on the car are "analog", meaning that by using the XBox controller, the car can move at a range of speeds, and turn at a range of steering angles. The right trigger is used for forwards, the left trigger is used for reverse and the left thumbstick is used for steering (these are the standard controls for XBox racing games). In order to transmit these "analog" inputs from the XBox controller to the car, the data travels through the programs as follows:

Throttle Data - C#:

1. The XBox Controller status is read. Left/right trigger values are saved as floats

2. A comparison is made between the two trigger values. The larger value is used, and the smaller value is ignored (eg, if both forwards and backwards are pressed, the larger value "wins")

3. The value is multiplied by 100, and manipulated so that 0 speed is the value 500. This means that full speed reverse is equivalent to the value "400", and full speed forwards is the value "600". This was done to prevent needing to use negative numbers, and the choice of 500 as the centre point was completely arbitrary.

4. The new throttle value is converted to a string (as 3 digits).

5. The throttle string is added to the C# output string, and sent to the Arduino when required.

Throttle Data - Arduino:

1. The Arduino receives the full string, and saves the throttle characters to a character array.

2. The throttle character array is converted to an int

3. Using the "map" function, the throttle value is converted into a compatible value for the ESC. The ESC accepts the same control signals as servo motors, so the Servo type is used to write a "degree" value to the ESC pin. The ESC has been calibrated such that 0 degrees is full speed reverse and 180 degrees is full speed forwards. 90 degrees is 0 speed.

4. The value is written to the ESC.

In the C# code, you'll also see some extra functions that manipulate the throttle. These were included to change the driving characteristics, but I haven't found them that useful. One of these functions involves a linear/squared/cubed throttle mode. Linear mode provides a 1:1 relationship between the trigger position and the speed. So, pressing the forwards trigger halfway results in the car moving at half of its max speed. Square mode involves squaring the raw value, so pressing the trigger halfway results in the car moving at a quarter of its max speed. This offers more range of control at lower speeds, and less at higher speeds. These throttle modes can be selected using the drop down box on the C# program GUI (using a mouse).

The other function involves the ability to enable/disable "slow mode", by pressing the B button on the XBox controller. Slow mode limits the car's top speed to half of its max speed. So, you could use the full range of the triggers to control lower speeds. This mode actually comes in handy sometimes - it is great for precise control at slow speeds.

Steering is quite similar to throttle. The way the data travels is:

Steering Data - C#:

1. The XBox Controller status is read. The left thumbstick x-axis value is saved as a float

2. The value is multiplied by 100, and 500 is added. This means that full left is equivalent to the value "400", and full right is the value "600". Like the throttle, this was done to prevent needing to use negative numbers, and the choice of 500 as the centre point was completely arbitrary.

3. The new steering value is converted to a string (as 3 digits).

4. The steering string is added to the C# output string, and sent to the Arduino when required.

Steering Data - Arduino:

1. The Arduino receives the full string, and saves the steering characters to a character array.

2. The steering character array is converted to an int

3. Using the "map" function, the steering value is converted into a compatible value for the steering servo. Note that the steering servo does NOT have the full range of 0 to 180. On my car, full left is 133 degrees and full right is 60 degrees, with a centre value of about 96 degrees

4. The value is written to the steering servo.

Like the throttle, the steering can be configured to linear/squared/cubed mode in the C# program. I found that for my car this was a bit pointless, due to the relatively small range in steering angle. Since the wheels don't turn far, it is easy to get them to the right angle in linear mode.

Note about Arduino Servo libraries:

When I was developing the Arduino sketch, I used the standard Arduino Servo library for both the ESC and steering servo. Once I introduced the NeoPixel stick, the Servo library could not be used anymore (see https://learn.adafruit.com/neopixels-and-servos). The TiCoServo library works just as well in my RC car, but there are limits - only two servos can be used simultaneously, only a small set of pins can be used (even on an Arduino Mega), AND only specific pairs of those pins can work together. The last one was figured out through trial and error...

Step 10: IP Camera (Part 1) - Hardware

Picture of IP Camera (Part 1) - Hardware

The Arduino isn't powerful enough for video, so I needed a self-contained video solution. This ruled out webcams, which would require an onboard computer to process and forward the video to the laptop. Also, GoPros are a bit pricy, and the models (when I started looking in mid-2014) did not live stream without a significant delay (3 seconds). The best option I found for a camera that could stream live digital video with minimal lag was an IP camera. These are typically used as surveillance cameras, which actually brings added benefits, such as IR night vision. I then put together a list of features that I needed/wanted:

- Ethernet and/or Wi-Fi interface

- Ability to set a static IPv4 address

- MJPEG video streaming (simpler to include in C# program)

- Documentation for how to control the camera via http commands

- Wide angle lens

- IR-Cut filter for daylight use (better colour accuracy)

- IR night vision

- 5V DC input

- (Optional) Pan/tilt control

I was able to find a model that fits all of these criteria. The IP camera I chose is the Foscam FI8910W IP camera. This is a non-HD IP camera that sends MJPEG video (max resolution: 640 x 480). I didn't choose a HD model, because they generally use H.264 video, and I don't know how to display a H.264 video stream in a C# winforms application (Is it even possible? Add a comment if you've done it before, or know how to).

The IP camera is powered by 5V DC (up to 0.7A required), which makes it compatible with a USB powerbank. However, the connector is a barrel connector, so I made a custom cable - one end has the barrel connector, and the other end has a USB connector.

The IP camera has both Wi-Fi and Ethernet interfaces. In theory, I could set up a direct ad-hoc Wi-Fi connection between the laptop and IP camera, but I had doubts about the performance of its Wi-Fi antenna. So, I decided to add a portable Wi-Fi router on the car. The model I chose is the Netgear Trek PR2000. I chose this model because it is tiny, can be powered from a USB supply and has Ethernet ports. Having a Wi-Fi router also allows flexibility for upgrades later on - other Ethernet/Wi-Fi based capabilities can be added easily.

IP Camera Configuration:

The only thing that needed to be set up was the static IP address. I chose the address 192.168.1.10 (subnet mask 255.255.255.0). To set up the camera, I plugged it into the Ethernet port in my laptop, and first made sure that the auto-assigned IP addresses were ok for communication. Then, I opened a web browser, and typed the IP address of the camera to load its configuration page. The static IP address was then set to 192.168.1.10. Note: This will break the connection to the computer - to recover the connection, the IP address of the laptop was manually changed to the same subnet (eg 192.168.1.11, subnet mask 255.255.255.0).

The username and password can also be configured, but since the camera will only be used on a private network, I left these settings at the defaults (user = admin, no password).

Wi-Fi Router Configuration:

Like most other consumer grade routers, the Netgear Trek router is configured via a web browser interface, and initial setup requires a wired Ethernet connection. For use in the car, the router needs to be configured to use the subnet 192.168.1.XXX (subnet mask 255.255.255.0). The router also needs to have DHCP enabled (it's on by default), and the basic Wi-Fi settings need to be configured (SSID and password). This configuration only needs to be done once.

The initial router configuration is pretty painless, but unfortunately the general startup procedure is not as simple as I expected. Whenever the router is turned on, it does not enter its operational mode until it detects a device connected to its "Internet" port, or a wired computer. With the IP camera attached to the yellow port, the router seems to power up to a "limbo" mode. To force the router to boot fully, the camera cable has to be disconnected and plugged into the blue "Internet" port. After a few seconds, the router will then boot properly and Wi-Fi will come on, allowing the laptop to connect wirelessly. The IP camera does not work in the blue port, so the cable has to be unplugged, and reconnected to the yellow port. A simple ping test can be executed to check if the laptop can see the IP camera on the network.

Note: Although this boot up procedure is annoying, the router does everything I need it to do. I'm not sure if other compact travel routers have the same boot up "feature".

Step 11: IP Camera (Part 2) - Software

Picture of IP Camera (Part 2) - Software

The C# program can send commands to the camera, and display its video stream. By default, the camera functions are disabled on application startup. This is to prevent program crashes if the camera is not available.

The camera receives commands via http. For example, to stream video at 640x480 resolution, the command is:

http://192.168.1.10/videostream.cgi?user=admin&pwd=&resolution=32&rate=0

Refer to your IP camera's SDK documentation or user manual for the command structure. I've attached the documentation for my camera to this step. These commands can also be entered directly into an Internet browser address bar.

Once the camera gets the command shown above, it will begin sending out an MJPEG video stream. My program processes this stream and displays it in the GUI. I wasn't able to find any libraries that process the stream, so I made my own function to do it. The function works by scanning the contents of the stream. When it finds the JPEG "Start of Image" bytes (bytes 0,1: 0xFF,0xD8), it will begin saving the stream into a separate byte array. It will keep adding the stream contents to the array until it finds the JPEG "End of Image" bytes (0xFF, 0xD9). This byte array is then converted into a "memorystream", then a bitmap, before finally being displayed on the GUI.

The program offers two video streaming resolutions. The higher resolution (640x480) offers the better clarity, but has a noticeably lower frame rate. The lower resolution (320x240) is not good for image quality, but the higher frame rate makes it the better choice if driving the car by camera.

There is also a button to show a still picture. This functionality relies on some code I found on a website (http://www.codeproject.com/Articles/15537/Camera-Vision-video-surveillance-on-C). Initially, I only used it for debugging purposes, when making my video streaming functions. I was going to remove it, but decided to leave it in.

Since the camera has pan/tilt motion built in, I also added these capabilities into the C# program. The right thumbstick on the Xbox controller has been assigned to the control of the camera position (this control assignment is typically assigned to "free look" in XBox racing games). The camera gets its pan/tilt instructions via http commands. For example, to move the camera up, the command is:

http://192.168.1.10/decoder_control.cgi?command=0&user=admin&pwd=

There are separate http commands for motor start and stop. To convert motion into measurable "steps", I used delays, so that when the thumbstick is moved within a single controller "frame", the camera just moves one step. However, the motors are far from precise, so these steps are very inconsistent in size. I initially wanted to include a "return to centre" function for the camera, but found that due to the wonky step sizes, the camera rarely returned to the centre position. (The function is still there in the source code, but not in use).

Step 12: NeoPixel Stick

Picture of NeoPixel Stick

Since it is an unwritten rule that Arduino projects should have obnoxious LEDs (just kidding!), I added a NeoPixel stick to the car. NeoPixels are a type of indvidually addressable RGB LED produced by AdaFruit, and the NeoPixel stick has 8 addressable LEDs on a compact PCB. The stick requires a third party Arduino library (https://github.com/adafruit/Adafruit_NeoPixel) to work, but it is quite easy to configure (both hardware and software). I soldered on some female headers so I could connect to it with 22AWG solid core wire.

The lights are controlled using the XBox 360 controller. The "Y" button toggles the NeoPixel stick on/off. The DPad controls the brightness and "sequence". The brightness is controlled by up/down on the DPad, and sequence is DPad left/right. The sequence refers to the preprogrammed modes configured for the NeoPixel stick.

The list of sequences in the current software version is:

Sequence 0: All LEDs set to white (adjustable brightness)

Sequence 1: All LEDs set to red (adjustable brightness)

Sequence 2: All LEDs set to green (adjustable brightness)

Sequence 3: All LEDs set to blue (adjustable brightness)

Sequence 4: Hazard lights - the end LEDs flash orange

Sequence 5: Police mode - the end LEDs flash red/blue (don't use this on a road at night time, haha)

Sequence 6: Pulsing/fading green LEDs

Sequence 7: Knight Rider mode (Red)

Sequence 8: Knight Rider mode (Blue)

Sequence 9: Blank sequence, currently set to white (adjustable brightness)

The C# program sends the NeoPixel instructions to the Arduino, using a 3 character field in the serial output message, such as "L51" The first character controls on/off (L = lights on, D = off(dark)). The second character is the brightness (if applicable for the sequence), and the last character is the sequence number.

To process this information, the Arduino receives the serial string, saves the light string to a separate 3 character array, and then checks each character. The NeoPixel status is updated in each iteration of the main loop.

Note: For animated sequences, such as the hazard lights and police sequence, the millis() function was used to track time. Most NeoPixel examples use the delay() function, but this can't be used for the car, since it will block the execution of all other code in the Arduino, until the delay completes.

Note 2: Since the NeoPixel stick is only updated in each iteration of the main loop, the minimum time between different NeoPixel states is the delay set in the main loop. As you know from the serial section, this delay sets the serial message update frequency between the Arduino and PC. So, very high frequency updates to the NeoPixel stick aren't possible - the highest frequency for the NeoPixels is directly tied to the serial message frequency (about 20Hz).

Step 13: Accelerometer + XBox 360 Controller Vibration

Picture of Accelerometer + XBox 360 Controller Vibration

Accelerometers are used to measure acceleration in one or more axes, so I thought it would be fun to put one in the car. I added an Adafruit ADXL335 3-axis accelerometer to measure the acceleration on the car, so that collisions will be detected and cause the XBox controller to vibrate/rumble. This accelerometer provides its measurements as 3 separate analog inputs to the Arduino. The range of measurements is -/+3g, which maps to 0 - 3.3V. Since the max voltage is only 3.3V, the 3.3V reference pin on the accelerometer board was connected to the Arduino's external reference pin.

The Arduino reads the accelerometer values, on each iteration of the main loop, and saves the values. The Arduino sketch compares the current acceleration values with the previously saved values. If the difference exceeds a threshold, the character "R" is written to the Arduino's serial output string, to indicate that the controller should rumble. If the difference is too small, the character "O" is written to the Arduino's serial output.

The C# program receives the serial string from the Arduino. If it finds the character "R", a "countdown" flag (rumblecount) is set, to indicate that the controller should rumble. In each XBox controller "frame", the status of this flag is checked. If it is above zero, the controller rumble is activated, and "rumblecount" is decremented. On each subsequent frame, the controller will rumble until the countdown flag hits zero. The reason for this countdown flag is to enable the controller to rumble for a minimum of multiple frames, since a single frame is too quick to notice (approx 20ms).

With the current thresholds in the Arduino sketch, the controller will rumble when the car crashes into something, rolls over, goes over large obstacles or drives down stairs. It will also rumble periodically when driving over grass, but not on smooth concrete, so in a way, you can get a feel for the terrain through the controller. It also rumbles when applying full throttle or full reverse.

Note about XBox 360 controller vibration: There are two vibration motors - one is low frequency and the other is a higher frequency. The intensity of vibration can also be controlled precisely (it uses a float for intensity), so you could get a very wide range of rumble effects (as anyone who has used an XBox / Playstation already knows). My program doesn't utilise these advanced features, because it will take too long to program and requires too much effort... :-P

Step 14: Car Startup/Shutdown Procedure

Since there are many individual hardware items on the car, the startup/shutdown process is a bit longer than a standard RC car. The start/shutdown procedures are summarised below:

Car Startup Procedure

- Connect the USB cables from the USB splitters into the powerbank. (IP camera + NeoPixels into the 2A connector, Arduino + WiFi router into the 1A connector). Wait a few seconds.

- Temporarily unplug the Ethernet cable going into the yellow port on the WiFi router, and plug it into the blue (Internet) port.

- Wait a few seconds, and the WiFi should be active. Connect to it with the laptop.

Unplug the Ethernet cable from the blue port, and plug it into the yellow port.

- Connect the USB XBee Explorer (with module) to the laptop.

- Connect the XBox 360 controller

- Start the C# program on the laptop.

- Press the button to connect the serial interface (change COM number in textbox if required)

- Make sure the Serial Input text box is populated and STABLE - no flickering of invalid data

- Connect power to the ESC on the car, and turn it on

- Start video on C# program (change IP address in textbox if required)

- The car is ready to go (finally!)

Car Shutdown procedure

- Turn off ESC first.

- Close the C# program

- Unplug powerbank cables, disconnect NiMH battery from ESC

Operation Issues

If the Serial input starts to flicker, shows incorrect data, and does not recover within a few seconds, the ESC should be turned off as quickly as possible. This problem can occur due to the XBee modules not coping well with the range or the data being transmitted. The C# program should then be restarted. After the serial connection is re-established, the ESC can be turned on again.

Note: Dropping the frequency of messages (by increasing the delay in the Arduino sketch) can improve reliability over longer distances, but unfortunately also increases lag.

Step 15: Conclusion

Picture of Conclusion

The car works well, but there is definitely room for upgrades and improvements! Some of these potential improvements are below:

Camera video quality - The IP camera I used only provides low resolution video, at low frame rates. I think that replacing it with a Raspberry Pi, with camera module, will improve the video (both resolution and frame rate) a lot. The Raspberry Pi can be configured to output an MJPEG stream, so it should be a simple upgrade. Alternatively, it would be great to get live H264 video (from a HD IP camera) through the C# program. However, I'm not sure where to start, or if it's even possible.

******UPDATE******

I have changed the camera solution to a Raspberry Pi 2 + Raspberry Pi camera module. The quality is much better than the original IP camera. The camera module is attached to a new pan/tilt mount, with two additional servo motors. Due to the extra servos, the NeoPixel stick has to be disabled. The camera change required software changes to both the arduino sketch and the C# program. The updated files are attached to this step.

Also, the YouTube video above shows the new configuration with the Raspberry Pi camera.

Camera pan/tilt speed - for simplicity, I chose an IP camera with built in pan and tilt motors. Although they are convenient, they are slow and imprecise. It would be better to use a fixed camera, mounted on standard servos. However, this will need a servo controller board if NeoPixels are also used, as the TiCoServo library only supports two servos (already used by the ESC and steering servo).

******UPDATE******

A new pan/tilt mount was added at the same time as the Raspberry Pi camera - see the YouTube video above.

Rollover Protection - with a high centre of gravity and (relatively) soft suspension, the car is prone to rolling over! I've used some tall screws at the front to protect the Arduino, but there is no protection for the IP camera or WiFi router. However, a roll cage will add more weight, high up, encouraging it to roll over even more...

Speed - I'm still using the original motor that came with the car. It is a little slow at top speed, so I might swap in a higher speed (lower torque) motor later on.

More functions - There are still heaps of spare buttons on the XBox controller, that haven't been assigned to any function. What are your suggestions for new functions?

Comments

SMILEY4242 (author)2017-08-04

This is great! I purchased a rock crawler jus for this purpose. I was wondering where did you get the stronger springs? I was planning to use my raspberry pi 3 and python, what are your thoughts on that?

getburnt (author)SMILEY42422017-08-06

Thanks for reading! I can't remember exactly - it was either an ebay seller or an online RC store. My rock crawler is a copy of an Axial Racing chassis, so it was easy to find compatible springs.

Raspberry Pi and Python is great if you want to use WiFi to communicate with the car. My latest project (see my YouTube channel) uses a Raspberry Pi and arduino. I ditched the XBee modules for the new project - the communication path I'm now using is Laptop <--WiFi (UDP)--> Raspberry Pi 3 <--Serial--> Arduino --> Motors / Sensors

TomasN29 (author)2017-06-05

Could i use usb camera ?

getburnt (author)TomasN292017-06-08

The software only works with an IP camera configured to stream MJPEG video. It won't work with a USB camera in its current state.

McZenithWorld (author)2016-12-28

Hello Sir, do you have any idea how to code the live streaming from FOSCAM IP Camera to Android phone? We are having the same project but the display is on the phone and the controller also.

getburnt (author)McZenithWorld2016-12-29

Hi, I haven't tried to do this myself, but some people have written apps for viewing IP camera streams on their Android device. If you do a Google search for "android mjpeg stream viewer" there are a few results which may help.

DNMEBOY (author)2016-10-26

I'm just terrible at coding. Building robots and stuff and picking apart other people's code I can do but writing my own from scratch is a no go for me. What you just said though about controlling the esc may be helpful if I give it a try again. Right now my only Arduino that's not in use has an issue where I can't upload to it no matter what I do. I'll have to order a new one to try again.

getburnt (author)DNMEBOY2016-10-27

Feel free to use my code as an example. Also, I find that making very small / basic Arduino sketches that only do one thing is a good way to start. Once you have a few of these, you can combine them slowly, and you'll eventually have something complicated that you made from scratch

DNMEBOY (author)2016-10-25

I have the Losi night crawler 2.0. I've been dying to make it autonomous with Arduino but never managed to get past controlling the esc :(

getburnt (author)DNMEBOY2016-10-26

If there isn't enough documentation for the ESC in your car, you could replace it with a different ESC that is easier to program / interface with an Arduino. The Axial Racing ESC I used has pretty good instructions for setting it up. On the Arduino side, controlling the Axial ESC is the same as controlling a servo - a value of "0 degrees" is full speed reverse, "180 degrees" is full speed forwards, "90 degrees" is stopped.

TheMasterOfAll247. (author)2016-10-16

Hey, just wondering if it was possible to control this car using a keyboard instead? If so, what is the most recommended way to achieve this? Also, are XBee modules the best choice if I want to use a keyboard?

If you are familiar with C#, you could probably modify the C# application to accept keyboard input, instead of an Xbox controller. However, you would lose fine motor/steering control, as the keyboard can only provide on/off signals (instead of the "analog" sticks / triggers).

The wireless communication method doesn't really matter. I like XBee modules (series 1) because they are very simple to setup and use (they work as a serial interface), but they are not reliable over long distances. (If you use something other than XBee / serial, the C# application would need extra modification)

Ah, thanks, but another question : What would you suggest as a communication method that would best be used for long distance?

There are some alternatives such as HC-12 modules. I haven't tried these yet, but apparently they can handle long distances (not sure about latency / transfer rates). You might need to check frequency / transmission power limits in your country.

If you are planning to use it in a fixed location, another option is WiFi with a few WiFi repeaters to increase coverage area. WiFi is probably one of the more robust solutions for reliable data transmission (but it is more complicated to use than a serial based interface).

SebastiánP63 (author)2016-07-28

Hello, Is possible make an app to drive this car by phone (SO: Android)?

getburnt (author)SebastiánP632016-07-29

Hi, it is probably possible with some modifications - for example, by changing all the communication to WiFi (instead of XBee + WiFi). However, I've never made an Android app, so I'm not sure how difficult it would be.

AhmedS280 (author)2016-04-29

Hello: How can I get the body of this car (4x4 rock crawler Cassese)?

getburnt (author)AhmedS2802016-04-30

Hi, I got mine from ebay. I'd suggest trying ebay or amazon to get a similar RC rock crawler (1/10 scale)

AhmedS280 (author)getburnt2016-05-02

Please can you give me a link for it ! I looked, but I did not find one resembling it exactly

getburnt (author)AhmedS2802016-05-03

This is the model I used (eBay Australia):

http://www.ebay.com.au/itm/NEW-HSP-1-10-RC-Remote-...

These ones are quite similar, but are from different brands (Amazon US):

http://www.amazon.com/MaxStone-Powerful-Electric-C...

http://www.amazon.com/Redcat-Racing-Everest-10-Wat...

If you're willing to spend more money, I'd recommend something like a Tamiya CR01, which probably is of much better quality.

AhmedS280 (author)getburnt2016-05-05

Thank you ^^

actionmm (author)2016-04-09

Hello :)
Do you think is it possible to convert this into a mobile app?
I want to do this project but make it a mobile app with live streaming and controlling the car?

getburnt (author)actionmm2016-04-10

Hi, it is probably possible, but the design would need some modifications. For example, instead of using XBee for car control, it would be better to use WiFi to make the car completely WiFi based. (but the car might have slightly less range for controlling steering/throttle with WiFi).

MJPEG viewer apps are available for Android / iPhone, so there are probably libraries available for making a custom app that can display video.

eddicuss (author)2016-02-18

Hello. I am in the process of building this project with the same exact hardware but without an accelerometer or neopixel stick. I edited the arduino code with no problems. I do have a hiccup on the C# program though. I have downloaded the xinput wrapper and added the xinputdotnepure.dll to the references and also copied the xinputinterface.dll to where the .exe file is. When I "start" the program, I get a popup error message that reads "An unhandled exception of type 'System.AccessViolationException' occurred in XInputDotNetPure.dll

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Any idea what this could be? On a side note, I tried to run the xinputdemo and it just crashes. I'm running Windows 7 Enterprise Service Pack 1 64bit if that helps. Any help will be greatly appreciated!

getburnt (author)eddicuss2016-02-19

Hi, I think it could be a 32bit / 64bit Windows thing. When I made this project, I used a laptop with Windows 8.1 64bit. I downloaded the 32 bit (x86) version of xinput and it worked fine on 64 bit Windows 8.1.

I just tried the 32 bit version of xinput on a Windows 10 64bit computer, and it doesn't work. However, the x64 version does - both xinputdemo.exe and xinputreporter.exe work properly. Maybe you can try the x64 version on your computer.

The github link is here: https://github.com/speps/XInputDotNet/releases

eddicuss (author)getburnt2016-02-19

Thanks for the quick response! So I tried the x64 version of the xinputdotnet release from the link you provided and got a different popup error which reads "An unhandled exception of type 'System.BadImageFormatException' occurred in mscorlib.dll

Additional information: Could not load file or assembly 'XInputDotNetPure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. An attempt was made to load a program with an incorrect format."

Any ideas? Thank you in advance!

eddicuss (author)eddicuss2016-02-19

Also, the xinputdemo.exe and xinputreporter.exe are working properly now.

getburnt (author)eddicuss2016-02-19

I forgot to mention that the C# project is configured to build for a x86 (32 bit) platform target. If you use the 64 bit version of xinputdotnetpure.dll you should change the project settings to build a 64 bit executable.

In Visual Studio, click "Project" -> "xbox_controller_test Properties" -> "Build" tab,

then select x64 for platform target.

I tried building a 64bit version of the executable, with the 64bit xinput wrapper and it runs successfully (on a Windows 10 64bit PC).

However, even though you're running 64 bit Windows, you should be able to create a 32 bit executable with the x86 xinput wrapper. Where are you putting the xinputdotnetpure.dll file? I've just put it in the debug folder (the same folder as the .exe and the xinputinterface.dll)

eddicuss (author)getburnt2016-02-21

ok so i got the C# program to work. Video is working and xbox360 controls are working in the C# GUI. I'm having a hard time configuring the two xbee modules to communicate. How did you set one to coordinator, at the other to router? The XCTU program only gives coordinator and end user in the drop down. I have the sparkfun xbee wireless kit with only one usb explorer. I got to configure one xbee module but can't get the other one configured and tested unless I take out the first one and use the usb explorer.I tried to "discover" it through COM3 where the arduino mega is plugged in with the xbee shield and module but it can't be detected. I guess my question would be is, how do I configure the xbee module connected to arduinomega/xbee shield via XCTU(while I have the other xbee module connected to PC/explorer USB.)?

getburnt (author)eddicuss2016-02-22

That's some great progress :)

I configured both of the xbee modules with the USB explorer. I put one of the modules into the explorer, configured it, removed it, then put the other module in to configure it. Once the modules are configured, you can leave one in the USB explorer and put the other one in the arduino shield.

To then test the connectivity, you can use a very basic arduino sketch. For example, make a sketch that receives ASCII text and prints it back out via serial. You can check that this works through the USB cable first, before trying with the xbees. (Or, you can test the interface with the C# application and the arduino_rc arduino sketch)

One thing to check when you first try the xbee interface is the COM port that Windows has assigned for the USB explorer. It will probably be different to the COM port assigned for the cabled Arduino connection.

(Also, if you are using an Arduino Mega, I recommend configuring the xbee shield to use Serial1 instead of Serial0. I couldn't get it to work on Serial0. Also, this gives you the advantage of debugging through dual serial interfaces - you can still have the USB cable attached while using the xbees. If you are using an Arduino Uno R3, there is only one serial interface, so you can't use the USB cable at the same time)

eddicuss (author)getburnt2016-02-23

Ok so I got the xbee modules to communicate via XCTU software but not through arduino. In the XCTU console when i close the conection and input a character, the xbee module on the arduino lights up indicating reception. But when I upload the arduino sketch(arduino_rc_neopixels) it doesn't work. I'm not sure if my loopback connections on serial1 are correct. I just connected 18 to header 3 and 19 to header 2 with some jumper wires. Do you have a pic of these connections by any chance? Or any suggestions? Thanks!

getburnt (author)eddicuss2016-02-24

The loopback connections are correct. Are you using the arduino sketch with the C# application? The arduino sketch will only respond to input data provided by the C# application (it won't respond to the XCTU console).

You can try debugging the xbee interface with the arduino USB cable serial connection (i.e. run the xbee interface as well as the USB serial interface).

First, get the C# application and arduino sketch started with all the xbee modules. Make sure the COM port for the xbee USB explorer is typed in to the C# program, and click "Connect/Disconnect Serial". Then, open the arduino serial monitor (configured to the COM port for the arduino USB connection) to see if it displays any text. This is one way to check if the arduino is actually receiving the data - it should work straight away if the xbee modules are working correctly.

Also, on an unrelated note, if you are using the original C# program (the one for the Foscam IP camera), you should change the value of a buffer to prevent (occasional) image corruption. There is a line:

const int BufferSize = 64000;

You should change it to a much larger value, eg 1000000

eddicuss (author)getburnt2016-02-24

This may be a dumb question, but am I supposed to configure the xbee modules to a baud rate of 38400 and change the COM ports as well to 38400? Also, when I upload the arduino sketch and open the serial monitor on COM3, I get these weird text characters:

ÿÿÿÿ

0 0

A,ÿÿÿ,,F,ÿÿÕ,O,Z

This is at a baud rate of 38400 without the C# application running. When I run the C# app, I can connect to COM4(Xbee module/USB explorer) but do not receive any data through the output textbox.

getburnt (author)eddicuss2016-02-25

Yes, all the baud rates should match. Also double check the data bits (8), parity (0) and stop bit (1). Both sides of the serial interfaces should match. You will usually get weird characters when the baud rate is mismatched.

To speed up the debugging process, I'd recommend creating a really simple arduino sketch. If you can get the xbee modules working with a basic arduino sketch, it should be easy to get the xbees working with your RC car. For example, to get started, write a sketch that reads in serial data from Serial (arduino USB cable), and sends out the same data over both Serial (arduino USB cable) and Serial1 (xbee). Use the arduino serial monitor for the USB serial connection and the XCTU console for the xbee USB explorer connection. Then, keep adding functionality until you can send data from your computer's xbee port, and receive it through the xbee port.

(Also, there is a switch on the xbee shield. Make sure it is set to DLINE, not UART)

eddicuss (author)getburnt2016-02-20

I did exactly this and it fixed it somehow. Building the 64bit version of the executable was a success. However, when I start it from within Visual Studio Express, I get another pop-up error that reads "An unhandled exception of type 'System.BadImageFormatException' occurred in XInputDotNetPure.dll

Additional information: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)".

I did put the xinputdotnetpure.dll file along with the xinputinterface.dll file in the debug folder. I can run the .exe file(the one in the debug folder) with success now. Before, it would just crash. I'll keep you updated. Thank you so much for all the help!

eddicuss (author)2016-02-24

I don't think the arduino sketch is uploading if that's the case. When I open the XTCU console and input a character, I can read it on the arduino serial monitor(receiving end). Also, the arduino serial monitor continues keeps displaying 2 zeros.

AbdellahM (author)2016-02-22

i can use another camera

and another rc car

getburnt (author)AbdellahM2016-02-22

If you use a different camera, you will need to modify the software - I'd recommend using a raspberry Pi + camera module (see the last step).

You can use a different RC car, as long as the ESC can be controlled with an Arduino (most ESCs should be ok)

diex0n (author)2016-02-15

Hi and thank you for this awesome project. I have a slightly off-topic (but still a relevant question). I want to connect a usb webcam to a stationary Arduino Yun and let it stream live video rather than Pi 2. You state that Arduino isn’t powerful enough for video but I wonder if Yun model with a 400Mz cpu would be up to such a task? If so could I also stream live audio with it, and if not can I stream both audio and video with Pi 2? I saw a project similar to what I intend to do here: https://learn.adafruit.com/wireless-security-camera-arduino-yun/stream-video-to-youtube Thanks in advance and keep up the great work!

getburnt (author)diex0n2016-02-16

Thanks for reading my instructable! I haven't used an Arduino Yun before, but it should be fine for video (it is very different to an Arduino Uno or Arduino Mega!). I'm not sure about the audio on a Yun.

A Pi 2 should be able to do both audio and video, but some people seem to experience sync / delay issues:

http://dius.com.au/2015/03/25/raspberry-pi-baby-mo...

https://www.raspberrypi.org/forums/viewtopic.php?f...

HuY2 (author)2015-11-27

Anyone managed to get this working with xBee series 2 modules? My local stores only seem to sell series 2 modules. :(

getburnt (author)HuY22015-11-29

If you think you can use the series 2 modules in some of your future projects, it might be worthwhile getting them, and trying them out for this project. I had a lot of strange connection issues with the series 2 modules, but you might have better luck than me.

(I'd still recommend getting the Series 1 Pro modules if you can - maybe try some online stores?)

HuY2 (author)2015-11-21

Why not control the arduino using an ethernet shield connected to the router?

getburnt (author)HuY22015-11-22

The XBee modules have slightly better range than WiFi. So, I can still control the car and bring it back into range when the Wi-Fi signal starts to fade (when the video drops frames and gets choppy).

HuY2 (author)getburnt2015-11-25

Oh thanks :) Is it also possible to use a wireless xbox 360 controller instead?

getburnt (author)HuY22015-11-25

Yes, a wireless Xbox 360 controller should work too

ligacampeon (author)2015-11-17

goood

LuisK1 (author)2015-10-21

Good Project how to do get low fps with the pi camera? Greatings from Chile :D!

getburnt (author)LuisK12015-10-22

Thanks! The Youtube video in the instructable shows the old design without the Raspberry Pi camera (it uses a surveillance camera, which has a low fps). If you check my Youtube channel, there is a video with the Pi camera. The Pi camera has a much higher fps and a clearer image. Also, the fps is configurable, through the "UV4L" driver (I use 30 fps).

LuisK1 (author)getburnt2015-10-22

Thanks do you have this configuration? i made a similar project, but for the moment i use a usb camera, in the c# application do u use the same old code?

About This Instructable

68,407views

234favorites

License:

Bio: I'm an engineer from Australia
More by getburnt:Arduino RC Car with FPV CameraArduino Laser Engraver
Add instructable to: