Urgent! Help! Serial 8-servo control doesn't work!

Dear Friends

The serial 8-servo control doesn’t work!
It is urgent for my project.
Could you help me! Thank you!

I am testing the micro serial 8 channel servo controller. When I use the “Pololu Serial Transmitter” to command the servo controller, the servos work well.

But when I connected the servo controller to our embedded system working on QNX and tested the servo controller using our own code, this servo controller didn’t work and servos cannot move. All the lights on the servo controller were turned off.

I have double checked my code already, which is attached as below. My code can open the serial port successfully and the baud rate is set to 9600. I have connected two servos at 2 and 5 servo outputs, and set their position to 110 and 120 respectively. The Mini SSC II Mode is used in this code.

#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

#define SVO_BAUDRATE 9600

int nsSVO;

int main(int argc, char *argv[]) {
		
	
	struct termios termSVO; 
	char szSVOCommand[32]={0}; 
	int ret;
	
	int i;
	
	//initialization
	//open serial port
	nsSVO = -1;
	nsSVO = open("/dev/ser2", O_RDWR |O_NONBLOCK);	
	
	if (nsSVO == -1) {
		printf("Error opening serial port!\007\n");
		return -1;
	}
	
	if (nsSVO > 0 ) {
		printf("nsSVO=%d\n", nsSVO);
		printf("Opening serial port successfully!\n");		
		//return;
	}	
	
	
	tcgetattr(nsSVO, &termSVO);     
    
	cfsetispeed(&termSVO, SVO_BAUDRATE); //input and output baudrate
	cfsetospeed(&termSVO, SVO_BAUDRATE); 
  
	termSVO.c_cflag = CS8 | CLOCAL | CREAD; //set teh communication flag
//	termSVO.c_cflag &= ~PARODD;
//	termSVO.c_cflag &= ~CSTOPB;
//	termSVO.c_cflag &= ~CSIZE;
            termSVO.c_iflag = IGNBRK | IGNCR | IGNPAR;
	
	tcsetattr(nsSVO, TCSANOW, &termSVO);      //update the attributes
        
	tcflush(nsSVO, TCIOFLUSH);
	
	
	for(i=0;i<100;i=+10){
		
		szSVOCommand[0]= 0xFF;
		szSVOCommand[1]= 02;
		szSVOCommand[2]= 110;
		//szSVOCommand[3]= 0x0d;
		//szSVOCommand[4]= 0x00;
		ret = write(nsSVO, szSVOCommand,strlen(szSVOCommand));
		
		sleep(1);
		
		szSVOCommand[0]= 0xFF;
		szSVOCommand[1]= 05;
		szSVOCommand[2]= 120;
		//szSVOCommand[3]= 0x0d;
		//szSVOCommand[4]= 0x00;
		ret = write(nsSVO, szSVOCommand, strlen(szSVOCommand));		
		
		getchar();
	}
	
	return EXIT_SUCCESS;
}

Lin Feng

What device do you have QNX running on for your embedded system?

Have you tried connecting that device’s serial port to another computer to verify the serial bytes and protocol you’re generating?

I’m a little confused when you say that all of the lights were turned off. Some lights (either just the yellow LED or all three) should have been on just from powering up the servo controller. Did this light (or these lights) come on at first, then turn off when you ran you program?

-Adam

Dear Adam

Thank you for your reply!

What device do you have QNX running on for your embedded system?
I am using a PC104 single board computer “Cool RoadRunner III” made by “Lippert”.

Have you tried connecting that device’s serial port to another computer to verify the serial bytes and protocol you’re generating?
I will try to write code in windows and command the servo controller, and let you know the result soon.

I’m a little confused when you say that all of the lights were turned off. Some lights (either just the yellow LED or all three) should have been on just from powering up the servo controller. Did this light (or these lights) come on at first, then turn off when you ran you program?
Yes, you are right. When I power up the servo controller, only the yellow LED have been on. But after I boot up the PC104 computer board which is connected to the servo controller, the yellow LED on the servo controller will turn off. Actually, at that moment, I didn’t run my program. When I run my program, all the lights are still off. My program sends command to the servo controller to control the servos, but the servos cannot be turned on and I still can manually adjust the main shaft of the servos very easy. I think the servos are not turned on.

I have tried to remove the DTR/RTS reset enable jumper. I powered up the servo controller, only the yellow light was turned on. I then powered up the PC104 computer board, the red LED was turned on.

But if I connect the servo controller to a desktop running windows, even I remove the DTR/RTS reset enable jumper, I still can use “Pololu Serial Transmitter” to command the servo controller and the red LED will not be turned on.

In addition, do you have any example codes for my reference? Thank you!

Best wish,
Lin Feng

Hi Lin,

I have some example code written in C for Windows here, but before you even do that, you might want to try connecting your Roadrunner to a serial port on another computer, and looking at its output with a terminal program (such as HyperTerminal or Br@y terminal for Windows) to make sure it’s sending what you think its sending. Look at all the output of the port starting when you power it up, as one bad byte can really mess up MiniSSC-II Mode (you probably shouldn’t even be powering on the servo controller first).

