Maestro 24 PWM Linux

The boards have access Pololu Maestro PWM.
Decided to “play” with the connection of low-power light bulbs.
When controlling a computer using the program Maestro Control Center to determine the parameters: start time 12, the period of 108 - at such parameters lamp lights. Changes in the period from 12 to 108 can control the lighting from minimum to maximum.
Now the question is how all the same to alter the command set of parameters.
Wrote this sequence, according to the documentation for the device Pololu:

{ byte 0xAA #Start Byte byte 0x01 #Device ID = 1 byte 0x0A #Command = Set PWM byte $ ((TARGET1 & 0x7F)) #On time low bits byte $ ((TARGET1 >> 7 & 0x7F)) #On time high bits byte $ ((TARGET2 & 0x7F)) #Period low bits byte $ ((TARGET2 >> 7 & 0x7F)) #Period high bits }> $ DEVICE

TARGET1 - on time
TARGET2 - period

As input parameters are used: TARGET1 = 12 and TARGET2 = 108, but nothing happens.
Help solve the problem.

Along the way, tell me, how can the same set of enable and disable PWM?


It sounds like you are trying to write a Bash script to send a serial “Set PWM” to a Mini Maestro 24-channel servo controller, and it is not working. Your script looks similar to the example Bash script in the Maestro User’s Guide.

You should make sure that you have set the Maestro to an appropriate serial mode like “USB Dual Port”, and that the PWM pin is configured as an output. You should also make sure that the Maestro’s serial device number is set to 1 to match the device number that you are sending in your code.

I noticed that you have spaces after the dollar signs ($) in your Bash script. I do not think that will work; you should remove the spaces after the dollar signs.

If this advice does not help, could you please use the Maestro Control Center to save a settings file and then post it here as an attachment? Also, please post your entire Bash script and provide the exact command that you are using to run it. If the script produces any output (including error messages), please post the entire output here.

You can enable PWM by sending the “Set PWM” serial command. You can disable PWM by sending a “Set Target” command, or you can simply set the PWM on time to 0 to make the output go low.


Here is a full working code bash script (

[code]#! / bin / bash

Sends a Set Target command to a Pololu Maestro servo controller

Via its virtual serial port.


Linux example: bash / dev / ttyACM0 0 6000

Mac OS X example: bash /dev/cu.usbmodem00234567 0 6000

Windows example: bash ‘\. \ USBSER000’ 0 6000

Windows example: bash ‘\. \ COM6’ 0 6000

CHANNEL is the channel number

TARGET is the target in units of quarter microseconds.

The Maestro must be configured to be in USB Dual Port mode.

DEVICE = "/dev/ttyACM0"
TARGET1 = $3
TARGET2 = $4
byte () {
printf “\x$(printf “%x” $1)”
byte 0xAA #Start Byte
byte 0x01 #Device ID = 1
byte 0x1F #Command = Set Multiple Targets
byte $N_TARGET #0x02 #Number of targets = 2
byte $N_CHANNEL #0x00 #First channel number = 0
byte $((TARGET1 & 0x7F)) #0x70 #First target low bits <- First SERVO
byte $((TARGET1 >> 7 & 0x7F)) #0x4E #First target high биц
byte $((TARGET2 & 0x7F)) #Second target low bits <- Second SERVO
byte $((TARGET2 >> 7 & 0x7F)) #Second target high bits
} > $DEVICE[/code]

Start line looks like this:

thereby rotate the actuator pointing script number 3 at an angle with a value of 6000 and a number of servo 4 by an angle with a value of 7000.

Now I need the same way (with another bash script) to control lighting.

Do this:

DEVICE="/dev/ttyACM0" TARGET1=$1 TARGET2=$2 byte() { printf "\\x$(printf "%x" $1)" } { byte 0xAA #Start Byte byte 0x01 #Device ID = 1 byte 0x0A #Command = Set PWM byte $((TARGET1 & 0x7F)) #On time low bits byte $((TARGET1 >> 7 & 0x7F)) #On time high bits byte $((TARGET2 & 0x7F)) #Period low bits byte $((TARGET2 >> 7 & 0x7F)) #Period high bits }> $DEVICE

but the team does not work.

Maestro mode is set to “USB Dual Port”. The device number is set to 1. The settings file will lay out later.

Spaces after the dollar sign ($) - it’s a typo when posting on forums. Corrected.

May suggest a sequence of commands to enable “Set PWM” and “Set Target”?

In general, gradually begin to understand the current problem.
When you turn on Maestro, exit “PWM Output” remains off. Accordingly, the line “Enable PWM on channel 12” is also in the off position. In this regard, management of this channel is not possible.
Tell me how you can programmatically using bash script in Linux to control the state of the channel (turn on and off)?

I just tried your Set PWM script on a Linux computer here, with an 18-channel Maestro, and it worked fine. I was able to control the brightness of an LED connected to channel 12, and the specific values that you were using (12, 108) also worked fine.

The PWM-related controls in the “Status” tab of the Maestro Control Center do not always reflect the current state of the PWM output. Whenever you start the Maestro Control Center, the “Enable PWM” checkbox will be unchecked and the parameters will be at their default values.

The “Set PWM” and “Set Target” commands are documented in the “Serial Servo Commands” section of the Maestro User’s Guide. You can disable the PWM output by setting the target of channel 12 to 0, using the “Set Target” command.

If you would like to keep troubleshooting the PWM Bash script, please post your Maestro settings file and the exact command you used to run the script. Also, do you see the Maestro’s green LED blink briefly when you run the script?


I have a startup command from bash red LED (error). As with the command bash read the error code?
And if you run through the program Maestro no error.

It sounds like when you ran your Bash script for setting the PWM, the red LED on the Maestro turned on. It also sounds like you are able to control the PWM output fine from the Status tab of the Maestro control center, without the red LED turning on. Is that correct?

The red LED indicates that an error happened. After the red LED turns on, I recommend looking in the “Errors” tab of the Maestro Control Center to see what error occurred.

If you want to continue troubleshooting the script, please use the Maestro Control Center to save a settings file and then post it here as an attachment. Also, please provide the exact command that you typed in your shell to run the Bash script. If the script produces any output (including error messages), please post the entire output here.


The script uses the same as that given above.
Sending a configuration file.
When you run under Windows means the program Maestro Control Center all works fine.
In the Linux graphical shell is not used. Works only on the command line console. Connects to your computer via SSH.
On one of the forums I was answered that PWM can be switched on / off only from the Maestro Control Center, thus limiting the possibilities of this product.
Now an error.
Error executing the above script and remained. The error code still can not provide, as it works in batch mode, however, when trying to display an error in the file are displayed here such characters: “Є!” (Encoding: 1251 - ANSI). Trying to translate into a more readable form.
maestro_settings.txt (4.53 KB)

If we use the structure of the “Set Target” to activate LED, then:

  1. Turn on or work only occur when the period of more than 6000.
  2. During the LED brightness can not be changed.

You should be able to set the PWM output with a serial command without using the Maestro Control Center. I am not sure why it has not worked for you yet.

Thank you for sending your settings file. I looked at it and I did not notice any problems.

Here is a Bash script you can use to read the errors from the Maestro:



byte() {
  printf "\\x$(printf "%x" $1)"

  byte 0xA1
  od -N 2 -x -An | tr -d ' ' >&3
} > $DEVICE < $DEVICE 3>&2

It prints them in the same hex format as the Maestro Control Center. For example, if it prints “0010”, that would be a Serial Protocol Error. After running this script, the red LED should turn off, and running the script a second time should give a result of “0000”. By the way, I noticed that this script runs forever without doing anything when I try to run it in Dash, so you should definitely keep using Bash.

Another option for seeing the errors would be to install the Maestro Linux software and run the command “UscCmd --status”.

What Linux distribution are you using? What type of hardware your Linux system running on?


Platform Raspberry Pi (model B).
Version of the system: Linux raspberrypi 3.18.5+ (Raspbian)
Your script prints nothing, even when working in the two terminals.

After trying the scripts on a Raspberry Pi here, I was able to reproduce your problem and solve it. The problem is that by default Raspbian or some component of it decides to do some manipulation of the bytes that are sent and received on a virtual COM port. The solution to that is to use the stty raw command on /dev/ttyACM to change those settings. Here are updated scripts that should work for you:

Set PWM:


byte() {
  printf "\\x$(printf "%x" $1)"

stty raw -F $DEVICE

  byte 0x8A
  byte $((ONTIME & 0x7F))
  byte $((ONTIME >> 7 & 0x7F))
  byte $((PERIOD & 0x7F))
  byte $((PERIOD >> 7 & 0x7F))

Get Errors:



byte() {
  printf "\\x$(printf "%x" $1)"

  stty raw
  byte 0xA1
  od -N 2 -x -An | tr -d ' ' >&3
} > $DEVICE < $DEVICE 3>&2


Thank you very much, David.
It worked!

Hi David,
your bash tricks helped me a lot to do my first successful steps using maestro micro servo controller with debian 8 linux bash.
I modified your ‘get error’ sample into ‘get position’ function. Both worked fine.
Is there a way to get the error/position value shown on the console into a variable for further processing?
Thanks for any hint in advance.

Hello, hkraspi.

In the code I posted above, the command that reads two bytes from its standard input (the Maestro’s serial port), formats it, and outputs it to its standard output is od -N 2 -x -An | tr -d. You can capture the standard output of that command and put it into a variable the same way you would capture the standard output of any other Bash command, by doing something like:

X=$(od -N 2 -x -An | tr -d)

I don’t think Bash is a very good language for processing binary data. You would probably be better off learning a language like Python or Ruby. The “Related Resources” section of the Maestro user’s guide has some Python code that you might find useful.


Hello David,

thank you so much for your fast and helpful hint.

I just got lost with the i/o redirects in the bash example.

Now it is clear to me and I got it working successfully.

Maybe I will use python instead of bash some day, when I should not be able
to solve any special case using bash.
Possibly due to performance reasons.

Thanks a lot again