Micro Serial Servo Controller

Hi,

I have one of your Micro Serial Servo Controllers but am having trouble
getting it to work.
I am using Pololu Mode with no jumper on the board.

When I power up the board the yellow LED comes on ok.
When I try to send data to the board, the red LED comes on and the green LED
flashes.
Even if I try to get the board to tell me the servo number settings.
This happens whatever baud rate I try and set.
e.g.


 // Open the serial port.
 g_hSerialPort = CreateFile (TEXT("COM1:"), // Pointer to the name of the 
port
       GENERIC_READ | GENERIC_WRITE, // Access (read/write) mode
       FILE_SHARE_READ | FILE_SHARE_WRITE,            // Share mode
       NULL,         // Pointer to the security attribute
       OPEN_EXISTING,// How to open the serial port
       0,            // Port attributes
       NULL);        // Handle to port with attribute to copy

 // If it fails to open the port, return FALSE.
 if ( g_hSerialPort == INVALID_HANDLE_VALUE ) {
  // Could not open the port.
  MessageBox (g_hWnd, TEXT("Unable to open the port"), TEXT("Error"), 
MB_OK);
  dwError = GetLastError ();
  return FALSE;
 }

 SerialPortDCB.DCBlength = sizeof (DCB);
 // Get the default port setting information.
 GetCommState (g_hSerialPort, &SerialPortDCB);

 SerialPortDCB.BaudRate = 9600;              // Current baud
 SerialPortDCB.fBinary = TRUE;               // Binary mode; no EOF check
 SerialPortDCB.fParity = FALSE;               // Enable parity checking.
 SerialPortDCB.fOutxCtsFlow = FALSE;         // No CTS output flow control
 SerialPortDCB.fOutxDsrFlow = FALSE;         // No DSR output flow control
 SerialPortDCB.fDtrControl = DTR_CONTROL_DISABLE ; // DTR flow control type
 SerialPortDCB.fDsrSensitivity = FALSE;      // DSR sensitivity
 SerialPortDCB.fTXContinueOnXoff = FALSE;     // XOFF continues Tx
 SerialPortDCB.fOutX = TRUE;                // No XON/XOFF out flow control
 SerialPortDCB.fInX = FALSE;                 // No XON/XOFF in flow control
 SerialPortDCB.fErrorChar = FALSE;           // Disable error replacement.
 SerialPortDCB.fNull = FALSE;                // Disable null stripping.
 SerialPortDCB.fRtsControl = RTS_CONTROL_DISABLE;          // RTS flow 
control
 SerialPortDCB.fAbortOnError = FALSE;        // Do not abort reads/writes on 
error.
 SerialPortDCB.ByteSize = 8;                 // Number of bits/bytes, 4-8
 SerialPortDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space
 SerialPortDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2


 // Configure the port according to the specifications of the DCB structure.
 if (!SetCommState (g_hSerialPort, &SerialPortDCB)) {
  // Could not create the read thread.
  MessageBox (g_hWnd, TEXT("Unable to configure the serial port"), 
TEXT("Error"), MB_OK);
  dwError = GetLastError ();
  return FALSE;
 }


 buff[0]=0x80;//start byte
 buff[1]=0x02;//device id
 buff[2]=16;//command number
 WriteFile(g_hSerialPort, &buff, 3, &len, 0);

Please advise what I am doing wrong.

Thanks
Simon

Your problem may be as simple as having your serial and ground communications lines swapped! I’m running a micro servo controller from a PC serial port, and that’s the LED pattern I see when I plug the connector in backwards. With a standard DB9 connector you want pin 5 to be ground, and pin 3 to go to the RS-232 serial input. The problem might be the same if you’re going through a logic-level converter to the TTL level inputs.

Your code looks fine to me, but if you’d like you can try this very simple one I made this morning for a co-worker to run a servo at our weekly meeting:
engin.umich.edu/~aborrell/prog/flipper.exe
It’s called flipper because the servo was actuating, well, a flipper on one of our robots. Anyway, it controls just one servo, and it will tell you all the key commands (and optional command-line arguments) when you run it the first time. If you’d prefer not to download and run a strange executable, here is the source code (in C for win32 console applications):

/*
Flipper Servo Demonstration Program
Adam Borrell
4/12/06
 */

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>

HANDLE openPort(int);
void put(int, int);
void move(int, int);
void servoOff();
HANDLE fd;