I’ve done a little work with Lippert PC/104 computers, although not with the Roadrunner specifically. I remember having a problem with the serial port, where it would output a pulse that would be interpreted as a zero byte by any devices that were already turned on. This could cause behavior similar to what you’re describing, although I believe the servos would all stick in their neutral positions, and would not be manually adjustable. You might try resetting the servo controller manually (or just waiting to power your servo controller on) after you start running the program. If this fixes it, you can use the handshaking lines to reset the servo controller, or you could even use one of the Roadrunner’s GPIOs to pull the servo controller’s reset line low for a few milliseconds (probably simpler to use the handshaking lines).

You should be able to run normally with the reset jumper removed completely. This is more on the software side, but I’ve had problems with serial ports opened in Linux asserting the DRT and RTS lines when I didn’t ask them to. Even if your servos aren’t moving, with this jumper off you should see the green LED blink ever so slightly whenever you send out a serial character. Do you see this?

-Adam

Dear Adam

Thank you for your great help! Sorry, I have to disturb you again!

I can control the servo controller using the PC/104 computer under QNX operating system now, but still get some problems.

According to your suggestions, I powered on the PC104 host computer first, then I powered on the servo controller which was connected to the PC104 computer. The yellow LED was turned on first and turned off. But I still cannot control the servo controller. So I tried to remove the DTR/RTS reset jumper, then power on the PC104 computer and the servo controller. I found the red LED was turned on and the yellow one was flashing. I have to re-start the servo controller and the red LED was turned off and the yellow one was on. Then I can send command using Pololu Mode to the servo controller and control the movement of the servos.

I guess when I power up the servo controller with removing the DTR/RTS enable jumper, the red LED on maybe caused by the wrong pulse send by the PC104 computer, which you mentioned before. I used the terminal program to monitor the serial port output of the PC104 computer, when it was turned on, the terminal program cannot receive any bytes. Anyway, I want to use the method you mentioned that using the handshake line to reset the servo controller, since in my project I have to start the PC104 computer and the servo controller together, and it is not easy to restart the servo controller due the my hardware configuration. However, I am not family with handshake setting of the serial port, if possible, could you give me some detailed explanation on how to use handshake line to reset the servo controller? Or could you give an example code on how to set the handshake line for the 8 channel serial servo controller? Thank you!

In addition, I also used the C example code you give to me to test the servo controller with a desktop running Windows XP. I found a very strange thing. If the DTR/RTS enable jumper was placed on, I cannot use the example code to control the servo controller, but if I run the “Pololu Serial Transmitter” once, the example code then can control the servo controller very well. I also tried to remove this jumper, and the example code can control the servo controller without running the “Pololu Serial Transmitter” first. I guess the “Pololu Serial Transmitter” must do some setting on the handshake line. I used the serial port monitor program, and observed the “Pololu Serial Transmitter” do the settings such as: set line control and handshake information, as well as clear and set the RTS and DTR. But I don’t know the meanings of these settings.

Sorry for this long letter and thank you for your patient to read this letter.

Best wishes,
Lin Feng

DTR and RTS are serial handshaking lines, DTR stands for Data Terminal Ready, and RTS stands for Request to Send. They’re meant to let two serial devices tell each other if they’re busy right now, or if its okay to send data. Most of the time you can ignore them. “Setting RTS” will drive the RTS line high, while “clearing RTS” will drive it low.

It’s not described clearly in the user guide, and my Pololu serial servo controller is old enough that it doesn’t have the RTS/DTR reset feature, but I think the jumper is connecting the RTS (or DTR, your choice) line to the reset pin. Assuming it starts out cleared (low) your software will have to set it (high) to let the servo controller start running. Just in case, it would be a good idea to start by clearing it, pausing for a few milliseconds, then setting it again. This would mostly explain the behavior you’re seeing, since my windows code leaves the handshaking pins alone, but someone from Pololu should be able to confirm this (I may have it backwards).

Anyway, I have little experience with serial port programming for Linux, but to use this feature you’ll need to figure out how to directly set and clear the RTS or DTR pins, and I’m not sure that the termios library will let you do this. It might let you turn on RTS/CTS handshaking, but that’s not what you want, you need direct commands. In the Windows demo code you would do something like this:

EscapeCommFunction(comPort,CLRRTS);//clear RTS pin
EscapeCommFunction(comPort,SETRTS);//set RTS pin

Hope that helps, and I’m glad you’re that much closer to getting things working!

-Adam

Any progress? Jan (from Pololu) cleared up which way was which for using the handshaking lines to reset the servo controller here.

-Adam

Dear Adam

Thank you for your great help!

I have solved the problem according to your suggestions. The program in QNX will turn on RTS, sleep 2 seconds, and turn off RTS, which makes the servo controller work. In QNX, I use following codes to do such thing:

data = _CTL_RTS_CHG | _CTL_RTS;
devctl(nsSVO, DCMD_CHR_SERCTL, &data, sizeof(data), NULL); /turn on RTS now/

sleep(2);
data = _CTL_RTS_CHG | 0;
devctl(nsSVO, DCMD_CHR_SERCTL, &data, sizeof(data), NULL); /turn off RTS now/

Hope these codes are useful for other guys using this servo controller under QNX operating system.

Best wishes,
Lin Feng