4 July 2013

RC Due - A new genaration of open source RC vehicle controller


After battling with many ideas, I needed a board that could cater to someone that was always adding new features to their models. The RC Due project is currently in early development and more information will be released within the coming month. The hardware and software will become open source and it is hoped that a strong community can form around it and develop together.

The currently hardware will boast:

- ARM cortex M3 microcontroller (same as the Arduino Due)
- Arduino compatible
- 12 PWM channels
- 11 ADC channels
- 2 DAC channels
- On board xbee header
- 9 DOF position sensors (accel, gyro, mag)
- Altimeter
- 8 GPIO
- I2C, SPI, Serial
- Powered from standard ESC or BEC

These features may change





A bit-o-history...

The inspiration started with a small RC car about three years ago. The Mini-Z was a fun toy for me whilst in my first year of university. We were often told of the great power of control systems engineering and how smarter electronics are replacing many current complex mechanical systems.

Whilst making adjustments to my mini-Z, I thought... All these gears, shafts and differentials are taking space and reducing efficiency in the model. There must be a way to drop all the mechanics and turn them into an easily adjustable electronic system. The simple idea of using individually driven wheels, removed the need for nearly all the moving parts within the model.

If these motors could be controlled individually and according to various amounts of turning and speed, there'd be so much room for fine tuning and even on the fly adjustment for various parameters.

Several prototypes evolved, with various features come and gone. Different ideas and expansion capabilities were explored and trade offs made to achieve a good overall design. Below is shown a prototype that used a PCB as a chassis for a small 1/18 scale car with the suspension and wheels attached. The PCB would hold all the control, power and wireless circuitry for the car and the batteries would sit on top.


After some more work it was realised that this wasn't a very flexible platform. Everyone's needs would be different and this all in one design wouldn't allow for much expansion.

The next step was to break everything down to the bare bones and think about how others would implement this system. All the power electronics were stripped from the design, allowing for power electronics of any given rating to be used. It was realised that the same control hardware could then be used on planes, copters or even boats.

The RC due was born!




Comparison to existing products...


This platform follows on from the same ideas as other popular RC controllers such as the Autopilot or KK2 boards. They are both cheap, configurable and loaded with sensors.They do however lack the I/O options for my application. I hoped to create a vehicle with many sensors and active suspension controls. Therefore required every ADC and PWM channel I could get. I wanted to keep with the Arduino platform to allow for unity with many of the pre existing hardware and community. It was decided that the new Arduino Due would serve as the base platform for the design.



Update as of 04/07/2013...


Currently waiting for the new PCB to arrive from OSH Park. Once it's in, I should be able to order the components I need for the new board and solder it up.

I've already tested the accelerometer (MMA8452Q) and gyroscope (L3G4200D) from the previous board. That portion has been carried over so should work right away. I found some example code for both the MMA8452Q and the L3G4200D. The both work as expected.


Update as of 17/07/2013...



I got the three boards back from OSH park. Very nice purple soldermask. First class USPS took nearly three weeks though...



*snap fingers*


After a long day of soldering yesterday, the board has been built. All the sensors are working as well as the xbee and the microcontroller.

