C Code to move multiple servos

Hi I was trying to move multiple servos using C Language. I modified the code provided in the user manual. I pasted the compact protocol in the manual for moving multiple servos. But it doesn’t work. There are no errors of warnings but the code doesn’t work. I used a serial monitor and took a peek at the serial output and I got this
aa 0c 1f 0d 0a 07 70 2e 70 2e 70 2e 70 2e 70 2e 70 2e 70 2e 70 2e 70 2e 70 2e I don’t know why there is a ‘0d’ in there. Its not supposed to be there. Oh and I am getting the pot position from channel 0 but I cant move the servos. It would be great if you guys can help me with it.

[code]// Uses POSIX functions to send and receive data from a Maestro.
// NOTE: The Maestro’s serial mode must be set to “USB Dual Port”.
// NOTE: You must change the ‘const char * device’ line below.

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#ifdef _WIN32
#define O_NOCTTY 0
#else
#include <termios.h>
#endif
#include <math.h>

int mod (int a, int b)
{
if(b < 0) //you can check for b == 0 separately and do what you want
return mod(-a, -b);
int ret = a % b;
if(ret < 0)
ret+=b;
return ret;
}

// Gets the position of a Maestro channel.
// See the “Serial Servo Commands” section of the user’s guide.
int maestroGetPosition(int fd, unsigned char channel)
{
unsigned char command[] = {170 ,12 ,16 , channel};
if(write(fd, command, sizeof(command)) == -1)
{
perror(“error writing”);

return -1;

}

unsigned char response[2];
if(read(fd,response,2) != 2)
{
perror(“error reading”);
return -1;
}

return response[0] + 256*response[1];
}

// Sets the target of a Maestro channel.
// See the “Serial Servo Commands” section of the user’s guide.
// The units of ‘target’ are quarter-microseconds.
int maestroSetTarget(int fd, unsigned char channel, int target[])
{
unsigned char command[] = {170 ,12 ,31 ,10 ,channel , // 0x9f command, 0x0A numbers of channels to move, channel is the first channel number.
target[1] & 0x7f, target[1] >> 7 & 0x7F, // channe1 pos, channel 1 speed
target[2] & 0x7F, target[2] >> 7 & 0x7F, // …
target[3] & 0x7F, target[3] >> 7 & 0x7F,
target[4] & 0x7F, target[4] >> 7 & 0x7F,
target[5] & 0x7F, target[5] >> 7 & 0x7F,
target[6] & 0x7F, target[6] >> 7 & 0x7F,
target[7] & 0x7F, target[7] >> 7 & 0x7F,
target[8] & 0x7F, target[8] >> 7 & 0x7F,
target[9] & 0x7F, target[9] >> 7 & 0x7F,
target[10] & 0x7F, target[10] >> 7 & 0x7F};// …

if (write(fd, command, sizeof(command)) == -1)
{
perror(“error writing”);

return -1;

}
return 0;
}

int main()
{
// Open the Maestro’s virtual COM port.
const char * device = “\\.\USBSER000”; // Windows, “\\.\COM6” also works
//const char * device = “/dev/ttyACM0”; // Linux
//const char * device = “/dev/cu.usbmodem00034567”; // Mac OS X
int fd = open(device, O_RDWR | O_NOCTTY );
if (fd == -1){
perror(device);
return 1;
}

#ifndef _WIN32
struct termios options;
tcgetattr(fd, &options);
options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
options.c_oflag &= ~(ONLCR | OCRNL);
tcsetattr(fd, TCSANOW, &options);
#endif
int pot = 0;
int position = maestroGetPosition(fd, pot);
printf(“Current position is %d %d.\n”, position, pot);

int x[10];

x[1] = 6000;
x[2] = 6000;
x[3] = 6000;
x[4] = 6000;
x[5] = 6000;
x[6] = 6000;
x[7] = 6000;
x[8] = 6000;
x[9] = 6000;
x[10] = 6000;

maestroSetTarget(fd,7, x);

close(fd);
return 0;
}

[/code]

Hello.

I noticed in your code that you are trying to access element 10 of a 10-length array, which is invalid. An array index always starts at 0; the index range of an 10-length array is from 0 to 9. If you attempt to access an array outside its bounds, you would get undefined behavior. (This thread on stackoverflow might help you better understand why accessing arrays out of bounds gives no error and could result in undefined behavior.)

It sounds like some part of your system is performing conversions of newlines instead of treating the commands as binary data. What OS are you using?

- Amanda

Win 8 code blocks

Is it possible to rewrite this code to pololu and run it on the pololu itself?? I know how to make the loops and move the servos and and get the positions from my potentiometers in the first five channels. But I dont know how to get the positions and store and use them later and manipulate them later. Is it possible to do in the pololu control center??

We do not use Code Blocks, so we are not familiar with that IDE. However, we looked into your issue further and found that the MinGW runtime (not Windows) is performing conversions of newlines when calling the write method, unless you set this option _setmode(fd, _O_BINARY) in your code. We confirmed that that command stops the newline conversions and have updated the cross-platform example with that command in the Maestro’s user’s guide.

It is possible for you to write a script in the Maestro Control Center that performs the same functions as the cross-platform C example. You can use the PEEK and POKE script commands to store values on the stack and manipulate them later. For more information about the Maestro scripting commands and to see some examples, see “The Maestro Scripting Language” section of the user’s guide.

- Amanda