24 ch servo controller intermittent random movement

Hi All,

I have built and nearly finished a pan & tilt time lapse system that uses servos for pan and tilt, and a servo relay to click the remote on the camera. It runs on a Rapsberry Pi using PHP. When panning/tilting, it has a starting position, an end position, and a number of intervals set. It calculates its next position using these 3 variables (with integer rounding) and works 99% of the time. This means every new position is always just a fraction different to the one before, to make it smooth.

Unfortunately, it intermittently pans (or tilts) ridiculously way off (more than 90 degrees sometimes) and then recovers perfectly for the next shot where it should be. I cannot understand what could make it behave like this. I have all of the servo values recorded in a log file, which I can mach up with each photo taken, so I know just where to look to look to see if my program is miscalculating values. It’s not though. The logs indicate perfect smooth movement.

I can only think that power issues might cause this but if that were the case then I would have thought it would become more apparent when the batttery gets weaker. I am using a 4000mah 2S 7.2V li-po battery hooked up to a 5v regulator, and the lipo has low voltage detector hooked up to each cell (set at 3.5v warning). I would have thought that this was a pretty good power control, so I am out of ideas.

If I can’t stop it from behaving like this then the project cannot work, so I would appreciate any feedback from anyone who has seen this before please.

Howard.

Hello.

Are you using a virtual serial port to talk to the Maestro? Have you made sure to configure it so that it is not modifying bytes that happen to be newline characters?

–David

Hi David,

Thanks for your reply. The Pi is connected via USB to the controller and the controller is in USB Dual port mode. When I run Maestro Control Center under X windows, it works just fine with scripts and real-time controls.

The PHP code uses a public serial library from code.google.com/p/php-serial/sou … s.php?r=11

It is called like this:

//******************************************************************************
//Set up connection
//******************************************************************************
$serial = new phpSerial();
$serial->deviceSet("/dev/ttyACM0"); //The device path
$serial->confBaudRate(9600); //Baud rate setting, although apparently not needed
$serial->confParity("none");//partiy, needed?
$serial->confCharacterLength(8); //byte length to 7 bits
$serial->confStopBits(1);//stop bits, needed?
// open the connection
$serial->deviceOpen();

Servo positioning is called like this:

set_servoposition($serial, 0, intval($tiltstart));
set_servoposition($serial, 1, intval($panstart));

This is my set_servoposition funtion:

// Set a servo's position

function set_servoposition(&$serial, $servonum, $position)
{
        $serial->sendMessage(chr(0x84) . chr($servonum) . chr($position & 0x7F) . chr(($position >> 7) & 0x7F));
        return 0;
}

I have written PHP code for calling all of the pololu function calls and was going to release it for all to use, but this infrequent but erratic behaviour is preventing me from confidently handing it out.

I hope that answers you question. Any advise would be greatly appreciated.

Howard

It looks like you haven’t done anything special to turn off the mangling of newline characters so that is probably the problem.

Check out our example C code in the “Cross-platform C” section of the Maestro User’s Guide. These are the lines that turn off several configuration options for the serial port, including the mangling of newline characters:

  struct termios options;
  tcgetattr(fd, &options);
  options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  options.c_oflag &= ~(ONLCR | OCRNL);
  tcsetattr(fd, TCSANOW, &options);

You will need to figure out how to do the equivalent thing in php. You might try googling around for things like “php c_lflag” or “php tcsetattr”, but I just did that and couldn’t find anything useful.

Before spending too much time on it you should probably confirm that newlines are the problem. You could confirm it by sending a command that happens to have a newline character (0x0A) as the third byte and seeing if the command gets messed up. I suspect that “\n” is getting replaced by “\r\n” so the fourth byte of the command would be totally changed.

–David

Hi David,

Thanks for the advice! I will certainly try and establish if this is the cause this week.

Thanks so much for your prompt replies.

Howard.

Hi David,

You were exactly right! :smiley: I placed a 0xA in the the third byte and it indeed went wrong. Thanks so much for identifying this. I can honestly say that I would never have thought of that :blush:

Now I just need to understand the code you posted and somehow translate it to PHP.

Many thanks. I’ll post again if I struggle with the conversion.

Thanks,
Howard

FIXED!

For anyone trying to use PHP and the the PHP serial library in the the link above, a modification is required to simulate the code kindly provided by David. Within the “deviceSet” function, there is a call made to the stty command. It needs to be modified as per the first line of the code below.

if ($this->_exec("stty -F " . $device . " -echo -echonl -icanon -isig -iexten -onlcr -ocrnl") === 0)
{
	$this->_device = $device;
	$this->_dState = SERIAL_DEVICE_SET;
	return true;
}

Once that is done, it’s all happy, and there are no more problems with a 0xA being in the 3rd byte. If I had more time I would update the class so it accepted this as a parameter, but I took a bit of a shortcut and hard coded it in the class code.

Thanks again David. Very impressed with the level of support.

Cheers,
Howard

Hello, Howard. I am very glad that you were able to figure this out, and that you posted your solution here for others to benefit from. I will refer future PHP+serial users to this thread!

–David