Saturday, January 28, 2012

Can I Control More Than X Servos With An Arduino ?

Yes, Yes, Yes, infact 'Yes' Twelve Times.

The Servo library for the Arduino UNO allows the control of upto 12 Servos on a single Arduino UNO. As the electronic speed controllers or ESC's used in remote controlled cars also use the same type of signal, you can control any combination of servos and speed controllers up to a total of 12 devices.

If you really need more devices you can -

1) Interface to an external servo controller - these are generally additional micro controllers but programmed purely to take servo related instructions from another source and manage the corresponding bank of servos.

2) Interface to another Arduino - this is the same as option 1) above but gives you some additional flexibility for instance you can share the collection and processing of sensor data across the two devices without having to learn a new micro controller.

3) Use one of the larger Arduinos - always an option, but when you can build a basic Arduino for less than 10 dollars option 2 looks hard to beat.

How does it work ?

If you have read the previous posts on interfacing to an RC Receiver you will understand that a servo signal is not at all what you might have been expecting. If you haven't read those posts, here they are -

How To Read An RC Receiver With A Microcontroller - Part 1

How To Read An RC Receiver With A Microcontroller - Part 2

So now that we understand that a servo expects a pulse of between 1 and 2 milliseconds to be sent about every 20 milliseconds, how does the Arduino control up to 12 servos all expecting these signals 50 times a second ?


Fortunately someone by the name of Michael Margolis has created the Arduino Servo library so that all we have to do is call two functions -

Arduino Servo Library


The Main Servo Library Functions -

1)  aServo.attach(pin_number); - This tells the library that there is a servo attached to pin number 'pin_number'. When the library attaches it will initially begin pulsing the servo with 1500us, this is the centered position for a servo, which is also the neutral position for a (RC Car) electronic speed controller.

2) aServo.writeMicroseconds(uS) - This tells the library to update the pulse width for your servo. There is another version 'write' which takes an angle instead of a microseconds argument. This version converts the angle to micro seconds and then calls writeMicroseconds, so if you do not need angles in your application, don't use them.

And now for an example, forget sweep, try 'multi sweep' -

Quick warning - Don't connect 12 Servos to the Arduino power pins, use external power or to just test the code using a single servo, connecting its signal pin to each of the arduino digital pins 2-13 in turn.

// Multi Sweep, Duane B
// Using the servo library created by Michael Margolis 
// to control 12 Servos with one Arduino Uno

#include <Servo.h>
// Sample sketch for driving 12 Servos from an Arduino UNO, servos are attached to digital pins 2,3,4,5,6,7,8,9,10,11,12,13

#define CONNECTED_SERVOS 12

// macro just adds two - the first servo is attached to digital pin 2, this gives us upto 12 servos - digital 2 to 13
#define SERVO_TO_PIN(x) (x+2)

Servo myServos[CONNECTED_SERVOS];

#define COUNT_DOWN -1
#define COUNT_UP +1
#define INCREMENT 10 // move in steps of 10 milliseconds

int nPulseWidth = DEFAULT_PULSE_WIDTH ; // 1500, defined in servo.h
int nDirection = COUNT_UP;

volatile unsigned long ulStart = 0;
volatile unsigned long ulStartToEnd = 0;

void setup()
{
  // attach the servos
  for(int nServo = 0;nServo < CONNECTED_SERVOS;nServo++)
  {
    myServos[nServo].attach(SERVO_TO_PIN(nServo));
  }
 
  // the library sets all servos to 1500 ms pulse width by default, this is center for a steering servo
  Serial.begin(9600);
  Serial.println("Completed setup"); 
}

void loop()
{
  delay(10);  // give the servos time to move after each update
 
  if(ulStartToEnd)
  {
    Serial.println(ulStartToEnd);
    ulStartToEnd = 0;
  }
 
  nPulseWidth += nDirection * INCREMENT;
 
  if(nPulseWidth >= 2000)
  {
    nPulseWidth = 2000;
    nDirection = COUNT_DOWN;
  }
 
  if(nPulseWidth <= 1000)
  {
    nPulseWidth = 1000;
    nDirection = COUNT_UP;
  }
 
  for(int nServo = 0;nServo < CONNECTED_SERVOS;nServo++)
  {
    myServos[nServo].writeMicroseconds(nPulseWidth);
  }
}

