4WD managed electronically on an RC car

Hi,

I’m new to Arduino, even if I have a few basics of C language, and I would like to know if some of You would have advices to give me about my project:

I happily own a 4WD nitro RC car and I would like to apply some sort of traction control to it.
It has 2 differentials (front and rear), so it means that if one of the front/rear wheels is blocked then the second will turn full speed but the blocked one won’t have any torque anymore, and it can lead to a poor control over the car when it is stuck or while it is turning.
On race cars and high-end cars, manufacturers use some “limited” differentials: like normal differentials it will split the power between the wheels except that one wheel will never be blocked, because part of the power is always given to each wheel. It allows wheels to turn at different speeds while the car turns but doesn’t let one wheel get stuck while the other spins full speed.
I don’t know if I’m making myself very clear haha

I would like to implement such a system on my RC car, plus a “pimped up” ABS control that would only work when the wheels are straight, allowing me to control the car when I’m braking on a straight line but also letting me “drift” if i brake while turning.

Mechanically, there is nothing easyer. I would need to check each wheel’s speed and if one wheel is let’s say 30% faster than the opposite one then I’d use a servo to tighten the break on it, and it would slow down until it reaches <30% speed difference.
Also, for the ABS, if there is no tension on the steering servo and one of the wheels is not turning anymore, I would override the braking order by lowering it 5% each step until the wheel starts turning again. It would be deactivated if the speed of the wehicle is lower than a certain limit, to allow me to stop the car and not end in a theoretical infinite substraction.

Now it’s the programming part that is not clear for me.

I would have to read the remote’s commands (by plugging the receiver’s OUT pins to 2 analog IN pins on the Arduino controller), read the wheels speeds, and action 6 analog servos: one for throttle, one for steering, and four for the brakes.

I was thinking of a Hall Effect sensor on each wheel for reading the speed.

The hardware I thought would be useful is:

  • an Arduino Uno or 2009, both rev3 (aren’t they the same?)
  • a Tinkerkit shield
  • 4 micro servos for breaking (1kg/mt is far enhough for pinching each brake)
  • 2 normal servos for throttle and steering (actual ones already present on the model)
  • 4 Hall Effect sensors, plus “magnet wheels” with 4, 6 or 8 magnets on each (depending on the overall size of the brakes, etc.)

I wrote some piece of code, but I have no idea on how to have an efficient order of execution, as some of the orders have to be given in parallel, some overriding others!

[MESSAGE TOO LONG]

[END OF TE MESSAGE]

EDIT: THE CODE IS TOTALLY WRONG, JUST NOTICED IT

  int FLpin_in = 0; // Front left speed sensor //
  int FRpin_in = 1; // Front Right speed sensor //
  int RLpin_in = 2; // Rear Left speed sensor //
  int RRpin_in = 4; // Rear Right peed sensor //
  int throttlepin_out = 11; //throttle servo output //
  int steeringpin_out = 10; // steering servo output //
  int FLbrakepin = 9; // Front left brake servo //
  int FRbrakepin = 6; // Front right brake servo //
  int RLbrakepin = 5; // Rear Left brake servo //
  int RRbrakepin = 3; // Rear Right brake servo //
  int throttlepin_in = ;
  int steeringpin_in = ;
 

void setup()
{
pinMode(FLpin_in, INPUT);
pinMode(FRpin_in, INPUT);
pinMode(RLpin_in, INPUT);
pinMode(RRpin_in, INPUT);
pinMode(throttlepin_in, INPUT);
pinMode(steeringpin_in, INPUT);
pinMode(throttlepin_out, OUTPUT);
pinMode(steeringpin_out, OUTPUT);
pinMode(FLbrakepin, OUTPUT);
pinMode(FRbrakepin, OUTPUT);
pinMode(RLbrakepin, OUTPUT);
pinMode(RRbrakepin, OUTPUT);
int FLspeed = 0;
int FRspeed = 0;
int RLspeed = 0;
int RRspeed = 0;
}

