Sometimes we need to take a series of values from a device connected to an analog input, modify those values and output them in a different fashion. One common example of this is reading a potentiometer and using that to position a servo. However, the series of values from the potentiometer will range from 0 to 255, while the servo output throughneeds to range from 75 to 225. We need to transform the input data to meet output requirements. In this particular case the transformation is simple one. We need to change the slope and adjust the ‘y-intercept’ or, perform a translation. This is what is called an affine transformation.servopos

Generally speaking for an affine transform of this nature, given a variable X, which has range between X_{L}and X_{H}that we wish to transform to another variable, Y, with a range given by Y_{L}to Y_{H}we must us the following formula:

Y=(Y_{H}-Y_{L})/(X_{H}-X_{L})*(X-X_{L})+Y_{L}(1)

Now, let’s say we have a PICAXE-08M2 with the wiper of a potentiometer attached to C.1 and a servo attached to C.4. We intend to read the value of the potentiometer into variable b0. Transform the data as required and put the result into b1. We will then use b1 to position the servo.

In our case, X is the variable b0, read from the ADC using the commandand whose range is 0 to 255, and Y is the variable b1 whose range we shall call b1readadc C.1, b9_{L}to b1_{H}, so we can simplify (1) to our 'general case' of:

b1=((b1_{H}-b1_{L})/255)*b0+b1_{L}(2)

Now, apply this to our scenario where we wish to control a servo, the range we need is b1_{L}=75 and b1_{H}=225. Plugging in these values to (2) we get:

b1=((225-75)/255)*b0+75 (3)

Given the limitation of the integer math and the order of operations imposed by PICAXE basic, we must rearrange (3) to become:

b1=150*b0/255+75(4)

Which will provide the results we require to use a pot to control a servo.

Now for a little more theory. We can now formulate 2 general affine transformations that can be used in PICAXE basic. The first uses a fixed range that we calculate before hand and hard code into the program. This formula would be useful in a case like the one that started this thread. Given an spread of R=b0_{H}-b0_{L}in the range of b0, and a desired output range of b1_{L}to b1_{H}we have:

b1=[b1_{H}-b1_{L}]*b0/R+b1_{L}, (5)

Where the term [b1_{H}-b1_{L}] is pre-calculated as an integer and coded into the program like we have already shown in (4). In that case R=255.

The second uses a programmable range determined at run-time. This would be useful in cases where the transformation would need to be adapted to changing conditions or to various output devices. Given a spread of the range of b0 (R from above) in b4, and a desired output range in variables b2 and b3 where b2 < b3, we have:

b1=b3-b2*b0/b4+b2 (6)

Code Example 1 - As in our text, to control a servo with a full-range potentiometer and using equation (5), where:

b1_{L}= 75

b1_{H}= 225

R=255

Code example 2 – Using the more general form, again control a servo that needs only a limited motion to vary a control valve based on a potentiometer that tells us a float level in a liquid tank. The potentiometer readings vary between 0 and 150 and the servo must be positioned between 100 and 180. Then using equation (6) we have:Code:servo C.4,150 do readadc C.1,b0 b1=150*b0/255+75 servopos C.4,b1 loop

Code:let b3 = 180 let b2 = 100 let b4 = 150 servo C.4,100 do readadc C.1,b0 b1=b3-b2*b0/b4+b2 servopos C.4,b1 loop

## Bookmarks