Great, so that works, but how and what does it cost us ?

The library makes extensive use of the 16 bit timer/counter, this has a cost to us. By taking over the timer, the library prevents us using analogWrite on digital pins 9 and 10, however on the up side we can control upto 12 Servos and there are still pins 3,5,6 and 11 to use with analogWrite. 

So how does the library manage to control 12 servos with a single timer ? is it a production quality approach or just a proof of concept ?

Note : Moderate simplification used to aid understanding and descriptive clarity below.

The library attaches an interrupt function to the timer which is called whenever the timer value matches its output compare register value. Think of this like the red hand on an alarm clock, when the hour hand matches the red hand, the alarm goes off. When the timer matches the output compare value, the interrupt function gets called.

In addition to this interrupt function, the library maintains an array of servo objects. Each servo object has two main fields, the pin it is attached to and the pulse width. Each time the interrupt function is called, it uses an array index to find the current servo object, then sets its pin LOW.

Next the array index is incremented to point at the next servo object, the code immediately sets this servos pin HIGH. These few lines of code represent the end of the pulse for the first servo and the start of the pulse on the next servo.

Next the function adds together the current timer value and the pulse width required for the current servo, this value is then put into the output compare register. This has the effect of ensuring that the interrupt will be called again in servo.pulsewidth microseconds from now.

This code has an effect a bit like the snooze button on the alarm, its basically saying, can you get back to me in a short while. In our case the short while is whatever the current servos pulsewidth is set to.

Note - This allows your code to carry on doing whatever it needs to, the timers and interrupts will work in the background to keep your servos where you want them.
 
At this point, however many microseconds later, the cycle starts again, the interrupt is called, the current pin it taken low, the next pin is set high, the pulse width of the new pin is added to the current time and then set in the timers output compare register to start the cycle again and so it goes on.

The table below provides a vastly simplified view of what happens each time the interrupt function is called -

Three servos 1,2,3 with pulsewidths of 1000,1500 and 2000

TIMER Servo 1 Servo 2 Servo 3 New value to set in output compare register OCRA1
0   HIGH LOW LOW current time 0 + pulse width 1000 1000
1000   LOW HIGH LOW current time 1000 + pulse width 2500 2500
2500   LOW LOW HIGH current time 2500 + pulse width 2000 4500

 
As far as I am concerned this is both elegant and simple as all the best code should be. Thanks to Michael Margolis for creating the library.

I hope this post will help clear some of the confusion around Arduino and mulitple servos using this great library.


In a future post I plan to cover servo trouble shooting.

Duane B

Stay Tuned ... and in the meantime let me know if you have found any of this useful.

Wednesday, January 25, 2012

Extra Channels On The Cheap

Ever wanted to add an extra channel to your car, boat, robot ?

One of the guys commenting on the blog mentioned that he was working on a tugboat project. This brought to mind the one or two marine models that I have seen, from memory these models are very big on scale detail and moving parts.

This set me to thinking what could a micro controller do in this environment ?

Something very quickly came to mind that could be used in this application or any other where you would like to add one or two 'toggle' channels to a model. These are channels that are either on or off, and are ideal for setting off signalling sequences, turning lights on and off, switching mix modes remotely, activating a scale winch or basically any other application you can think of that requires the ability to remotely switch something between two states or positions.

This is a very simple trick which I have used to remotely toggle between dad mode and child mode in one of my projects. The trick is to use the small zone between neutral throttle and the point at which the motor overcomes stall inertia.

If neutral throttle is a pulse of 1500, you can use 1510-1525 to toggle one action and 1475 to 1490 to toggle another action. The values may need adjusting in particular applications, but the concept is the same -


If the throttle is held in this region, switch an indicator light on and take a time stamp.

If the throttle moves out of this region, switch the indicator light off and clear the time stamp.

If the throttle remains in the region, check the time stamp against the current time, if the difference exceeds your switch period, then toggle your mode/lights/winch whatever.


Its the method I use to switch modes in the child mode project, its incredibly useful to be able to switch parts of your code on and off remotely while the model is running. But the same approach applies equally well to all sorts of scale model applications such as I have suggested above.