void wheelspeed() //Front Left wheel speed
{
  int time = 0;
  int counter = 0;
  // i don't know how to set a timer here!
  while (time = 0.1)
  {
    digitalRead(FLpin_in) = FLpinstatus;
    if (FLpinstatus == 1)
    {
      counter++;
    }
  }
  int FLspeed = counter / time / 8; //if there are 8 magnets on the wheel, 8 triggers for one second means the wheel goes 1rpm
}

void brake() // this is the ABS system
{
  analogRead(throttlepin_in) = throttle_in; //check the throttle command
  if (throttle_in >= 1) //if the command is neutral, or accellerate
  {
    while (throttle_in >= 1)
    {
      analogWrite(throttlepin_out) = throttle_in //output is the same as input
    }
    analogWrite(throttlepin_out) = 0; //make sure that once i release the throttle, it reaches 0
  }
  else
  {
    while (throttle_in <= 1) // if the command is "brake" on the remote control, then activate the "ABS check" that follow
    {
      int brakepower = throttle_in * 5; // as the brake signal is the 0 to 1V output of the remote receiver and the servos are 5V, multiply the power received
      analogWrite(FLbrakepin) = brakepower; // by 5 times so at its maximum the brake servo receives 5V
      analogWrite(FRbrakepin) = brakepower;
      analogWrite(RLbrakepin) = brakepower;
      analogWrite(RRbrakepin) = brakepower;
      if (FLspeed == 0) // on this part: if the wheel blocks, release the pressure on the brake (keeping a constant braking command of 0.5 the brakepower)
      {
        analogWrite(FLbrakepin) = 0.5 * brakepower; 
      }
      else
      {
        if (FRspeed == 0) //the same, for each wheel
        {
          analogWrite(FRbrakepin) = 0.5 * brakepower;
        }
        else
        {
          if (RLspeed == 0)
          {
            analogWrite(RLbrakepin) = 0.5 * brakepower;
          }
          else
          {
            if (RRspeed == 0)
            { 
              analogWrite(RRbrakepin) = 0.5 * brakepower;
            }
          }
        }
      }
    }
  }
  analogWrite(FLbrakepin) = 0; //make sure the brakes are set to 0 when the remote is released
  analogWrite(FRbrakepin) = 0;
  analogWrite(RLbrakepin) = 0;
  analogWrite(RRbrakepin) = 0;
}
void tractioncontrol()
{
  // i dont know how to  call another function, here it would be the wheelspeed() function
  if (FLspeed => 1.1 * FRspeed)
  {
    while (FLspeed => 1.1*FRspeed)
    {
      analogWrite(FLbrakepin) = 0.5; // 0.5V would be a 10% braking on the brake power
    }
    analogWrite(FLbrakepin) = 0;
  }
  else
  {
    if (FRspeed => 1.1 * FLspeed)
    {
      while (FRspeed => 1.1*FLspeed)
      {
        analogWrite(FRbrakepin) = 0.5; // 0.5V would be a 10% braking on the brake power
      }
      analogWrite(FRbrakepin) = 0;
    }
    else
    {
      if (RLspeed => 1.1 * RRspeed)
      {
        while (RLspeed => 1.1 RRspeed)
        {
          analogWrite(RLbrakepin) = 0.5;
        }
        analogWrite(RLbrakepin) = 0;
      }
      else
      {
        if (RRspeed => RLspeed)
        {
          while (RRspeed => RLspeed)
          {
            analogWrite(RRbrakepin) = 0.5;
          }
          analogWrite(RRbrakepin) = 0;
        }
      }
    }
  }
}

Now I am totally lost, because I’m not sure wether my functions are declared the right way or if the code will be doing what I would like it to do… I’m kinda lost in all these variables haha

