Search This Blog

Sunday, October 24, 2010

Now remotely controlled via IP

After some hobby time spenditure, the result meets the expectations. While it is a functional and simple (and a good fallback solution), controlling the car via a regular RC radio is not the most interesting scenario. Having a device that is mostly digital, being controlled by an analog receiver isn't quite the nicest thing one would want to showcase. With that in mind, and taking into account that all the necessary hardware was already there and working, I have decided to take a little bit of time implementing the necessary components to be able to control the car from a remote peer in a wifi network. As such all I had was to:
  • Select the transport: TCP or UDP;
  • Design the protocol for carrying the control messages;
  • Design and implement the server application (running in OpenWrt linux);
  • Design and implement the client application (running in Windows or desktop linux);
(1) For the first point I have chosen UDP. In this type of use case, a connection oriented transport would not be optimal, compromising the realtime requirements of the communication. Occasional packet loss, in this scenario, can be well handled by the receiver, which includes timeouts to handle loss of communication, by taking the appropriate measures. As the data flow doesn't have to be acknowledged, the power consumption of the car can be further reduced.

(2) In the second point, a very simple protocol for carrying the control messages have been defined. Each packet has the following:

  • CSEQ - (2 bytes) a field containing a sequential number for each message. It helps keep track of message order and rate of packet loss;
  • CODE - (2 bytes) describes the type of the message (can be CONTROL, STATUS, or KEEP_ALIVE);
  • LENGTH - (2 bytes) indicates the size in bytes of the payload (the field that follows);
  • DATA - (0 - 18 bytes) the data itself;
  • CHKSUM - (2 bytes) a simple 16 bit check sum of the entire packet.
The DATA packet of a CONTROL message has the following structure:
  • CHANNELS - (16 bytes) each channel is a 2 byte value which corresponds to the pulse width to be applied to the corresponding servo;
  • BUTTONS - (2 bytes) each button in the joystick is represented by one bit, which contains its status.
(3) For the third point, implementing a C application to handle the incoming control UDP packets wasn't such a big challenge. All I had was to use the OpenWrt kamikaze toolchain, and compile the code with appropriate gcc cross compiler. The application would use the previously implemented library for handling the serial communication with the PIC based servo control and acquisition board (Droids MuIn). Configure it to run as a service and wouldn't have to bother launching it while booting up the Fonera.

(4) For the client I have given preference to implementing it in Java. The only challenge however was that Java doesn't natively support Joystick devices, so I had to find a library to take care of that. After a bit of searching I have found JXInput (http://www.hardcode.de/jxinput/), which seemed to be a decent library, with reasonable documentation and examples. All I had to do was using this library in my application (in the form of a Jar), and have the necessary windows dll in my application folder. This dll establishes the bridge (through JNI) to the Windows Joystick (or any other HID) API. Here is a screenshot of my application:



It connects to the car, passing steering commands from the joystick device. The user can select the joystick to use, and enter the IP address and port of the car.

A few photos of the car, during a maintenance task. In the aileron is the battery pack for the control electronics (the Fonera and the MuIn):

A bottom view of the sensor and control block (the heart of the robot), with all the necessary components:


Now controlling the "beast" is as simple as playing a videogame :)

Don't need the big 41 MHz antenna anymore, great! It's now easier to get under the table and say...watch under the skirt :)


No comments: