Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Controlling two servos at same time problem


#1

Hello,
I have a pololu maestro 18 channel servo controller . I have written a python code to control the maestro via pc using serial bluetooth HC 05

first of all I have made a library like this
code /

class Controller :
 self.PololuCmd = "0xaa" + "0xc"
 
 def setTarget(self, chan, target):
        lsb = target & 0x7f #7 bits for least significant byte
        msb = (target >> 7) & 0x7f #shift 7 and take next 7 bits for msb
        # Send Pololu intro, device number, command, channel, and target lsb/msb
        cmd = self.PololuCmd + "0x04" + hex(chan) + hex(lsb) + hex(msb) 
        self.usb.write(cmd)

/ code
it is not full code but a logic

this seems to work
when i use this library
like this

code /

import maestro
maestro = maestro.Controller()
maestro.setTarget(0,9000) #moves to max angle

/ code

but when i want to set targets at multiple channels
like this
code/

import maestro
maestro = maestro.Controller()
maestro.setTarget(0,9000) #moves to max angle
maestro.setTarget(1,9000)

/code

this will successfully set servo 1 to max angle
but servo 0 will not have any effect
like it haven’t received any commands for servo 0
and this also happens vice versa

maestro.setTarget(1,9000) #moves to max angle
maestro.setTarget(0,9000)

in this case servo 0 moves to max angle

i think the problem is somewhere in sending some bytes
i mean it only understands ending commands
also there is a serial error of 0x0010 this lights up red led always

i have used set multiple target command and it also works for both servo
but set target method doesnt work for me

any help would be appreciated


#2

Hello.

The error message you are getting on the Maestro is a serial protocol error (see the “Errors” section in the Pololu Maestro Servo Controller User’s Guide for details), so you are correct about the issue being caused by your command byte string, cmd. I noticed that you are writing cmd as a hexadecimal string when it should be in bytes. Please see this post for details on how to escape hex values in Python. Also, you might find it helpful to look at (or use) this python module for the Maestro, which was written by one of our forum members.

By the way, if you do not already know, the Maestro is configured to output a standard pulse width range of 1ms to 2ms (or 4000 quarter-microseconds to 8000 quarter-microseconds on the Maestro) by default, which corresponds to about 90 degrees of movement on most servos. It looks like you are trying to send a pulse width (9000 quarter-microseconds) outside of the default range. You can increase the minimum and maximum range for any servo channel on the Maestro. One of the FAQs for the Maestros explains how to do this in more detail.

- Amanda


#3

Thank you very much for your support.
And the code written by me was actually edited python module written by one of the member that you have referenced.
I had to edit because the chr() function was giving me same serial error so i gave a try with hex().
By the way is their something i have to add at ending of a command so that maestro knows
Where the command is ended and when a new command starts.


#4

hey,
the library you referenced
works for only one servo at a time
let me explain
first it gives error saying it needs to be encoded to bytes, unicode not supported
so we should simply edit it to cmd.encode()
this solves the problem in python shell

but if you try to send command for 2 servos like this

maestro.setTarget(0,6000)
maestro.setTarget(1,6000)

maestro will always understand the second command
and the servo1 will reach to position to 6000 and hold the position
and servo 0 will not go anywhere also you can freely rotate servo 0 with your hands
this concludes that there is some error in sending bytes to maestro which will always light up red led

Today i figured out the problem
using .encode() solves the problem from python side but it also adds up an extra byte '/xc2’
this creates error in maestro servo controller

suppose you want to give command like this

maestro.setTarget(0,6000)
maestro.setTarget(1,6000)

i have already changed the limits from 600 to 2400 in control centre to give full range of motion

this sends bytes like
’\xc2\xaa\0xc\0x04\channelbyte 0\byte lsb0\byte msb0 \xc2 \xaa\0xc\0x04\channelbyte1\byte lsb1\byte msb1’
if i am not wrong
this means maestro detects wrong command
\xc2\xaa\0xc\0x04\channelbyte 0\byte lsb0\byte msb0 \xc2’ upto here
and next command ‘\xaa\0xc\0x04\channelbyte1\byte lsb1\byte msb1’ gets valid
this ends up controlling only servo 1
also lights up red led on maestro indicating unknown command error

so i have to again modify the code like this

import serial
ser=serial.Serial('COM10',115200,timeout=1)
def setTarget(chan, target):
    lsb = target & 0x7f #7 bits for least significant byte
    msb = (target >> 7) & 0x7f #shift 7 and take next 7 bits for msb
    # Send Pololu intro, device number, command, channel, and target lsb/msb
    cmd = (chr(0xaa) + chr(0xc) + chr(0x04) + chr(chan) + chr(lsb) + chr(msb)).encode()
    command = cmd.split(b'\xc2',1)
    ser.write(command[1])
i=9000
setTarget(0, i)
setTarget(1, i)

which will split the bytes by \xc2 and will send the exact required command
this finally solves all the problem and all the servo reaches correct position also no red error led


#5

I am glad you resolved the problem; thanks for letting us know and sharing your solution.

The Python class for the Maestro is capable of sending multiple Set Target commands (back to back) to set multiple servo channels’ positions. We have tested this and have not heard of others having problems doing that.

No, the Maestro does not have a stop byte.

Based on your description, I suspect you are using Python 3 with maestro.py which would explain why you were having trouble using the module. If you do not already know, strings are all in unicode in Python 3, not bytes like in Python 2. Even though your code works, you might consider converting your code to use bytes or bytesarrays as a more elegant solution to properly format your command byte string. (You can find more information about those objects here.) You might find it helpful to look at this post to get an idea of how to use bytearray and this post for bytes.

- Amanda