Here is what I wanted to do before I got totally messed up:

  • read the throttle and steering inputs. Steering is retransmitted to the output without modification
  • if throttle value is “positive” (relative or absolute positive? I haven’t tested this yet) then it is retransmitted “as is”
  • if throttle is negative, so if i’m breaking, then we go to the braking program

braking program:
-if the absolute valor of steering input is >0 (let’s admit a little error and say 1V, so i guess if steering is > 200) then the brakes are actionned without modification of the input signal (not implemented in the program yet)
-if the steering is 0 (or with an error steering < 200), then i retransmit the braking “power” value to the brake servos and read the wheel’s speeds. If one wheel blocks, its servo value is 95% of the asked value, and the breaking value stays the same until it is modyfied (lower or stronger) then the ABS starts calculating again.

differential control program:

  • it is deactivated while breaking and if throttle is neutral, it only works when throttle is >20%
  • the program reads each wheel’s speed and if it notices one is let’s say 10% faster it will activate its brake a little (10% of the max. braking power(has to be fast enhough to act under 0.5 seconds, i know i ask a lot haha) until the speed is maximum 10% faster than its opposite wheel

Some details:

  • on the actual remote system, the throttle servo is used for breaking too: it has a positive and a negative direction: when it turns in the positive direction it acts on the throttle, and in the negative direction it acts on the brake (yes, it actually has one single brake for 4 wheels :stuck_out_tongue: )

And now my questions:

  • do you see something that doesn’t sound right in my approach of the project? If so, do you have any advice?
  • How can I complete this program? Don’t worry I’m not asking You to give me a finished program, some clues are more than welcome :smiley:
  • If I made some mistakes, can You point them out explaining what is wrong? I want to understand my mistakes
  • Will be the program fast enhough to work in real time? If not, can I run several programs in parallel? Because if it’s longer than 0.5 to 1s I guess the differential controll will be useless
  • How to make an efficient function’s hierarchy in this program?

Using fiddle brakes as a crude form of traction control is feasible as long as you can cope with the amount of wear and heat going into the brakes. The amount of energy going in could be considerable in some situations. If you have electronic throttle control you may be able to mitigate that by backing off the power if both axles show excessive wheelslip.

You have a fundamental problem that you can't tell the difference between sliding with all wheels locked, and stationary.

You may be able to get something workable by guessing at the maximum deceleration that you could achieve without sliding on a typical surface and control the braking so that the wheels don't decelerate more than that. It's not ideal, but could be achieved without any extra sensors. It will still gradually lock up if you hold the brakes on hard for long enough, but it will be nice and gradual and easy to drive around.

You may be able to come up with a technique that works better, but all the ones I've thought of so far have their own drawbacks.

Hi,

I have good and bad news for you.

The bad news - most of your assumptions are wrong.

The good news - I have a blog with many posts you will find useful, many people have been able to get RC Projects working by following my posts.

Start here - http://rcarduino.blogspot.com/2012/01/how-to-read-rc-receiver-with.html

Duane B

rcarduino.blogspot.com

PeterH: In fact, I also thought about this and was wondering if an accellerometer would work to check the deceleration. But as You say, the best solution is to set up the "brake power" to an optimal value for avoiding excessive wheel blocking but keeping a good deceleration. (unless I misunderstood You?)

DuaneB: Which assumptions do You mean exactly? The article You linked made me discover something, actually I was thinking that the receiver delivered an analog signal! But this may be what You were referring to, talking about assumptions. I'm sure I'll find some more interesting things on Your blog, this article already changed my approach of the project.

I thank both of You, I was first hesitating on posting such an abstract project instead of a completed one but I actually learned a lot and had good advices. Let's hope that I got at least something right haha

And I came up with another idea, comparable (but not the same principle) to the assisted steering on full scale automobiles: limiting the steering after the car reached a certain speed to avoid getting it upside down if I get a bit too itchy with the steering control. But it would have the same problematic as PeterH said: how to know what is the real speed or the "sliding wheels" speed? Unless I also get a GPS sensor, but I'd first stard in a modest way and "pimp" the program after some testing.

Hi,

I have a project i am near to publishing which uses a gyro to provide steering stability ( yaw control ) it is also sensitive to user input and will intervene less the more the user is steering.

You can actually acheive this just by using a helicopter rate gyro, details of this approach are already on my blog if you search for yaw control. My current project goes a lot further than the original goals set out in the yaw control post.

I should be publishing it in the next week - as soon as i have some before and after videos of the system in action.

Duane B

I'll check that out, actually Your blog is full of useful information and I guess I'll be following Your projects :)