As we are using the stall space around neutral, our model will not be moving, so there is no reason why we could not combine this with the steering channels to add even more channels.

By my calculation using throttle and steering channels gives 2 (up,down) * 3 (little left, little right, centered) = 6 on/off channels.


How much do these extra toggle channels cost ? An Arduino UNO is around 20 GBP but you can assemble your own from components for 7 GBP and the best part is the Arduino can do a lot more than just switch something on and off, any one of those six toggle channels could set off pre programmed sequences across multiple servos, lights, speakers and other actuators.

Simple Example - Toggling One Mode Using Throttle Channel

  if(nThrottleIn <= THROTTLE_THRESHOLD && nThrottleIn >= (THROTTLE_THRESHOLD-20))
   {
     unsigned long ulCurrentCounter = millis();
     if(ulModeSwitchCounter == 0)
     {
       ulModeSwitchCounter = ulCurrentCounter;
     }
     else
     {
       if((ulCurrentCounter - ulModeSwitchCounter) > MODE_SWITCH_DURATION)
       {
         
ulModeSwitchCounter = 0;
          // SWITCH YOUR MODE HERE

       }
     }
   }




Duane B.





Friday, January 20, 2012

How To Read an RC Receiver With A Microcontroller - Part 2

If you read 'How To Read an RC Receiver With A Microcontroller - Part 1' you will probably have guessed that my approach is based around interrupts, you may even be thinking 'So what, there is nothing new in any of this'.

Your right on the first part, but writing the code to take control of the throttle signal on my 40Km/h RC Race car was a very long way from reading a signal and writing it to the serial port.

What Could Possibly Go Wrong ?

The real world quickly gets in the way - underground cables, vibration, noise from the RC Components in the car, mobile phone transmitters, the built up environment, low transmitter batteries, even passing traffic effects the signal.

During the design and test of the code, I had two hardware problems with a dry solder joint on the power capacitor attached to the electronic speed controller and a track on my low quality strip board which crumbled away. At the time I was not aware that these hardware issues were the cause and so I investigated every conceivable cause of interference.


Power Capacitor Soldered to ESC Power Terminals
Strip board track repaired after crumbling away!


One simple test repeated since the hardware issues were resolved involved propping the RC Car wheels off the ground and then walking away from the car with the transmitter. I repeated this many times, increasing the distance or changing the line of sight to include/exclude features in the built up environment. I was very surprised to see just how badly the signal degrades as you move the transmitter away from the car.



Transmitter and Receiver Adjacent To Each Other

Transmitter and Receiver 20 Meters Apart.



The charts show the pulse width variation over time with the transmitter set at a constant neutral signal. A straight line would indicate there is no variation in the pulse width, this is the result we might initially expect.

The two charts are generated using the code presented in the preceding post 'How To Read an RC Receiver With A Microcontroller - Part 1'


To create the charts, the serial output was cut and paste into Microsoft Excel.

The charts clearly show that as the distance between the transmitter and receiver increases, so the variation in the signal increases. My tests have shown that the built up environment has an additional effect, further compounding the effects of distance.


With no controller input and the transmitter positioned just 20 meters away, the signal output by the receiver would randomly wander by as much as 30 milliseconds either side of the transmitter signal. Some of this would be due to the built up environment, moving the transmitter to a position occluded by a steel reinforced concrete pillar would cause chaos in the servo at only 20 meters.

So this isn't going to work is it ?

Not only does it work, but it works brilliantly. The best thing I can say about using the Arduino to control the throttle signal is that you can't tell its there.

The first few times I drove the current version of the software I kept having to bring the car back in to check that I hadn't shorted something and bypassed the Arduino completely.

So how does it work ?

First of all the mechanical nature of the servos and motors in our equipment provides a certain amount of signal smoothing, put simply, they just cannot move fast enough to react to the variation in the signal and so their position at any point in time reflects an average value of the signal in the preceding milli seconds.

Sample signal variation over 1 second - a random walk around the value 1540 - the value output by the transmitter.


