Is this normal behavior?

I’m having some trouble with my usb 16 servo controller. When I send a command, the yellow LED goes out, but nothing else happens. I don’t have a servo hooked in, but I’m trying to get it to blink out the current number of servos.

I’m running on Mac OSX.

Here’s my code:

#include <iostream>

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <poll.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <cmath>
#include <math.h>
#include <time.h>


int fdIMU_;


/******************************************************************************
 *
 *****************************************************************************/
bool connect() {

    struct termios term_info;
    fdIMU_ = open("/dev/cu.Pololu", O_RDWR | O_NOCTTY);
    if(fdIMU_ < 0) {
		perror(NULL);
		return false;
    }   else fcntl(fdIMU_, F_SETFL, 0);

	
	
    if (tcgetattr(fdIMU_,&term_info) < 0){
		return false;
    }
	
    cfmakeraw(&term_info);
	
    if(tcsetattr(fdIMU_,TCSAFLUSH,&term_info) < 0){
		return false;
    }
	
    if(cfsetospeed(&term_info, B9600) &&
       cfsetispeed(&term_info, B9600)) {
		return false;
    }

	term_info.c_cflag |= (CLOCAL | CREAD); /* enable */
	term_info.c_cflag &= ~PARENB;
	term_info.c_cflag &= ~CSTOPB;
	term_info.c_cflag &= ~CSIZE;
	term_info.c_cflag |= CS8;
	
    if(tcsetattr(fdIMU_,TCSANOW,&term_info) < 0){
		return false;
    }
	printf("Set attr\n");

    return true;
}


/******************************************************************************
 *
 *****************************************************************************/
bool disconnect() {
    close(fdIMU_);
	
    return true;
}

/******************************************************************************
 *
 *****************************************************************************/
bool moveServo() {
	std::cout << "Attempting to send...";
		
    //static const unsigned char cmd[] = {0x80,0x01,0x01,0x00,0x40};
	static const unsigned char cmd[] = {0x80,0x02,0x08};
	//static const uint8_t cmd[] = {0x80, 0x01, 0x02, 0x00, 0xFE};
    ssize_t bytesWrote = write(fdIMU_, cmd, 3);

	if(bytesWrote < 0) {
		perror(NULL);
		printf("Bytes wrote: %d\n", bytesWrote);
		printf("Errno: %d\n", errno);
		return false;
	}
       return true;
}


int main (int argc, char * const argv[]) {
    printf("Time to work\n");
	connect();
	moveServo();
	printf("Done.\n");
    return 0;
}

{0x80,0x02,0x08} is the right string of bytes to send to check the servo number settings, and the yellow LED should turn out on proper serial byte reception. You should be seeing the green LED blinking out the servo numbers variable plus one. Do you have the mode setting jumper removed for Pololu mode communication?

-Adam

I do have the jumper removed. I see the activity light blink (looks like maybe once, too quick to tell) and then the yellow LED goes out. Nothing else happens.

If I resend the command, the activity light blinks again, but still nothing on the number of servos.

The green LED flickering ever so slightly is a good sign, it does this as serial characters whiz by, and the yellow LED going out is normal for the servo controller having properly detected the baud rate. It’s definitely seeing bytes, it’s just not interpreting them as the show-servonumbers command for some reason. The servo-number-display blinking should be much slower and more apparent.

On Windows I would recommend watching what bytes your program is actually sending with a serial port monitor program, but I don’t know of any (free) ones for Mac. Can you try just sending those three byte values from a serial terminal program?

-Adam

I believe I got the board blinking out the proper value now. It blinks once, short delay, blinks again and that just keeps repeating.

I reset it and try to send a servo command and now the green LED lights up and stays lit, yellow goes out, but my servo doesn’t move. I’m using an o-scope to check the lines and they are all at 1520uS.

I’m sending it {128,1,2,4,0}. I believe that should be move servo 4 to the zero position.

Great! That sounds exactly how the green LED would display the default set of servo numbers, what was the issue?

The Green LED closer to the servo pins should be on solid any time the controller is generating a signal for at least one servo (as opposed to the green LED by the USB port, which flickers with serial activity). That looks like a proper Pololu mode command to set servo 4 to the bottom of the reduced 90 degree range. If every signal pin is showing 1520uS after sending just this one command something is odd, it should only start a signal on the commanded pin. What you’re describing sounds like the behavior of MiniSSC-II mode, which sets all servos to their neutral position after the first serial byte is received. Sorry to bring up the same question twice, but did you put the mode selection jumper back perhaps?

-Adam

Strangely enough, to fix it I stopped using hex values and just went with the decimal numbers.

Apparently the jumper was back on again (my bad). Works now!

I’ll make a new post in the Mac section with code for everyone that works once I get it cleaned up.

Thanks!

OK, now I have a new problem.

If I send a command, it works fine, but I can’t do anything else after it. I can see the activity light still blinking, but nothing is getting sent. I found that the real problem was that I needed a sleep after I send the bytes out (no idea why).

Am I missing something glaring?

#include <iostream>

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <poll.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <cmath>
#include <math.h>
#include <time.h>


int fdIMU_;

//Globals
#define RUD_TOP 40
#define RUD_MID 25
#define RUD_BOT 0
#define ELV_TOP 100
#define ELV_MID 75
#define ELV_BOT 50


/******************************************************************************
 * Open and setup a serial port for connecting to the serial servo controller
 *****************************************************************************/
