RC-IP Drone

Description

The purpose of this project was to control an RC car with an Xbox 360 wireless controller and mbed. The electronic speed control on the car is interfaced by sending UDP packets over IP and through a wireless router. The principles in this project should apply to any electric RC car as long as an ESC is present, however, parts used and tested listed in the Hardware section.

Team Members

  • Tyler Drake
  • Sam Litchfield
  • Richard Farr

Hardware

In this case, the parts that comprise a Traxxas Rustler XL-1 and XL-5 were used.
XL-5 model here: Traxxas Rustler XL-5

Most important RC parts for basic functionality:

Parts required for mbed functionality

  • mbed LPC1768
  • Ethernet Breakout Board
  • LM7085 +5V Voltage Regulator & Two 1μF-10μF Capacitors
  • Stable 7-18V Power Supply
  • IOGear GWU627 Wifi-Ethernet Adapter (Optional)
  • Xbox Wireless Controller
  • USB External Batteries, powering Mbed, IOGear
  • TP-Link WR702N Wireless Router (Optional)
  • Android Phone as IP Camera
  • Laptop/PC

Mbed and the servo will be powered from the regulated 6V output from the XL-5 ESC.

The Xbox 360 Wireless Receiver will need to be powered off of the 7-18V power supply through the use of the LM7085 voltage regulator. It was found that keeping this device on its own power supply was the most stable option as it seems to draw a lot of power. In initial experimentation, an Energizer 9V battery was drained over the course of approximately 5-6 hours. A more stable power supply (preferably rechargeable) is being searched for.

In this state, the RC car has two power switches. One on the ESC itself, and another to send power to the USB port.

Software

The software behind the Xbox 360 Wireless Controller and Android IP Camera are handled on the Laptop/PC end. The Xbox controller uses the Xinput API and the reception of the IP camera video feed uses Videocapture from OpenCV. UDP interfaces between mbed and the Laptop/PC are handled through the Winsock API.

In using an Android phone as the IP camera, an app called IP Camera can be downloaded from Google Play that provides a versatile and stable output.

Also, since there is an ESC between mbed and the motor, it was discovered that the ESC operates exactly like a servo. So, instead of trying to drive the motor with a standard PwmOut or Motor output, it is better to use the Servo class.

/media/uploads/rfarr6/img1.jpg

main.cpp

#include "mbed.h"
#include "EthernetInterface.h"
#include "Servo.h"

const char* SERVER_ADDRESS = "192.168.0.100";
const int SERVER_PORT = 7777;

Serial pc(USBTX, USBRX);

Timer t;

int main(){
    pc.printf("\rAttaching on 192.168.0.101\n\r");
    EthernetInterface eth;
    eth.init("192.168.0.101", "255.255.255.0", "0.0.0.0");
    eth.connect();
    
    pc.printf("Binding to UDP socket 7777\n\r");
    UDPSocket sock;
    sock.bind(7777);
    sock.set_blocking(false, 2); // don't block, check 500 times a sec
    
    Endpoint server;
    server.set_address(SERVER_ADDRESS, SERVER_PORT);
    
    char in_buffer[256];
    char*  heartbeat = "";
    int bytes_found;
    int left_x = 0, left_trigger = 0, right_trigger = 0;
    int failcount = 0;
    
    Servo engine(p24);
    Servo servo(p23);
    
    while (true) {
        // receive information, send back heartbeat
        bytes_found = sock.receiveFrom(server, in_buffer, sizeof(in_buffer));
        if(bytes_found == 7) {
            
            failcount = 0;
            heartbeat = "Good";
            pc.printf("BAD NO\n\r");
            // unpack information
            // |xx|xx|xx|
            //  ^  ^  ^- Right Trigger
            //  |  `- Left Trigger
            //  `- Left Stick X
            in_buffer[7] = '\0';
            pc.printf("%s\n\r", in_buffer);
            sscanf(in_buffer, "%3d%2d%2d", &left_x, &left_trigger, &right_trigger);\
            
            servo.position(-left_x-2);
            if(left_trigger > 0 && right_trigger == 0){
                engine.position(-left_trigger/2);
            } else if (right_trigger > 0 && left_trigger == 0){
                engine.position(right_trigger/2);
            } else {
                engine.position(0);
            }  
        } else if(bytes_found == -1){
            failcount++;
        } else {
            failcount++;
        }
        if(failcount > 25) {
            pc.printf("FAIL!\n\r");
            engine.position(0);
        }
        
        // Actually send results, and report output to serial port
        sock.sendTo(server, heartbeat, sizeof(heartbeat));
    
    } // end true
}


Please log in to post comments.