In addition to the smoothing provided by the mechanical nature of the car, I have included a 'confidence' algorithm in the code. This algorithm compares the current input to the previous output, if the variation is small it ranks the new signal with a low value, if the variation is larger, the signal scores a higher degree of confidence. If the signal returns to its original value the confidence is reset to zero. The basic concept is that if we receive a vastly different signal, the chances are that its a new command from the driver, but if we receive a series of wandering signals they can generally be ignored provided that they do not creep in one direction which would indicate a subtle but valid input from the driver.


// Confidence Version 2, smaller, better, faster ?

int nDifference = nThrottleIn - nThrottleOut;

 if(nDifference == 0)
 {
    nConfidence = 0;
 }
 else
 {
   nConfidence += (nDifference/4);
 }
  
 if((nConfidence >= SENSITIVITY) || (nConfidence <= -SENSITIVITY)) // SENSITIVITY = 8
 {
   nConfidence = 0;
  
   // do something with this pulse ....
 }



I am currently open minded as to the value of the confidence algorithm. Standard RC Equipment works well enough without the addition of this algorithm, however it is at a cost of battery drain, heat and mechanical wear. The real value of the algorithm in a mircocontroller environment is potentially in providing a lightweight, easily tuned mechanism to condition the signal for input into subsequent algorithms without introducing the lag that results from smoothing across multiple samples.

The following charts show a badly degraded signal before and after the simple confidence algorithm -

Signal Before Algorithm


Signal After Algorithm


In the charts above, the confidence algorithm clearly smooths a large amount of the signal noise, however it is too sensitive to cope with the extremes.

One feature of the algorithm is that the sensitivity can be easily changed through a single variable. 

Test Conditions 
The tests were performed with the transmitter and receiver at opposite ends of a steel reinforced concrete villa  -

The line of sight was occluded by at least two walls
The receiver was adjacent to and transmitting serial data to a laptop. 
The line of sight included an LCD TV and a kitchen appliance.

The reinforced walls, LCD TV and Kitchen Appliance have all been observed to cause a large degree of interference to RC equipment and signals. 

Ideally the tests should be repeated with a higher value sensitivity however the test conditions are extreme and do not provide any qualification of the algorithms real world usefulness.

At present the algorithm has very little performance impact and clearly removes some noise, however before the algorithm can be qualified into or out of the RC Arduino projects it will need to be tested in the two most common RC Applications -

1) Racing - This is a tough environment with multiple transmitters sharing a fairly narrow physical and electro magnetic space. 
2) Street Driving - This has its own challenges in the form of distorted signals reflecting from the build up environment.

In use to date, the confidence algorithm has no detrimental effect so it stays 'in' with one small change - 'Sensitivity' actually has the opposite effect and should really be renamed 'Damping' to reflect it effect on the signal variation.

Next up - Bad Pulses And What To Do With Them

How To Read an RC Receiver With A Microcontroller - Part 1

Its a very common question, 'How do I read an RC Receiver with my micro controller' and the answer is often very simple however the simple answer is close to useless in a real world application.

The approach outlined in this series of posts has been tested in an RC Race car running at 40+ Kmh at a range of 100 meters.

The approach is reliable, resilient, easy to understand and easy to modify. It has been tested using using 27Mhz AM radio equipment and entry level electronics. Use of better quality electronics and radio equipment will provide improvements in range and signal quality however as the development process has demonstrated, even low end equipment can be interfaced with Arduino for control of an RC Race car.

Update 05/11/12 Read multiple RC channels with a smoother, faster library -
http://rcarduino.blogspot.com/2012/11/how-to-read-rc-channels-rcarduinofastlib.html
For the background to this and the original sketch before optimisation see - 
http://rcarduino.blogspot.com/2012/04/how-to-read-multiple-rc-channels-draft.html


Update 04/11/12 - For those of you looking to read a PPM Stream instead of individual channels, I will have a small fast library up this week - will post an update with the link here -
http://rcarduino.blogspot.ae/2012/11/how-to-read-rc-receiver-ppm-stream.html


Background Information

What are we looking for when we read from an RC Receiver ? Its not what I originally expected, my guess was that it was an analogue signal that would be amplified by the speed controller or servo controller to drive the motors. Its not analogue at all, its actually mostly empty space.

Each channel decoded by your receiver is sent to your ESCs and Servos as a train of pulses, these pulses are sent about 50 times a second but the suprising part is, each pulse only lasts between one and two milliseconds (1/1000 to 2/1000 of a second). Before the next pulse arrives, there is a gap of 10 times the length of the even longest pulse.

