Hello,
I am using an embedded arm ts 7800 to control the maestro servo controller. I have been looking through the pololu user’s guide and am having a little trouble getting the sample code to work. I am running this off of the TTL on the board, I have gone in to the maestro control center and checked that it is in dual usb and crc is not checked. When ever I compile the code I have no problems, but when I run the code the controller gives me a solid red light with a yellow blinking light and my terminal window doesnt give me any output to running it. I am running the servo on channel 2. I have tried one code which will output:
open port: port /dev/ttts7 has been opened correctly.
fd = 3
:::: 4:
:::: 4:
:::: 4:
etc…
repeatedly.
The code below does this.
#include <stdio.h> /* Standard input/output definitions */
#include <stdlib.h>
#include <time.h>
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
void put(int servo, int angle); // Moves servo (0-5) to angle (500-5500)
void waitMS (int ms); // This allows for a set system instruction pause. Note: 1000ms = 1 sec.
void neutral(); // This sets up all the servos neutral positions before use.
typedef unsigned int DWORD;
int mainfd = 0; /* File descriptor for the port */
void waitMS (int ms) {
clock_t endwait;
endwait = clock() + ms * CLOCKS_PER_SEC/1000;
while (clock() < endwait);
}
/*
* 'open_port()' - Open the serial port.
* Returns the file descriptor on success or -1 on error.
*/
int open_port (char portName[]) {
int fd; /* File descriptor for the port */
fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) { /* Could not open the port */
fprintf(stderr, "\nopen port: Unable to open %s - %s\n\n", portName, strerror(errno));
exit(EXIT_FAILURE); // EXIT
}
else {
printf("\nopen port: port %s has been opened correctly.\n\n", portName);
printf("fd = %i\n\n", fd);
}
return (fd);
}
void config_port(int mainfd) {
struct termios options;
tcgetattr (mainfd, &options);
// Set the read and write speed to 19200 BAUD.
// All speeds can be prefixed with B as a settings.
cfsetispeed (&options, B9600);
cfsetospeed (&options, B9600);
// Now to set the other settings. Here we use the no parity example. Both will assumme 8-bit words.
// PARENB is enabled parity bit. This disables the parity bit.
options.c_cflag &= ~PARENB;
// CSTOPB means 2 stop bits, otherwise (in this case) only one stop bit.
options.c_cflag &= ~CSTOPB;
// CSIZE is a mask for all the data size bits, so anding with the negation clears out the current data$
options.c_cflag &= ~CSIZE;
// CS8 means 8-bits per work
options.c_cflag |= CS8;
}
void close_port(int mainfd, char portName[]) {
/* Close the serial port */
if (close(mainfd) == -1) {
fprintf(stderr, "\n\nclose port: Unable to close %s - %s\n\n", portName, strerror(errno));
exit(EXIT_FAILURE); // EXIT
}
else {
printf("\n\nclose port: The port %s has been closed correctly.\n\n", portName);
exit(EXIT_SUCCESS);
}
}
int main(int argc, char* argv[]){
if (argc != 2) {
printf("USAGE: %s PORT. i.e. %s /dev/ttts7.\n", argv[0], argv[0]);
exit(EXIT_FAILURE); // EXIT
}
mainfd = open_port(argv[1]);
config_port(mainfd);
waitMS(2000); // Wait one second
unsigned char serialBytes[4];
int channel = 0x2;
int target = 6000;
serialBytes[0] = 0x84; // Command byte: Set Target.
serialBytes[1] = channel; // First data byte holds channel number.
serialBytes[2] = target & 0x7F; // Second byte holds the lower 7 bits of target.
serialBytes[3] = (target>>7) & 0x7F; // Third data byte holds the bits 7-13 of target.
int a;
while(1){
a = write(mainfd,serialBytes,4);
printf(":::: %i: \n",a);
waitMS(100);
}
close_port(mainfd, argv[1]);
}
Another code that I have tried I believe is closer to the sample code that pololu has in the user guide, which as I have said compiles fine, but when I run it, it gives me the solid red light with the blinking yellow, and shows no output in my working window.
// 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>
#include <termios.h>
// 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[] = {0x90, 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, unsigned short target)
{
unsigned char command[] = {0x84, channel, target & 0x7F, target >> 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/ttts7"; // 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;
}
int position = maestroGetPosition(fd, 0);
printf("Current position is %d.\n", position);
int target = (position < 6000) ? 7000 : 5000;
printf("Setting target to %d (%d us).\n", target, target/4);
maestroSetTarget(fd, 0, target);
close(fd);
return 0;
}
I apologize if I am posting this in the wrong section or the format is wrong, this is my first time using these forums.
Thanks in advanced for any help.