Also, I came up with one more idea: setting up an air/fuel ratio control. It would be a passive control, as generally on these simple 2 stroke engines: - when the ratio is poor, the engine is not well lubricated and will heat up faster - when the ratio is good well... it's good! - when the ratio is rich the lubrication is excessive and it somehow "controls" the engine temperature. I'd like to define - by testing it - the different positions of the ratio screw on the engine to define 3 settings: poor, good and rich. With a temperature sensor I'd check the temperature, have a poor ratio when the engine's cold to heat it up faster, then keep the good ratio for the "play time" and when the engine's too hot I'd reduce the throttle command and check if a richer ratio really cools it down (i have some doubts because at the same time the engine receives more fuel, and these 2 stroke engines are sensitive).

Hi, I have no experience of fuel powered RC Cars other than seeing that most people struggle to start them and once they are started many also struggle to keep them going, your fuel mix plan is definitley one to develop.

I dont know if your transmitter has telemetry, the one I am currently using has two temperature sensors which can be installed in the car and send data back for display on the transmitter -

http://rcarduino.blogspot.com/2012/03/reading-from-rc-reveiver-do-you-need.html

Duane B

rcarduino.blogspot.com

No, I don’t have such a transmitter but it actually seems to be an interesting idea to develop too, I may invest in such a transmitter later!
I’ll try to write a piece of code in the next days, taking as an example Your work. I’m also interested in Your speed sensor, I was thinking that an optical sensor would be harder to implement but the way You did it changed my mind.

Also, as I see Your code is quite “heavy” (I never wrote such a long code, so it seems big to me), do You have good execution times? Would such big code fit for a real-time correction (like for the differential control system I’d like to set up)? Reading the receiver commands, treating them, applying them to the servos, getting a feedback (wheel speeds on the 4 wheels), correcting the differential right/left ratio on both differentials? If I add that other servo for controlling the air/fuel ratio (by reading every x seconds/minutes the engine temperature and modify the servo angle if needed) would it make the code too long to execute?

As You know, driving RC cars is a quite “stressed” driving with fast command changes (direction, throttle, etc.), and if the code is too long to execute it may alter the reactivity of the car.

Damn, Your blog just gave me too many ideas XD

Hi, I don't think my code is long ? it has way more comments that I would normally use which might make it look longer but they are only there to help people understand it.

Here is a link to a sneak peak at the yaw control system -

It reads the two transmitter channels, transforms them based on a gyro reading and then generates two modified outputs. The circuit is very simple as you can see, its running an ATMega 8 which has only 8K program memory and 1K ram, so the program is not that big either. At the moment, the system applies intervention between 100 and 120 times per second, this is not a problem with the 18 million operations a second that the Arduino is capable of.

Duane B

rcarduino.blogspot.com

Thibman:
With a temperature sensor I’d check the temperature, have a poor ratio when the engine’s cold to heat it up faster, then keep the good ratio for the “play time” and when the engine’s too hot I’d reduce the throttle command and check if a richer ratio really cools it down (i have some doubts because at the same time the engine receives more fuel, and these 2 stroke engines are sensitive).

I think you’ll find that these engines need to run rich when they’re cold, and you can afford to lean them out as they warm up. Once the engine is running cleanly, then within a very narrow range of adjustments the engine will tend to run hotter when it is lean and cooler when it is rich. Running rich also reduces the power output. Only a very small change in fueling will cause a lean misfire or foul the plug through over fueling. Maybe you’ll be able to improve on the standard engines, but my experience is that once you have found the optimum setting you just leave it alone.