void main(int argc, char *parameters[])
{
	char input[32];
	int il=0,ol=0;
	int done=0;
	int min=2000, max=4000, step=50, neutral=3000, servoNumb=0;
	int ang;
    fd=openPort(CBR_19200);

	printf("Flipper Flipper\n\n");
	printf("Commmands:\n");
	printf("A - Increase servo position\n");
	printf("Z - Decrease servo position\n");
	printf("Q - Send servo to min\n");
	printf("W - Send servo to neutral\n");
	printf("E - Send servo to max\n");
	printf("Spacebar - Emergency Servo Stop (no effect on digital servos)\n");
	printf("Backspace - quit\n\n");
	
	if(argc==1){
		printf("Argument Format:\n");
		printf("Servo Neutral Position 500-5500 (Defualt 3000)\n");
		printf("Servo Min Position 500-5500 (Defualt 2000)\n");
		printf("Servo Max Position 500-5500 (Defualt 4000)\n");
		printf("Servo Step Size (Defualt 50)\n");
		printf("Servo Number (Default 0)\n\n");
	} else {
		if(argc>1){
			neutral=atoi(parameters[1]);
		}
		if(argc>2){
			min=atoi(parameters[2]);
		}
		if(argc>3){
			max=atoi(parameters[3]);
		}
		if(argc>4){
			step=atoi(parameters[4]);
		}
		if(argc>5){
			servoNumb=atoi(parameters[5]);
		}
	}

	ang=neutral;

	while (!done) {
		*input = getch();
		switch(*input){
			case 32:
				servoOff();
				printf("Emergency Servo Stop\n");
				break;
			case 8:
				done = 1;
				break;
			case'a':
				if(ang<=(max-step)) ang+=step;
				put(servoNumb,ang);
				break;
			case'z':
				if(ang>=(min+step)) ang-=step;
				put(servoNumb,ang);
				break;
			case'q':
				ang=min;
				put(servoNumb,ang);
				break;
			case'w':
				ang=neutral;
				put(servoNumb,ang);
				break;
			case'e':
				ang=max;
				put(servoNumb,ang);
				break;
			
			default:
				break;
		}
	}
	servoOff();
	printf("done!\n");
	return;
}

void put(int servo, int angle) {
	unsigned char buff[6];
	DWORD len;

	unsigned short int temp;
	unsigned char pos_hi,pos_low;
	
	temp=angle & 0x1f80;
	pos_hi=temp>>7;
	pos_low=angle & 0x7f;

	buff[0]=0x80;//start byte
	buff[1]=0x01;//device id
	buff[2]=0x04;//command number
	buff[3]=servo;//servo number
	buff[4]=pos_hi;//data1
	buff[5]=pos_low;//data2
	WriteFile(fd, &buff, 6, &len, 0);

	printf("%s%d\n", "Servo Position ", angle);

	return;
}

void servoOff() {
	unsigned char buff[6];
	DWORD len;
	int servo;

	buff[0]=0x80;//start byte
	buff[1]=0x01;//device id
	buff[2]=0x00;//command number
	buff[4]=0x0f;//data1
	for(servo=0;servo<8;servo++) {
    	buff[3]=servo;//servo number
    	WriteFile(fd, &buff, 5, &len, 0);
    	}    
	return;
}

HANDLE openPort (int baud) {
	HANDLE fd;
	COMMTIMEOUTS joy_timeouts = {0,0,0,0,0};
	DCB joy_dcb;
	fd=CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
	if(fd==INVALID_HANDLE_VALUE) {
		fprintf(stderr, "BOO: Could not open COM1 port!\n");
		return (HANDLE) -1;
	}
	if(!GetCommState(fd, &joy_dcb)){
		CloseHandle(fd);
		fprintf(stderr, "BOO: Could not read COM1 state!\n");
		return (HANDLE) -1;
	}
	joy_dcb.BaudRate=baud;
	joy_dcb.ByteSize=8;
	joy_dcb.fParity=0;
	joy_dcb.Parity=NOPARITY;
	joy_dcb.StopBits=ONESTOPBIT;
	if(!SetCommState(fd, &joy_dcb)){
		CloseHandle(fd);
		fprintf(stderr, "ERROR: Could not set COM1 State!\n");
		return (HANDLE) -1;
	}
	if(!SetCommTimeouts(fd, &joy_timeouts)){
		CloseHandle(fd);
		fprintf(stderr, "ERROR: Could not set COM1 Timeouts!/n");
		return (HANDLE) -1;
	}
	return fd;
}

Another potential problem is the one I had with my first Pololu micro servo controller…after I accidentally shorted power to the TTL input pin (puff of smoke, sad day). Servos connected to it still go to their neutral positions after I start sending commands of any sort, and sometimes it takes a few just flashing the green light, but sooner or later I get a different pattern of unhappy looking LED flashing.

Anyway, I hope some of this helps. Please post to let us all know how it works out!

Many thanks for the quick reply, and thanks for the code.

After laying awake last night I found the problem!

I was testing the controller with a serial cable with 2 wires jammed into the plug. It turns out that my serial cable is a NULL modem cable so pins 2 and 3 are crossed (Doh!)
As soon as I connected it to the right pin it worked fine!

Now all I have to do is modify the servos for linear motion!

Thanks again
Simon