In an Electric RC Car a pulse width of 1000 is full reverse or brake, a pulse width of 2000 is full throttle and a pulse of 1500 is neutral. Note that these may be reversed, but the nature and range of the signal does not change.

This pulse train as it comes from the receiver could not be used to drive anything, not even a toy motor. The ESC or Servo control circuitry takes the pulse train as an input and generates a very different output, not just in power, but also in profile and even polarity in the case of reversing a motor.


The Simple Approach and Why Its Wrong

A common suggestion is to connect the receiver to the microcontroler such that there is a common ground (GND) between the two devices and then attach the white or orange signal wire from the receiver to one of the digital input microcontroller pins.

From here there are a variety of approaches to reading the values from the pins -

PulseIn (a blocking polling approach)

PulseIn is a function available with the Arduino that implements an approach know as 'poling'. It essentially sits around waiting for something to happen, until something happens the rest of your code is blocked. This is okay for a simple lab exercise to read and print values from a receiver but it is a hopeless approach for a real world application. Fortunately there are better approaches that do not require a major learning curve.

Timers

There is an example in the Arduino Playground which uses timers ReadReceiver. It may offer greater resolution than the method I am using, but it is also considerably more complicated and as I will show in a follow up post, the source receiver signal degrades rapidly as you move outside the lab rendering the increased accuracy less valuable.

Interrupts

The Timer example and my own approach both use Interrupts. Interrupts allow you to declare your interest in an event and then have the micro controller 'interrupt' your code whenever the event occurs.

Lets take a closer look at the channel signal and determine which bits we should be interested in -



If all we are interested in is the pulse duration, why not use pulseIn ? after all there is nothing else of interest in the signal.

The Arduino UNO is able to perform 16 million operations in one second. In the 2 milli second duration of a full throttle pulse, the Arduino could have performed 32,000 operations ! Thats a lot of wasted power. But it gets worse, what if you call pulseIn immediately after a pulse, you will have to wait a whole 20 milliseconds for the next pulse to arrive and complete. Thats a full 320,000 operations useful operations your code could have completed.

On average you can expect to call pulseIn in the center between two pulses, this means that over an extended period, half or your available processing power is wasted just waiting for the next pulse to arrive and complete. If you add more inputs, the approach becomes quickly unsustainable as you can only give your attention to a single input at a time.

Don't Use Pulse In !

Here are some updates showing the code in action - 

Active Yaw Control Of An RC Race Car
http://rcarduino.blogspot.com/2012/07/rcarduino-yaw-control-part-2.html 

Mapping RC Car Controls To A  Tank Tracked Robot
http://rcarduino.blogspot.com/2012/05/interfacing-rc-channels-to-l293d-motor.html 


Using an interrupt to efficiently detect new pulses and output to serial

For reading multiple RC Channels see - 

http://rcarduino.blogspot.co.uk/2012/04/how-to-read-multiple-rc-channels-draft.html


// First Example in a series of posts illustrating reading an RC Receiver with
// micro controller interrupts.
//
// Subsequent posts will provide enhancements required for real world operation
// in high speed applications with multiple inputs.
//
// http://rcarduino.blogspot.com/
//
// Posts in the series will be titled - How To Read an RC Receiver With A Microcontroller

// See also http://rcarduino.blogspot.co.uk/2012/04/how-to-read-multiple-rc-channels-draft.html 

#define THROTTLE_SIGNAL_IN 0 // INTERRUPT 0 = DIGITAL PIN 2 - use the interrupt number in attachInterrupt
#define THROTTLE_SIGNAL_IN_PIN 2 // INTERRUPT 0 = DIGITAL PIN 2 - use the PIN number in digitalRead

#define NEUTRAL_THROTTLE 1500 // this is the duration in microseconds of neutral throttle on an electric RC Car

volatile int nThrottleIn = NEUTRAL_THROTTLE; // volatile, we set this in the Interrupt and read it in loop so it must be declared volatile
volatile unsigned long ulStartPeriod = 0; // set in the interrupt
volatile boolean bNewThrottleSignal = false; // set in the interrupt and read in the loop
// we could use nThrottleIn = 0 in loop instead of a separate variable, but using bNewThrottleSignal to indicate we have a new signal
// is clearer for this first example

