I have a single servo that I am using to move a foamcore arrow like the dial of a meter, to point to various points around it. The servo is connected to a Micro Serial Servo Controller (the manual for it is here: https://www.pololu.com/file/0J37/ssc03a_guide.pdf).
In order to avoid power problems, the servo controller is powered with a 9V 700mA power brick, the servo power is provided by a 5.5V 500mA power brick with a 1000uF capacitor across it, and the Vcc=Vss jumper is removed. That way, if the servo consumes a lot of power, it will not cause the Micro SSC to reset.
The serial connection is from the RS-232 input on the MicroSSC to a straight-through DB9 cable to the serial port on the back of my computer. I had been using a USB-Serial converter, but removed it to see if it was the source of the problem.
My code is at the end of this message. If I set the #define statement so that it is not in MiniSSC II mode, remove the mode jumper so that the board is in Pololu mode, and apply power to the board, the yellow LED comes on and the servo moves. Each time I plug the servo controller in, if the servo is clockwise of a specific position, the servo moves to the specific position. If the servo is counterclockwise of that position, it moves to that position when the program starts.
When I start the program, the yellow LED goes out, and the green LED flickers three times, each 3 seconds apart, as I would expect. However, the servo does not move. When the program ends, all the LEDs are off and the servo is receiving a position signal (it resists turning).
If I re-run the program, the green LED blinks again, as above, when the serial data is sent.
If I add the MiniSSC II mode jumper, the servo does not move when power is applied to the board. The yellow LED comes on. When I run the program, the yellow LED goes out and the green one blinks three times, at three second intervals as before. However, the servo does not move. It also does not resist being turned by hand, so it isn’t getting any positioning signal.
I have tried:
-
Using just the serial cable, using just the USB-serial converter, and using both. The symptoms remain the same.
-
Switching which Micro SSC I use (I have two).
-
Switching which servos I use
-
Switching which port the servos are connected to
-
Changing to the termio configuration from this project: pololu.com/docs/0J4?view_all=1#4
-
Switching between Pololu mode and MiniSSC II mode.
-
Reconfiguring the servo numbers as per page 8 of the instruction manual. The yellow and red LEDs do not light, as the manual says they should, and the green LED blinks once, rather than twice.
-
Using a benchtop supply for the servo.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define MINISSC
#ifdef MINISSC
#define BAUDRATE B9600
#else
#define BAUDRATE B38400
#endif
#define DEVICE "/dev/ttyS0"
int main(char** argv, int argc) {
int fd, c, res;
struct termios oldtio, newtio;
unsigned char cmd[16];
fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY); // avoid controll chars
if (fd < 0) {
perror(DEVICE);
exit(-1);
}
tcgetattr(fd, &oldtio); // save current port settings
bzero(&newtio, sizeof(newtio)); // clear struct for new port settings */
// these settings come from the pololu site
newtio.c_iflag = 0;
newtio.c_lflag = 0;
newtio.c_oflag = 0;
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
// flush and apply settings
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
#ifdef MINISSC
cmd[0] = 0xFF; // MiniSSC sync
cmd[1] = 0x00; // 0th servo
cmd[2] = 0x80; // middle position
res = write(fd, cmd, 3);
if (res != 3)
printf("Error writing to %s\n", DEVICE);
sleep(3);
cmd[0] = 0xFF; // MiniSSC sync
cmd[1] = 0x00; // 0th servo
cmd[2] = 0x00; // Left position
res = write(fd, cmd, 3);
if (res != 3)
printf("Error writing to %s\n", DEVICE);
sleep(3);
cmd[0] = 0xFF; // MiniSSC sync
cmd[1] = 0x00; // 0th servo
cmd[2] = 0xFF; // Right position
res = write(fd, cmd, 3);
if (res != 3)
printf("Error writing to %s\n", DEVICE);
sleep(3);
#else
cmd[0] = 0x80; // synchronization value (always 0x80 for pololu)
cmd[1] = 0x01; // device type always 0x01
cmd[2] = 0x04; // set position
cmd[3] = 0x00; // first servo
cmd[4] = 0x02; // First position, 600
cmd[5] = 0x58; //
cmd[6] = 0x00;
res = write(fd, cmd, 6);
if (res != 6)
printf("Error writing to %s\n", DEVICE);
sleep(3);
cmd[0] = 0x80; // synchronization value (always 0x80 for pololu)
cmd[1] = 0x01; // device type always 0x01
cmd[2] = 0x04; // set position
cmd[3] = 0x00; // first servo
cmd[4] = 0x0b; // Middle position, 3000
cmd[5] = 0xb8;
cmd[6] = 0x00;
res = write(fd, cmd, 6);
if (res != 6)
printf("Error writing to %s\n", DEVICE);
sleep(3);
cmd[0] = 0x80; // synchronization value (always 0x80 for pololu)
cmd[1] = 0x01; // device type always 0x01
cmd[2] = 0x04; // set position
cmd[3] = 0x00; // first servo
cmd[4] = 0x13; // End position, 5000
cmd[5] = 0x88;
cmd[6] = 0x00;
res = write(fd, cmd, 6);
if (res != 6)
printf("Error writing to %s\n", DEVICE);
sleep(3);
#endif
/* restore the old port settings */
tcsetattr(fd, TCSANOW, &oldtio);
}
That code is based on code from https://forum.pololu.com/t/micro-serial-servo-controller-on-linux-problem/3103/1, where the problem was the power supply. I’ve tried adding the lines from https://forum.pololu.com/t/lower-7bits-0x0a/2922/1, but the behavior persists.