Ok, actually I'm running it on the "optimum" ratio (I say "optimum" because it has been set with practice, as most hobbyists do, without any data acquisition on torque and power), there would probably not be a real change with some sort of "ratio cartography" (and cartography is a reeeeeeally big word for this kind of settings). And I didn't know that the ratio had to be rich on startup, my idea was that with 2-strokes engines a poor ratio on startup would heat up faster, thanks for pointing that out :)

buuuuuuut i think i'll use the Arduino boards to make a clear data acquisition to find the best ratio, as anyways now i have to put my hands in them.

About what kind of nitro 2 stroke engines are we talking? 2,2 cc or 3,5 cc? What brand and type of car?

Paco

It’s a 3.5cc engine, on a Kyosho Mad Force.
But the Mad Force is changing quite fast… i lowered it a bit, had a quick 4W direction hack, re-balanced the car (as it tended to do wheelies quite often, which is normal for such a car but i’m not keen on this) and now i’m setting a “semi-crawler” chassis. It will look like a crawler but won’t do crawling actually (as nitro cars aren’t great for crawling), won’t have the same flexibility as crawlers but still a better one than the original, having “thin” tires (they’re still large but thinner than the full-sized Mad Force tyres), and so on.
I’m used to drive it like a buggy, so some kind of traction control would help as the differential is reeeeally sensitive and tend to stick the car when it turns. Also, I don’t want to block the differentials because I want to keep their advantages.
Adding this 4WD control also allows me to add some effective brakes. The original one, even the ventilated model, is totally uneffective. With such a weak servo a single 30mm brake can’t stop such heavy vehicle (it weights 3.5kg)
As the terrain is not even where I live, it makes it the perfect vehicle if it had a good handling out of the box. Now problems are getting solved little by little :slight_smile: Maybe someday I can really obtain the maximum handling it can give, I just need to think about it (also, find the problems first!)

This weekend I’ll have some time, I will try to progress in this project.

Is it possible to get a limited slip differential for that application? I imagine that 4wd with opens diffs would be problematic.

For "pure" crawling people usually block differentials. A lot of differential locking pins are available for a lot of models if you don't wanna make your own, but what i wanna do is in fact an electronically managed limited slip differential because I never found one for the model I have.

And as You say, an open diff would be problematic and make people hate crawling haha

I just ran into a video on youtube on a programmable ABS for rc cars, I guess that it can be done in the same way on Arduino! And it's less complicated than the system I was imagining: http://www.youtube.com/watch?v=z8Qun8MRuW0

Hi,
ABS is quite a common option, I have it on my Budget Futaba transmitters. A useful feature for crawlers is to have a ‘drag brake’, a lot of rock crawler ESCs offer this feature but again it would be easy with Arduino if yours doesn’t.

Duane B

rcarduino.blogspot.com

Thibman: For "pure" crawling people usually block differentials. A lot of differential locking pins are available for a lot of models if you don't wanna make your own, but what i wanna do is in fact an electronically managed limited slip differential because I never found one for the model I have.

Limited slip differentials are not the same as a locked differential.

Limited slip differentials are not the same as a locked differential

I know, maybe I explained it wrong, what I wanted to say is that blocking a differential is easy to do because a lot of parts are available and you can even make your own locking pin easily but limited slip differentials are rare options and it's not available for my model so i'd like to do my own.

Hi,

What is your model ? I have way too many, but the crawlers I have are Tamiya CR01, Tamiya CC01 and a Junfac joker which is a conversion chassis for the CR01.

These and a few of my other cars are here -

http://rcarduino.blogspot.com/p/cars.html

The crawlers are the last two on the page. I am hoping to race the minis for the first time in about a year later today.

Duane B

rcarduino.blogspot.com