void setup()
{
  // tell the Arduino we want the function calcInput to be called whenever INT0 (digital pin 2) changes from HIGH to LOW or LOW to HIGH
  // catching these changes will allow us to calculate how long the input pulse is
  attachInterrupt(THROTTLE_SIGNAL_IN,calcInput,CHANGE);

  Serial.begin(9600);
}

void loop()
{
 // if a new throttle signal has been measured, lets print the value to serial, if not our code could carry on with some other processing
 if(bNewThrottleSignal)
 {

   Serial.println(nThrottleIn); 

   // set this back to false when we have finished
   // with nThrottleIn, while true, calcInput will not update
   // nThrottleIn
   bNewThrottleSignal = false;
 }

 // other processing ...
}

void calcInput()
{
  // if the pin is high, its the start of an interrupt
  if(digitalRead(THROTTLE_SIGNAL_IN_PIN) == HIGH)
  {
    // get the time using micros - when our code gets really busy this will become inaccurate, but for the current application its
    // easy to understand and works very well
    ulStartPeriod = micros();
  }
  else
  {
    // if the pin is low, its the falling edge of the pulse so now we can calculate the pulse duration by subtracting the
    // start time ulStartPeriod from the current time returned by micros()
    if(ulStartPeriod && (bNewThrottleSignal == false))
    {
      nThrottleIn = (int)(micros() - ulStartPeriod);
      ulStartPeriod = 0;

      // tell loop we have a new signal on the throttle channel
      // we will not update nThrottleIn until loop sets
      // bNewThrottleSignal back to false
      bNewThrottleSignal = true;
    }
  }
}



Next up - Part 2 including what does the signal really look like ? and more of the code to deal with it.

For reading multiple channels using an interrupt driven technique see -

http://rcarduino.blogspot.co.uk/2012/04/how-to-read-multiple-rc-channels-draft.html

Thursday, January 12, 2012

Traction Control Part 1.3 - Childs Play.

EDIT: This has turned out to be really cool. Its great being able to take a car along on a walk with the kids,  drive it flat out and then be able to hand the controls to my two year old or three year old. All I have to do is hold the brake for a few seconds and the car will discretely switch into 'Child Mode'. Read on for details ...

If your a dad its great when your kids show some interest in any of your hobbies, but when a three year old takes control of your race car it can be a short lived and expensive experience.

Can I Have A Go ?


This is an open source project, based on open source hardware, but here is a project pitch anyway -

Wouldn't it be great if you could set you car to a lower 'child' speed even if it was at the other end of the park ?

You can now put your car into 'Child Mode' or back to 'Dad Mode' anywhere within range of your transmitter.

Turn RC Day into family day and protect your investment from children, wives and learner drivers of all ages !


There is no need to modify any of your existing components, just plug your receiver throttle channel into the Arduino and likewise connect your ESC to the Arduino.

Features
  • Remotely toggle between restricted power 'Child Mode' and full power 'Dad Mode'
  • Uses standard RC Equipment
  • No Modification of existing equipment required
  • Plug and play self calibration for quick changes between different models
  • Independently adjustable forward and brake/reverse power settings
  • 'Child Mode' Restricts the power available while still retaining proportional control through the full range of your controller
  • No additional RC Equipment required, takes its power from the existing car battery.


How does it work ?

The radio control equipment that steers and powers your vehicle uses on/off pulses to control the power and direction of your car. In general a pulse that is 1500ms wide is the center or neutral point, full throttle is around 2000ms and full brake or reverse is around 1000ms. These pulses are sent a steady 40 or 50 times per second, only the pulse width varies, not the frequency.

In standard 'Dad' mode, the Arduino reads the incoming signal and outputs a signal of the same pulse width to the ESC, the Adruino is effectively operating in straight through mode (blue line in chart below).



In 'Child Mode', the Arduino reads the incoming signal but generates an output signal based a scaling factor anywhere from 20% to 100%. The scale factor is separately adjustable for forwards and reverse, allowing any combination for example 50% forward power with full 100%  brake/reverse power (red line in graph) or 20% power in both directions (green line in graph).