A few problems I came across involved a short on the PCB. On the first board I started with, there was a short to ground on the 3V3 rail with no components loaded (It's now a drinks coaster)..

On the second board there was no short so I started putting all the devices on and testing one by one. I had a hell of a time soldering the tiny accelerometer and gyroscope chips, but in the end, I got them down and working. Look out for an SMD soldering tutorial video soon!

Here are links to some useful example code I used to test the various devices...

-   I2C scanner - Scans all the devices on the I2C bus and returns their address
-   L3G4200D Gyroscope Example
-   MMA8452Q Accelerometer Example

It seems that the Wire.h library doesn't work on the new Arduino Due. This is due to a different implementation and a different library has to be used. I'll be experimenting with this within the next few days, but in the mean time, I hooked an older AVR chip to the I2C line and ran the code.

Now, a very wise lecturer told me while I was in college, "If your circuit works first time, go buy the lottery because it will be the luckiest day in your life"

Where as the circuit didn't start the first time (due to the dodgy PCB), the spare board I had did work. I've so far found one area to improve on. The pull up and pull down resistors on the SAM3XE's reset and erase pins are unnecessary and cause strange behaviour. I've found a work around with the current board by replacing the entire resistor array with a 1k rather than a 10k.

The next tasks are to test all the IO pins, PWM and analogue inputs. Once that is done and working, I can get some code going.

The biggest challenge right now is with the Arduino Due's I2C bus implementation. The hardware is fine, but there is a problem with the current library. It might take some time to fix >.<

Update as of 23/07/2013...

Mud.. mud.. glorious mud!


So now the board is partially functional. Above is a "glamour shot" of the RC car platform.. What???! You expected a clean rally car?! Okay, here's a closer look...


There will be another post explaining the RC car platform in further detail as that in itself is a different project.

The board remained fully functional throughout the first testing and was easily cleaned under a running tap. While powered off of course.. As mentioned before the board is designed without components that could get clogged up and be difficult to clean. That means no USB connectors, no buttons or switches. These components would quickly be rendered useless from water sand or dirt. I hope to have the final production version conformal coated so it will be even more resistant!

Below is shown the RC transmitter. It consists of an Xbox controller, battery pack, Arduino USB shield, Arduino nano and XBee radio. It has fairly decent range, enough for a car, though a dipole antenna may be a good idea for flying vehicles.


With help from some code at circuitsathome.com, the transmitter was easily programmed to talk to the RC Due controller. 

An important consideration was safety due to transmission errors and loss of signal. I was running the XBee modules at 115200 baud so the error would be high. A simple serial to PWM output program would have the issue of causing the vehicle to go out of control if corrupt data was received and/or signal was lost. One example; suppose the controller sent a throttle value of 10% and steering value of 80%. If the received signal was missing the first packet, then the 80% steering could be applied to the throttle rather than the steering...
Then the problem of loss of signal; suppose the transmitter measured the controller throttle stick value and sent it to the receiver. The receiver would apply this value to the motor system and then the vehicle may go out of range. It would be expecting to receive a new throttle value to update the motor speed, but it would never get one. A program without a time-out on the throttle would have the vehicle on its previous throttle value indefinitely. Oops! Runaway car!!

To prevent these problems, simple solution was put into place.. The transmitter would send a fixed number of bytes/packets X(n). The receiver would then expect the same fixed number of packets X(n). The total data sent would start with a special pre defined start byte and end with a checksum value. The figure below shows the basic implementation...

This method has so far proved to be quite robust. The car does indeed stop when it goes out of range or begins to get too much corrupted data. The board will never apply corrupted data to the outputs so there is no jitter or jerky movement to the car when it starts to loose signal.

The source code so far is shown below. There are extra options for steering and throttle range as well as some housekeeping.

Transmitter side Arduino code:

#include <XBOXUSB.h>
USB Usb;
XBOXUSB Xbox(&Usb);

// Servo range for 333Hz should be: 85 <-> 170. Center = 128
    
const int fullLowRate = 85;
const int fullHighRate = 170;

const int steeringTrim = 0;
const int steeringLim = 20;
const int throttleLim = 0;

int throttle = 145;
int steering = 130;
int bakLight = 128;
int brkLight = 0;
int checksum = 0;

void setup() {
  Serial.begin(115200);
  if (Usb.Init() == -1) {
    while(1);
  }  
}

void loop() {
  Usb.Task();
  if(Xbox.Xbox360Connected) {
    throttle = Xbox.getButtonPress(R2) - Xbox.getButtonPress(L2);
    steering = Xbox.getAnalogHat(LeftHatX);
    throttle = map(throttle, -255, 255, fullHighRate + throttleLim, fullLowRate - throttleLim);
    steering = map(steering, -32768, 32467, fullLowRate + steeringLim + steeringTrim, fullHighRate - steeringLim + steeringTrim);
    
    if(throttle > 128){
      bakLight = 0;
      brkLight = 0;
    }
    
    else{
      bakLight = 200;
      brkLight = 255;
    }
    
    Serial.print('.');
    Serial.write(throttle);
    Serial.write(steering);
    Serial.write(bakLight);
    Serial.write(brkLight);
    checksum = (throttle + steering + bakLight + brkLight) / 4;
    Serial.write(checksum);
    delay(5);
  }
}


Receiver side Arduino code:

const int throttlePin = 9;
const int steeringPin = 8;
const int bakLightPin = 7; 
const int brkLightPin = 6;

int lastSerialTime = 0;
int currentSerialTime = 0;
char serialInputArray[5];
int checksum = 0;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
  pinMode(throttlePin, OUTPUT); 
  pinMode(steeringPin, OUTPUT);
  pinMode(bakLightPin, OUTPUT); 
  pinMode(brkLightPin, OUTPUT);
  
  lastSerialTime = millis();
}

void loop() { 
  while(Serial.available()) {
    if(Serial.read() == '.')
      Serial.readBytes(serialInputArray,5);  
      checksum = ((int)serialInputArray[0] + (int)serialInputArray[1] + (int)serialInputArray[2] + (int)serialInputArray[3]) / 4;
      if(checksum == (int)serialInputArray[4]){
        lastSerialTime = millis(); 
      }
  }
  
  currentSerialTime = millis();
  
  if(currentSerialTime < lastSerialTime + 100){
    analogWrite(throttlePin, (int)serialInputArray[0]);
    analogWrite(steeringPin, (int)serialInputArray[1]);
    analogWrite(bakLightPin, (int)serialInputArray[2]);
    analogWrite(brkLightPin, (int)serialInputArray[3]);
  }

  else{
    analogWrite(throttlePin, 128);
    analogWrite(steeringPin, 128);
    analogWrite(bakLightPin, 128);
    analogWrite(brkLightPin, 128);
  }
}


The next task is to address a PWM issue. Standard servos and ESCs like a PWM signal as shown below:


The PWMs on the Arduino however are fixed to 1kHz. A servo requires 50Hz with a small high period. Changing the PWM frequency on Arduino is by no means a trivial matter. Sure a servo function exists to make it easier, but my outputs are inverted due to 3.3V to 5V inverter and the library claims to be jittery with a large number of servos.

I have managed to change four of the PWM channels to a 3ms period (333Hz). This number is found by doubling the 1.5ms duty cycle for a centred servo position. It allows for good PWM resolution with duty changing from 1ms to 2ms. For an 8 bit resolution (0 - 255), full servo range is from 85 to 175.

The other 7 PWM channels require modification of register and timer values which may throw off various time dependent functions built into the Arduino source code. One of which I rely on to provide loss of signal time-out.

This along with the I2C problem is the next hurdle!


Update as of 31/07/2013...

Latest hardware schematic:



Order a blank PCB here.

Get the Kicad design files here

Some more misc files, bits of code, etc. here

3 comments:

  1. Hi,

    I'm very interested by the PCB chassis design. Could you share more info on why I you didn't continue this way, what are the dimensions, what suspension linkage and wheels are you using, and maybe the PCD design files.

    Thanks,

    ReplyDelete