Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Understanding commands?


#1

Please excuse my ignorance, but could someone explain how to work out the correct hex value that corresponds to servo movement in pololu mode?
Thankyou


Arduino + Pololu Micro Serial 8 Servo Controller
How to get started with USB16 controller?
Help with Servo Controller Pololu Mode and Arduino
Need two Servo Controllers for simultaneous motion?
Serial 8-servo controller and Linux
Using PIC18 MCU..SSC receives data..on 1.5ms pulse on line
PD0 / PD1 on LV168?
Programming Serial Servo Controller in Visual Basic .NET
Programming Serial Servo Controller in Visual Basic .NET
#2

I’ll try and make my question a little clearer. I’ve got a micro servo serial controller 8. Looking at the following command, (0x80 0x01 0x04 0x01 0x19 0x32) Please explain does the following hex numbers correspond 0x19 and 0x32 from the range of 500-5500.
How do I convert the angles I want the servo to position itself into appropriate hex numbers.
:? [/u]


#3

Sure, the Pololu mode protocol uses five or six serial bytes in each command, the start byte, the device ID, the command number, the servo number, and one or two data bytes. Lets break down the command you talked about:

Data Bytes: 0x19, 0x32
The absolute position command range is 500 to 5500, and one byte can represent a number from 0 to 255, so it takes two bytes to represent higher position numbers. Normally, you could just split a number up into a high and low byte, but the Pololu protocol doesn’t let you have the highest bit in a byte set to 1, unless it is a start byte. So, the second byte contains the lower 7 bits of the position number, and the first byte contains the remaining upper bits. What??? Lets work backwards in binary:

0x19=00011001
0x32=00110010

Taking the lower seven bits of these two numbers strung together we get:

00110010110010=0xCB2=3250

WOW! So how to you work forwards from a position number like 3250 to get 0x19 and 0x32? Let me pull out my standard C program:

void put(int servo, int angle){
	unsigned char buff[6];
	DWORD len;

	unsigned short int temp;
	unsigned char pos_hi,pos_low;
	
	temp=angle&0x1f80;
	pos_hi=temp>>7;
	pos_low=angle & 0x7f;

	buff[0]=0x80;//start byte
	buff[1]=0x01;//device id
	buff[2]=0x04;//command number
	buff[3]=servo;//servo number
	buff[4]=pos_hi;//data1
	buff[5]=pos_low;//data2
	WriteFile(comPort, &buff, 6, &len, 0);

	printf("Servo %d Set to %d\n", servo, angle);
}

The important part is:
[ul]temp=angle&0x1f80;
pos_hi=temp>>7;
pos_low=angle & 0x7f;[/ul]

The first line is a bitwise and operation between the input angle and the hex number 0x1f80, or binary 0001111110000000. This basically sets the temp variable to the angle number, after erasing the upper three and lower seven bits (5500, the maximum allowable position number doesn’t use the upper three bits).

The second line sets the pos_hi variable to the temp variable rotated 7 bits to the right. So the bits that got through the first and operation are now the lowest bits in the high byte.

The third line sets the pos_lo to the result of a bitwise and operation between the original angle number and the hex number 0x7f, which is 01111111 in binary. As I’m sure you’ve already guessed, this erases the eighth bit, and leaves pos_lo with the lower seven bits.

SO, if I were to feed the position 3250, which is binary 0000110010110010 through these operations, I would get:

temp=0000110010110010 & 0001111110000000 = 0000110010000000
pos_hi=0000110010000000 >> 7 = 00011001
pos_low=0000110010110010 & 01111111 = 00110010

so in the end, pos_hi=00011001=0x19, and pos_lo=00110010=0x32. IT WORKS!

As for how to scale the numbers from 500 to 5500 to the angles of a servo, that really depends on the particular model of servo, so you’re going to have to determine that experimentally, but it should be nice and linear!

Well, let me know if that all makes sense to you now, and good luck!

-Adam


#4

Much appreciated Adam. What I’m trying to do is create a vertical 3D laser scanner. It needs to scan a specific target multiple times very slowly. I have a moderate understanding in C, but haven’t programmed in years. I guess I have to brush up on my programming skills… :unamused:


#5

hey tetrion, I would recommend you program in C#, and use this project as a guide: http://www.codeproject.com/cs/media/lasergesture.asp

Its written in C# and will show you how to do image recognition to find a laser pointer.

If you need help moving the servos in C#: http://www.colinkarpfinger.com/pololu/


#6

I attached an excel file that is a big chart where you can get the data1 and data2 values for 8 bit positions. Find your position number in the chart (500 - 5500) and then go up to get the data1 number, and to the left to get the data2 number. This is a good way to do it if you just want to experiment with the serial transmitter utility. I have wonderend if it would be worth loading this as an array in a program and just query the array for the data values rather than calculate them, but maybe thats not a very efficient approach. Please somebody check my work.
David K
Pololu_8_Bit_Position_Hex_Array.xls (173 KB)


#7

Hello.

Thank you for the chart. However, it sounds like you’re more generally talking about values for the absolute position command, not just the 8-bit position command (where data1 is always is always just 0 or 1, and your position ranges from 0 to 255).

I think the calculation to obtain the data1 and data2 bytes is straightforward enough (see nexisnet’s post above) to where writing a function to calculate them would always beat out storing an array of the values.

You could make nexisnet’s code even simpler:

data1 = position >> 7;
data2 = position & 0x7F;

If you want to work it out on a calculator, you can do the following:

data1 = truncate(position / 128) (i.e. make it an integer by forgetting everything after the decimal point; 3.9 becomes 3)
data2 = position - data1 * 128

And to go the other way:

position = (data1 << 7) + data2; // i.e. position = data1 * 128 + data2

- Ben


#8

Thanks Ben,
So command-3 (8 bit position) and command-4 (absolute position) do not use the same data1 and data2 values??

I will admit I only tested with command-4 :]

does command-3 have less resolution than command-4?? (256*2 positions vs 5000 positions)?

The controller instructions just do not answer these questions at all. thank god for the forums.

Thank You,
david K


#9

I’m not sure what you mean by “the same data1 and data2 values”? The two commands are different, as described in the user’s guide, so the data values supplied are treated differently (though they are encoded the same way for both commands so the same conversion routine will work for both). Commands 2 and 3 are relative position commands that depend on the range and neutral settings (see the description of command 5 for more information about how these commands work). Command 4 is an absolute position command that lets you directly set the servo’s internal position variable. You have more theoretical resolution with command 4, but your actual step resolution will be limited to much less than 5000 by the servo itself.

In general, if you talk about sending a value of 5000 for an 8-bit position, something fishy is going on since an 8-bit number cannot exceed 255.

- Ben