Operation

The software is designed to start up in 'Dad Mode', as the car is driven, the software will monitor the maximum and minimum pulse width received in order to determine the full throttle and full brake settings.

How do you keep your paint as fresh as this ? Try 'Child Mode'
When the system switches to child mode, it will deliver only a percentage of the power available. The percentage delivered is determined through two rotary adjusters one for forwards power and one for reverse/brake power.The power delivery is scaled so that full proportional control is retained, for example if the power is set to 50% the system will deliver 50% of the input signal at 100% input, 45% at 90% input, 25% at 50% input etc. This allows the user to build experience in the proportional control of a performance model. As the user becomes more proficient, so the available power can be increased through the built in rotary adjusters.

To switch between 'child' and 'dad' mode, simply hold the brake for about 5 seconds and you will see the green child mode light indicating that the car is now in restricted mode. To return to standard mode, hold the brake again and wait for the light to go out.

The Circuit

The circuit is extremely simple using only the following components and Arduino PINs

  • Two LEDs with current limiting resistors as status indicators
  • Two variable resistors connected to two Arduino analogue inputs as the forward and reserve power adjusters
  • A single Arduino interrupt to read the incoming servo signal
  • A single Arduino PWM Pin to generate the outgoing servo signal
  • Power is from the LIPO battery in the car
The PIN assignments can be read from the code comments, the assigments are created through #define statements and so can easily be changed to suite an alternative layout.


Installed and road tested in my Tamiya M03 Race Car


The Code

The code is again very simple, whereever possible I have used meaningful names for variables and functions, its not that I like typing, I really dislike reading code, more typing now means less reading in the future.

The three novel features are -

1) EEPROM Error Log - I have a small 10 Byte area reserved in the EEPROM to record errors. Its round robin so will overwrite itself rather than overflow. On startup the software will send the 10 Bytes to serial to allow post run diagnostics if required, the log is cleared as it is sent so each run starts with a clear log.

2) Confidence - During my bench testing I noticed that the input signal as measured by the Arduino wanders around by +- 4 or 8 ms. If I treat each of these as a new command to the ESC, I get a lot of jitter. To smooth this and reduce the number of calls to Servo.writeMicroseconds, I have a very simple algorithm which maintains a 'confidence' level that an incoming signal is meaningful - its not very complex and is only designed to filter out random wandering around the current value.

3) Be bad, but not very bad - In early versions of the project the software would enter an error mode and put the car in neutral after receiving a single bad pulse. I have now introduced a bad pulse tolerance which allows the system to soak up noise that can't be avoided for example from crossing underground cables etc.
 

Further Development

For my purposes this project is a simple test of using the Arduino to interface between a hobby quality radio controlled car receiver and electronic speed controller or servo.

The project proves that -

1) It is feasible to read, process and output the throttle signal in realtime using the Arduino platform
2) Electrical noise can be managed so that it is not an issue

The next step for me is to implement 'active traction control' based on the wheel speed monitoring previously described in Part 1.1, however there are some potentially interesting further developments to this for example 'passive traction control'.

Passive Traction Control Project Suggestion 1 - Mulitple Acceleration Profiles




The existing code and circuit forms the basis for a passive traction control system. One simple project idea is to provide the car with different acceleration modes or profiles to suite different surfaces. The Arduino would read the desired throttle level from the receiver but would control the rate at which the output signal seeks the level of the input signal - on a dirt setting this rate of change would be low, on a tarmac setting a higher rate of change would be possible - this could be fine tuned in car using the existing circuit potentiometers.

Passive Traction Control Project Suggestion 2 - Brake Pressure Profiling



When a car is traveling at high speed, the brakes can be applied powerfully, however as the car slows down the brake pressure should be reduced to avoid the brakes locking up. This is a particular problem for RWD radio controlled cars which are prone to locking the rear wheels and spinning out under braking. In this project, the Arduino would monitor the input signal for maximum brake, it will initially output a maximum brake signal, but will begin to fade this signal for the duration of the brake command. The rate of fade and the target value - around 30% brake force for my M-04 could be adjusted in car using potentiometers. 

These two passive projects will be less effective than an active solution which monitors wheel speed however they are developments of the existing project that provide an incremental challenge. I will skip these developments and continue with the active version but feel free to use my code to explore these approaches.

