poor_mans_expo

Hi,

I have a couple of RC cars and have 3 relatively cheap Tx/Rx combos. These combos suit my needs with the exception of the one for my on-road race car, the missing functionality is expo. On the high speed straights the steering is too sensitive and I would like to soften it.

I thought of doing an Arduino project reading out the steering channel PWM signal from the receiver and via an algorithm change it to create the expo functionality.

This is a photo of what I want to achieve, depending on the value of a potentiometer have a certain degree of expo (t (for "thickness" of expo)).
Vertical axis: PWM signal from uC to servo
Horizontal axis: PWM signal from receiver to uC

This is a photo of the electrical circuit I think I need. (I have left out the transponder)

This is the sketch so far, I have divided it into "chapters" (A, B, C & D) to help discussing it.

/*
Sketch: "poor_mans_expo"
This sketch is to be used in an electrical circuit on the steering channel
of a model RC car to add the expo functionality when this
functionality is not present in the Tx/Rx combo
The sketch is written for use in a ATtiny45 uC.
The two reasons for this project are learning and to save the need
for a more expensive high end Tx/Rx combo.
by Leo Groeneveld
*/

#include <Servo.h> 
Servo myservo;            // create servo object to control a servo 

int potPin = 2;           // select the input pin for the potentiometer (hardware pin 7 on ATtiny45)
int pin = 1;              // select the input pin for the PWM signal from the receiver ch. 1 (hardware pin 6 on ATtiny45)
int val = 0;              // variable to store the value coming from the sensor

unsigned long duration;

/*

Put example code here during programming, remove after use.

*/

void setup() {
  pinMode(pin, INPUT);
  myservo.attach(0);      // attaches the servo on pin 0 to the servo object (hardware pin 5 on ATtiny45)
}

void loop() {
/*
A) In this part of the sketch the pulse width of the receiver signal to the servo is read.
*/

  duration = pulseIn(pin, HIGH);   // read the PWM signal from the receiver ch. 1

/*
B) In this part of the sketch the adjustment of the potentiometer is read.
This adjustment is used to set the level of expo of the signal to the servo.
*/

  val = analogRead(potPin);        // read the value from the potentiometer

/*
C) In this part of the sketch the algorithm is located to calculate the PWM signal to the servo from
the PWM signal from the receiver and the adjustment of the potentiometer.
*/

// The result is a value (val) between 1 and 179 that is to be sent to the servo. (This the the TROUBLE AREA)

/*
D) In this part of the sketch the calculated value of the PWM signal is sent to the servo.
*/

  myservo.write(val);             // sets the servo position according to the scaled value 
  delay(5);                       // waits for the servo to get there (I'm not sure this line is needed due to the minimum delay of 18ms in PWM signal between pulses)
  
// Now start again.

}

Now the main question:
Because I'm not able to do the math needed to write the algorithm, can you please help me with that?

Regards,

Leo

Hi Leo,

This could be a job for multiMap() - Arduino Playground - MultiMap -

it helps to mimic non linear functions with a look up table

If you want this in a formula, it is indeed not trivial (I'm not gonna dive into it)

Hi Rob,

I'm going to study the look up table function.

What on earth is "expo" in this context?

exponential?

Yes, it means exponential.

MarkT:
What on earth is "expo" in this context?

Exponential, a non linear output from a linear input. Originally used by RC systems to compensate for the fact that rotary RC servos do not provide a linear mechanical output from a linear input signal but often used these days to dampen down the response to movements around the centre of RC transmitter stick movements. This "softens" the response of control inputs whilst leaving the range of control movement the same overall.

I studied the look up table code but it's all abracadabra to me.

Even if I would understand, in order to fill the array I would have to calculate the values (and lots of them) meaning I would be able to do the math. I would then be able to make a formula in the code. The need for a look up table would be absent then. And more then max. 15ms look up time isn't possible if I understand the text correctly making this function way too slow.

If you can draw the table and take only those points between which linear interpolation is ok and then you are done.

The easiest way to do this might be select 30 x 2 cells in Excel and just feed it with numbers.
Make an XY-graph of the 2 columns and if the graph matches your wishes you found the numbers
for the lookup tables of multimap.

A smart colleague of mine suggested the following formula:

Y = a * X^n + (1-a)*X, where a is the variable to set the amount of expo. (I think I will fix n at 3 or 4)

Some mapping and flipping of the sign (at 1,5ms pulse width) for a*X^n is needed in the code but I think this is the base for the solution.

to boldly code what no man has coded before

to boldly code what no man one has coded before

More up-to-date version. :wink:

Y = a * X^n + (1-a)*X, where a is the variable to set the amount of expo. (I think I will fix n at 3 or 4)

If you do this, remember that in C++/Arduino code, the ^ symbol does not mean exponentiation.

If you want to raise a number to the 3rd or 4th power, the simplest and most direct way to do it is multiplication, like this: (xxx) for cube or (xxx*x) for 4th power.