bool connect() {

    struct termios term_info;
    fdIMU_ = open("/dev/cu.Pololu", O_RDWR | O_NOCTTY);
    if(fdIMU_ < 0) {
		perror(NULL);
		return false;
    }   else fcntl(fdIMU_, F_SETFL, 0);
	
    if (tcgetattr(fdIMU_,&term_info) < 0){
		return false;
    }
	
    cfmakeraw(&term_info);
	
    if(tcsetattr(fdIMU_,TCSAFLUSH,&term_info) < 0){
		return false;
    }
	
    if(cfsetospeed(&term_info, B9600) &&
       cfsetispeed(&term_info, B9600)) {
		return false;
    }

	term_info.c_cflag |= (CLOCAL | CREAD); /* enable */
	term_info.c_cflag &= ~PARENB;
	term_info.c_cflag &= ~CSTOPB;
	term_info.c_cflag &= ~CSIZE;
	term_info.c_cflag |= CS8;
	
    if(tcsetattr(fdIMU_,TCSANOW,&term_info) < 0){
		return false;
    }

    return true;
}


/******************************************************************************
 * Close connection to serial port servo controller
 *****************************************************************************/
bool disconnect() {
    close(fdIMU_);
	
    return true;
}



/******************************************************************************
 * Change the speed that the servos move between positions
 * 0 = Instantaneous change
 * 1-127 = 50uS/S - 6350uS/S
 *****************************************************************************/
bool setSpeed(int servo, int speed) {
	static const unsigned char cmd[] = {128,1,1,servo,speed};
	ssize_t bytesWrote = write(fdIMU_, cmd, 5);
	
	if(bytesWrote < 0) {
		perror(NULL);
		printf("Bytes wrote: %d\n", bytesWrote);
		printf("Errno: %d\n", errno);
		return false;
	}
	sleep(1); //This needs to be here!!!
	return true;		
}
			   


/******************************************************************************
 * Move the specified servo to the desired position
 * servo = depends on setup (default is 0-15)
 * position = 0-127
 *****************************************************************************/
bool moveServo(int servo, int position) {
	printf("[MoveServo] Servo: %d  Position: %d", servo, position);

	static const unsigned char cmd[] = {128,1,2,servo,position}; //50, 75, 100 for 15
	
	ssize_t bytesWrote = write(fdIMU_, cmd, 5);

	if(bytesWrote < 0) {
		perror(NULL);
		return false;
	}
	
	sleep(1);

	return true;
}


int main (int argc, char * const argv[]) {
    int rud_pos = RUD_BOT;
	int elv_pos = ELV_BOT;
	printf("Time to work\n");

	setSpeed(15,0);
	setSpeed(14,0);
	
	while(1) {
		if(rud_pos == RUD_BOT) rud_pos = RUD_MID;
		else if(rud_pos = RUD_MID) rud_pos = RUD_TOP;
		else if(rud_pos = RUD_TOP) rud_pos = RUD_BOT;

		if(rud_pos == ELV_BOT) rud_pos = ELV_MID;
		else if(rud_pos = ELV_MID) elv_pos = ELV_TOP;
		else if(rud_pos = ELV_TOP) elv_pos = ELV_BOT;
		
		connect();
		moveServo(14, rud_pos);
		disconnect();
		//sleep(1);
		connect();
		moveServo(15, elv_pos); //57, 90
		disconnect();
		//sleep(1);
	}	
	
	printf("Done.\n");
    return 0;
}

The servo controller can accept commands sent as fast as the baud-rate supports, but in my experience you run into a lot of problems, especially with virtual serial ports, if you’re opening and closing them all the time. I would suggest running your “connect()” function once before your while loop, and moving “disconnect()” after the loop. Of course, a condition that will actually break you out of the loop would be helpful at some point.

-Adam

Oh sorry, the connect/disconnect stuff was something I was trying. That didn’t work either.

I had it setup to just kick out the three positions, but that still didn’t seem to work. Am I missing a port flush or something?

I don’t think you should need to flush, but I’m not super-familiar with termios. Can you print the “bytesWrote” values to make sure the write command is at least claiming to have written enough bytes? Also, since you have access to an oscilloscope, you could check the TTL level serial pins on the servo controller and look at the bytes going by, just to see if the right number of them are actually transmitted.

-Adam

I’m not too familiar either.

What’s strange is that I can set the speed and then send a servo position without an issue, but I can’t send the position command again and again.

So I just found out about the echo back feature and here’s what I see…

Time to work

[MoveServo] Servo: 14 Position: 1
Bytes written: 5
Echo: 0x80 0x1 0x2 0xE 0x1

[MoveServo] Servo: 14 Position: 127
Bytes written: 5
Echo: 0xFF 0x0 0x0 0x80 0x1

[MoveServo] Servo: 14 Position: 1
Bytes written: 5
Echo: 0x2 0xE 0x1 0xFF 0x0

Done.

Can you post your current code with the echo statements? If they’re printing accurately, your character strings are getting messed up somehow.

Why are you declaring the character strings both “static” and “const”? It seems like that might be causing trouble the second time you call the function, sine the array is still stored in memory, but it is declared constant, and you’re trying to change it. I would suggest you try just declaring the arrays as plain unsigned chars. If the write function requires a const char array, you can always cast the array as you feed it into the function.

-Adam

Holy crap! I can’t believe I did that. Changed it from static const to just const and it works great now… OY!