The Hardware
The project is currently running an on Arduino UNO, this is a USB programmable version of the Arduino that costs around 20 dollars. This is an easy to use development board, but now that the code is finalised it can be run on a PCB or strip board based Arduino that is smaller, lighter and best of all can be built from components that cost less than 10 dollars.

Child Mode/Traction Control Circuit - Version 1

Top left - decoupling capacitors
Bottom left - mode and operational indicator LEDs
Center - Forwards and Reverse Child Mode max power adjustment
Right of center - connections for wheel speed sensors for all four wheels in traction control mode
Bottom right - 3 Pin headers for ESC Input and Output.

Child Mode/Traction Control Circuit - Version 2

Top Left - Power to the Arduino comes from the 8.4V Lipo battery in the car, it passes through this circuit on its way and is decoupled by the .01 .1 1 and 47 uf capacitors in the top left of the picture.
Top Left - Next to the decouplind capacitors are two strips of three pin PCB Headers, these are used to connect the throttle channel of the RC Car receiver to Arduino interrupt 0 and an Arduino output pin to the car ESC signal pin.
Bottom Left - The two potentiometers are used to adjust the amount of power the Arduino will make available for forwards and reverse throttle in child mode.
Top Center - Indicator LEDs, red for error, green for child mode and blue for a glitch or unexpected pulse that is within operating tolerance, its really an information signal telling me that the signal environment is dirty but not so much that we need to treat it as an error condition.
On the right hand side are the connections for the four wheel speed sensors. These are not used in the child mode project but are used in the ongoing traction control project.


Tuesday, January 10, 2012

The Uncontrollable Sand Scorcher Explained

Someone pointed out to me that its clear the Sand Scorcher has a lot of power in it from this picture.

 A lot of power putting a lot of sand in the air !

It turns out they were right. The low powered 'silver can' motor I installed was actually a much more powerful 19 Turn motor. Combined with the lightweight 25C Lipo battery was a bit much for the 30 year old chassis design.

Interestingly I was running the battery/motor combination through a standard Tamiya TEU104-BK Electronic Speed controller which survived the two or three runs it took me to discover the motor mistake.

Does this mean you can run a 19 Turn motor off the TEU-104 ?

No, I was lucky, you might not be. I will not be running this car again until I get the time to change the motor to either a Tamiya Sport Tuned or a Hobbywing 13 Turn brushless.

In the meantime I hope to road test part of the m-chassis traction control system this evening. I am a little apprehensive about moving this from the bench to road testing. This will be the first time I have run the car with the Arduino taking an active part in the control of the car, its a bit like 'fly by wire', there is no direct connection from the receiver to the speed controller, all speed signals are being sent from the Arduino.

Traction control update coming soon ...

Friday, January 6, 2012

Arduino, ESC = Noise, Noise, Noise - Problem Solved

Noise, Noise, Noise - only it wasn't in the end.

My projects have been stuck for two weeks while I have read up on decoupling, shopped for components, scanned through my code, rebuilt my circuits, twisted all my wires together etc etc etc all in the hope of tracking down and eliminating a problem I have with noise when my Arduino is connected to the ESC (Electronic Speed Controller).

The problem only occurs when the Arduino is PWMing (Pulse Width Modulation) the ESC, I can PWM a servo in place of the ESC and all is fine, but as soon as I try to drive the ESC with PWM I start getting a garbage pulse every 6th pulse or so.

Now that my board is loaded up with decoupling capacitors, the problem is finally solved - with a resistor.

 330 Ohm Resistor Show a resistor of 560 Ohms is being used in the project at present. The resistor is connected between the PWM Pin and the signal pin of the ESC.

I had a nagging idea that I might be damaging the PWM Pin by pulling too much current from it into the ESC so I added a 560 Ohm current limiting resistor and my rogue pulse vanished, not what I was expecting to happen but a very welcome development.

Thanks to this gentleman for the idea - http://www.thebox.myzen.co.uk/Site/Welcome.html look for the 'school box', all good stuff which has helped.

I got the idea for the resistor from reading the section about LED current draw slowly damaging pins even if it looks as if its working. It looks as if the ESC was was drawing too much current.