Let's Make Robots!

FORMULA TO CONVERT ADC VALUES (0-255) TO SERVO POSITIONS (75-225)

Guides you when doing the math inside the code.

The need to convert the result of the ADC pins proportionally to servo positions arose recently in my Pic-Aim project, which in turn was inspired by this comment. In it, user chench shared the following formula to convert one into the other:

Readadc C.1,b1 ; read value into b1

b2 = (b1 / 2) + 75; convert from 0-255 to 75 - 203

Which works beautifully well.

However if you are looking for more accuracy -specially when refining and debugging code-, there is some room to improve on the given formula. I gave it to my younger sister who is a lot better at math than I am, and in 8 seconds flat she came up with the following:

y=ax+b

...where:

  • Y= is the servo position
  • A (constant)=(225-75)/255 or 0.588235
  • X= the ADC value
  • B (also constant)= 75

A little implementation: Let´s say you want to calculate the servo position that would result from an ADC value of 111. All you have to do is replace the explained components with their values:

y=(((225-75)/255)*111)+75

y=(0.588235*111)+75

y=65.294085+75

y=140

As you can see, the difference with Chench´s formula is minimal, but it is there.

Hope this helps any of you who finds themselves in the same situation I was in last week!

Cheers,

Andrés


NOTE (July 28th, 2011): This formula will only work correctly with exponential potentiometers. If you are using linear ones, the servo response will not be full range. 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The reason for chench's b1/2 and your b1*.588235 are different is that chench might know the PICAXE has no floating point ability. To get more precise results you would need to do what voodoobot did and use word variables and multiply by a fraction.

To work with voodoobot's concern of varying servo ranges, just use a pair of min/max variables and don't send anything outside of the range or use the MIN/MAX keywords that are available in PICAXE BASIC. My preference would be variables as they could be quickly found and changed, if need be.

Hey birdmun,

Could you please ellaborate on floating points? I don´t know what they are.

Thanks,

Andrés 

Integers are whole numbers or numbers without decimal places. Floating point numbers are numbers with decimal points and numbers that follow to the right. I guess it is possible on your side of the pond that rather than decimal points they would be commas. For example, 12 is an integer and so is 24/2, they infact are the same number. OTH 1/2 and 0.5(or 0,5) have decimal places and therefore are floating point numbers. Many lower end microcontrollers do not understand decimal points and require a user to do integer math. Multiplying 3.14 by 100 and using that as PI then remembering that you will need to divide your final answer by 100 to get your answer truncated to a whole number(integer).

I hope my response helped your understanding. Maybe I should have started this with "I am not a teacher" :D

Ok, birdmun. I get it. Thanks. I just didn´t know that decimals were called "floating points". I am fully aware of what kind of numbers the Picaxe "likes" and what kind of math they´ll accept. I guess I should have been more specific as to the theoretical nature of the tip.  I thought that not giving any code samples was proof enough. I will rewrite it.

BTW, very cool that you know that not all of use use a decimal POINT, and that some of us, use a COMMA!!

Thanks for enlightening me, teach! ;)

Cheers,

Andrés

This explains the technique I used perfectly. This was also explained somewhere in the picaxe manual 1 I believe(which is why I did it this way).

The special sauce formula as I came up with and explained in this post(source included). This was specific to the picaxe and used on a 08M for my testing purposes or several servos. I set the limit of 80 and 220 due to the fact that not all servos like 75-225 so cutting it down slightly worked for test purposes. 

w1=w0*10/17+75

One issue you may face is that many servos do not work perfectly linearly across their range of movement. 

My approach was merely theoretical, Ignoblegnome. This is, by no means, a law. In theory, everything is nice, tidy and simmetrical. Reality is a nasty can of worms.

However this is intended to be merely an approach, a stepping stone, but at least a nice and accurate one... in theory!

No critism intended. This is a good tip. 

Just pointing out that results may vary based on your servo, and a linear change from the analog input may not be a perfect linear change in your servo position. The error may not be significant, and for many purposes this tip should work just fine!

I welcome criticism, Ignoblegnome, :) and you raise a valid point.

Regarding your other comment on my project Deacon, I have already pledged allegiance as promised.

Cheers,

Andrés