Servo pwm map function

Sorry this might be a long post but I'm stumped as to the answer.

This code will not run if you dont have a PCA 9685 pwm servo driver unless of course you can understand whats going on or can bypass the driver bits.

If you cant guess from the code its to move gauges for a flight sumulator (flightgear) a sample bit of code it supplied in the doserial function.

Curently I have only one servo connected (servo 14) with a 1:2 ratio to rotate the needle, as it is the easiest to show movement without actually having to fly the sim.

If you run the supplied code you will see from the terminal screen that the captured data is as supplied yet the mapped data is minus 2 for all data inputs via the setservopos function.

The data passed from the doserial function, is as expected, as is the data from the print statements, yet the servo will not respond to the mapped results. The last data item 1500 data should put the RPM gauge to approx mid range but it goes to full scale,

Input the servo min or servo max figures and the servo will move to those positions. I am assuming the problem lies within the setservopos function as servo is not responding to the code as expected. If you change servo 14 data (the last data item in the string) to 250 the gauge will read 0, change to 635 the gauge will read 3500.

I actually calculated the map function and it calculates out as expected. I included the calcs as maths is like Shakespeare to me (gibberish).

servo min 250 servo max 635 fsmin 0 fsmax 3500

(x-inmin) * (outmax -outmin)/(inmax-inmin)+outmin
for the range it is

0-0 * (635-250)/3500-0) +250
0 * 385 /3500 +250
0 * 0.11 + 250
0 + 250
= 250 servo min.

3500-0 * (635-250) /(3500-0) +250
3500 * 385 /3500 +250
3500 * 0.11 +250
385 + 250
= 635 servo max.

So where have I gone wrong?

parsein_tc182.ino (11.8 KB)

#define SRV_ZERO 0
#define SRV_SPAN 1
#define FS_ZERO 2
#define FS_SPAN 3

.....

value = map(value, FS_ZERO, FS_SPAN, SRV_ZERO, SRV_SPAN );

How is mapping 2-3 to 0-1 going to produce a useful value for a setPWM() command?

Steve

I'm not sure but I think 0-3 refers to the array elements that holds the min and max values for the servos and for the data that comes from the flight sim.

I think you meant:

  value = map(value, servodata[servo][FS_ZERO],
                                           servodata[servo][FS_SPAN], 
                                           servodata[servo][SRV_ZERO],
                                           servodata[servo][ SRV_SPAN] );

And if your _SPAN values aren't maximum values you may have to add the _ZERO value

  value = map(value, servodata[servo][FS_ZERO],
                                           servodata[servo][FS_ZERO] + servodata[servo][FS_SPAN], 
                                           servodata[servo][SRV_ZERO],
                                           servodata[servo][SRV_ZERO] + servodata[servo][SRV_SPAN] );

If you're using the math in the post:

0-0 * (635-250)/3500-0) +250
0 * 385 /3500 +250
0 * 0.11 + 250
0 + 250
= 250 servo min.

I would use

(0-0)*(635-250)/(3500-0) + 250 which in this instance works out accidentally. The right Bracket before the last 250 has no matching left bracket.

but if the "-0" were -25 then the brackets would definitely make a difference since
(0-25)(635-250)/(3500-25) + 250 it would be 243.6043165

I should have gone on because

3500-0 * (635-250) /(3500-0) +250
3500 - 0* all this is 0 +250
which gives you 3250, not 635

Check your brackets.

3500 * 385 /3500 +250
3500 * 0.11 +250
385 + 250
= 635 servo max.

So where have I gone wrong?

3500-0 * (635-250) /(3500-0) +250
3500 - 0* all this is 0 +250
which gives you 3250, not 635

Check your brackets.

If you put parentheses around 3500-0* like so (3500-0)* now you're not ,multiplying by "-0 * (635-250) /(3500-0) +250" which turns out to be 0 + 250 = 250. The way you are doing it is subject to the rules of precedence for math to do the ( and ) and * and / in that order then the addition or subtraction unless the addition and subtraction is in parentheses . I'm not sure if you are doing the math in your code or not. But if you make sure you are putting all the parentheses in the right place.

The difference between

  1. 3500-0 * (635-250) /(3500-0) +250
    and

  2. (3500-0) * (635-250) /(3500-0) +250

is for 1) 3500 - 0*()/() +250
is 3500 + 0 +250 = 3750

is for 2) (3500-0)(635-250) /(3500-0)+250
is 3500
385/3500+ 250
is 385 + 250 = 635

Thanks for the answers chaps, I got the servos to respond as they should by inserting the servodata[servo] into the map function.

By varying the input data, the gauges move to the positions I expected them to now I just need to sort out the communication between the arduino and flightgear.

As for my maths well I did say it was like Shakespeare (gibberish) but it may have been my typing of the equation, which is variable to say the least.

If I get stuck I'll be back.

Bill