Calculating absolute position from 16bit int

I’m attempting to setup a routine to calculate positions from a degree. The first part is easy, converting degree to 500-5500 for the extreme points.

uint16_t position = ((uint8_t)deg * 27.7) + 500;

where 27.7 is (5500 - 500) / 180

Now it gets to the hard part since the data fields require 7bit integers. I have figured out 2 method to convert to 2 8bit ints but cannot figure out a way to convert to 2 7bit ints without changing the sum.

As i’m getting somewhat close I should post the conversion I’m probably going with.
Converting a 16bit int to two 8bit

uint8_t lsb = (uint8_t)position;
uint8_t msb = position >> 8;

OK, I’m pretty much guessing and testing from here

uint8_t slsb = lsb >> 1; // this should be a realistic 7bit number, but wrong
uint8_t smsb = msb << 1; // shift that bit onto the next byte?

This works reasonably well but has an inconsistant margin of error of 7bits or 1-128. Thats a 4.6deg margin of error, derp.
So I think I know what needs to be done, but just don’t know how its done. My guess is that the actual bit shifted off of lsb needs to be shifted onto msb, so in the case that bit 0 is 0 msb isn’t getting a 1 shifted on for no reason.


Are you trying to convert this to the 7-bit format for some Pololu product? Which one?


Yes, for the SSC03A.

The solution with reasonably good results I settled on for now is like this.

uint16_t pos = (deg * 27.7) + 500;
uint8_t lsb, msb;

lsb = pos >> 7;
msb = pos >> 14<<7;

servoContol(servo, 0x04, lsb, msb);

This is probably horrible code.


Okay, I think you should back up a bit to make sure you are doing things right. With the Micro Serial Servo Controller, 500-5500 is probably not going to correspond to exactly 0-180 degrees. As the manual says, this corresponds to the entire range of the servo controller, which is more than 180 and greater than the range of most servos. Since pushing your servo beyond its range can easily damage it, you should do some tests to find the actual range.

Next, if you want to compute something like deg * (5500 - 500) / 180, you should just write it exactly like that instead of simplifying it to 27.7. Using floating point numbers is unnecessary. But please make sure that deg is a 4-byte integer so that it does not overflow when you multiply it by 5000.

Now, your formula for “lsb” correctly calculates the upper seven bits. I recommend just calling that something else, like “byte1” or “upper_seven_bits”, since LSB stands for “least significant bit”. Your formula for “msb” will always return zero, and I do not understand what you thought it would do. You are probably misleading yourself somehow by putting some of the parts closer together, without spaces. If you want certain parts of your expression to be evaluated first, you should just use parentheses. Anyway, instead of that, you should be able to get the lower seven bits with

lower_seven_bits = pos & 0x7f

You can read more information about C operators at a lot of websites - try Googling for “C operators” or “C bitwise operators” for some tutorials.