Micro Maestro 6 and Processing

Hello All,

I am attempting to control a servo using the Micro Maestro 6 and processing processing.org/. I was unable to find any online resources on how to do this.

Based on my experience with other servo controllers such as:
SSC-32 lynxmotion.com/p-395-ssc-32- … oller.aspx
And
SD-84 robotshop.com/devantech-sd84 … oller.html
And what I could gather from the User’s Guide here is the processing code I am attempting to use:

import processing.serial.*;
Serial myPort;  // Create object from Serial class

void setup()               // run once, when the sketch starts
{
myPort = new Serial(this, "/dev/tty.usbmodem00054531", 115200, 'N', 8, 2.0);
/*
with MSB set
For example, if we want to set the target of servo 0 to 1500 µs, we could send the following byte sequence:
in hex: 0x84, 0x00, 0x70, 0x2E
in decimal: 132, 0, 112, 46
  
  myPort.write(0x84);  
  myPort.write(0x00); 
  myPort.write(0x70); 
  myPort.write(0x2E);
  */
  
  /*
  with MSB cleared
  For example, if we want to set the target of servo 0 to 1500 µs for a Maestro with device number 12, we could send the following byte sequence:
  in hex: 0xAA, 0x0C, 0x04, 0x00, 0x70, 0x2E
  in decimal: 170, 12, 4, 0, 112, 46
  */
  myPort.write(0xAA);
  myPort.write(0x0C); 
  myPort.write(0x04);  
  myPort.write(0x00); 
  myPort.write(0x70); 
  myPort.write(0x2E);
  //*/
}

void draw()
{
/*
For example, if we wanted to set the target of servo 0 to its (configurable) neutral position, we could send the following byte sequence:
in hex: 0xFF, 0x00, 0x7F
in decimal: 255, 0, 127
*/
   myPort.write(0xFF);
   myPort.write(0x00); 
   myPort.write(0x7F); 
  
   delay(20);
}

When I run this code in processing the green LED on the Maestro blinks rapidly indicating that data is getting through but the servo connected to channel 0 does not move or even freeze in a locked position position. I can easily turn the horn with my hand indicating to me that no data or power is going to the servo.

I am able to control servos using the Maestro Control Center software.

The processing sketch is being run on:
Mac OSX 10.7.5
Processing v2.0b

I have tried selecting both:
UART, fixed baud rate 115200
And
UART, detect baud rate
On the Maestro Control Center….

I suspect there is an issue with how I am setting the servo up with the hexadecimal commands. Does anyone have any ideas?

Thank you,

Hello. You are trying to control the Maestro over USB, right? The correct serial mode to use is “USB Dual Port”. In the future, please use [code ] and [/code ] tags (without the spaces) to make your code readable. --David

Hi David,

Thank you for the response. Yes, I am using a USB cable. Setting the “USB Dual Port” got me closer. I now have the servo moving but its range is very limited. Sorry for the sloppy code posting in my previous message. With the below code, the servo should move from 0 to 1500 when the mouse is scrolled.

import processing.serial.*;
Serial myPort;  // Create object from Serial class
int x = 500;
int servoX;
byte[] servo_bytes;

void setup()  
{
   size(512, 512);
   myPort = new Serial(this, "/dev/tty.usbmodem00054531", 115200, 'N', 8, 2.0);
   myPort.write(0xAA);
   myPort.write(0x0C); 
   myPort.write(0x04);  
   myPort.write(0x00); 
   myPort.write(0x70); 
   myPort.write(0x2E);
}

void draw()
{
   background(constrain(mouseX / 2, 0, 255)); 
   servoX = int(map(mouseX,0,512,0,1500));
   myPort.write(0xFF);
   myPort.write(0x00); 
     servo_bytes = new byte[2];
     servo_bytes[0] = (byte(servoX));
     servo_bytes[1] = (byte(servoX>>7));
   myPort.write(servo_bytes);
   myPort.write(0x7F);
   println(servoX);
   delay(20);
}

But it only moves from 0 to 255 and then resets to 0 again. Clearly I am doing something wrong with how I break the position data into bytes. How do I make position information(a variable from 0 to 1500) into something the Maestro understands?

cheers!

It looks like you are using the MiniSSC protocol, so the third byte of the command specifies the position of the servo and needs to be between 0 and 254. I think the processing “map” function that you are already using can be used to easily generate that byte:

myPort.write(0xFF);
myPort.write(0x00); 
myPort.write(int(map(mouseX,0,512,0,254));

You were sending two bytes for the servo position followed by 0x7F; this is incorrect. This Mini SSC command is just three bytes, and they are specified in the Maestro User’s Guide.

–David

Hi,

Thank you for the response. Sorry for the confusion. The reason I was using the “Mini SSC protocol” was because it was the only one I could get to work. But it is not useful to me because it only moves the servo in a limited range with limited resolution. I would like to move the servo from 0 to 1500. I have tried, from my interpretation of the user guide, the “Set Target Pololu protocol”

servoX = int(map(mouseX,0,512,0,1500));
  //Pololu protocol: 0xAA, device number, 0x04, channel number, target low bits, target high bits
   myPort.write(0xAA);
   myPort.write(0x0C); 
   myPort.write(0x04);  
   myPort.write(0x00); 
   myPort.write(byte(servoX)); 
   myPort.write(byte(servoX>>7));

and the “Set Target Compact protocol”

   servoX = int(map(mouseX,0,512,0,1500));
   //Compact protocol: 0x84, channel number, target low bits, target high bits
   myPort.write(0x84); 
   myPort.write(0x00); 
   myPort.write(byte(servoX) & 0x7F); 
   myPort.write(byte(servoX>>7) & 0x7F);

Neither of these work. Can you see anything in these that I might be missing?

thank you,

I am not sure what you mean by 0 to 1500. Pulse widths are typically 1000 microseconds to 2000 microseconds. The Maestro has a quarter microsecond resolution, so it represents those pulses as numbers from 4000 to 8000. Therefore, your servoX variable needs to be between 4000 and 8000. Your implementation of the Compact Protocol looks correct to me except for the value of servoX. Your Pololu Protocol implementation is incorrect because you forgot to mask off the most-significant bit of the data bytes using " & 0x7F".

I recommend a careful reading of the “Set Target” subsection of the “Serial Servo Commands” section of the Maestro User’s Guide.

–David

Hello.

These are not valid positions for a servo. The standard range for a servo is 1000 us to 2000 us, but you can often expand this a bit to get a little more range from your servo (be careful not to damage the servo by commanding it past its end stops if you try expanding the range!). The Maestro command you are using takes the servo position in units of quarter microseconds, so if you want to send a pulse of 1500 us, you need to send a position value of 1500x4=6000.

I suggest you start by simplifying: just send a string of fixed bytes that should work. For example, the user’s guide tells you exactly what to send to get a position of 1500 us on channel 2:

For a position of 1700 us, you would send:

Can you just have your program alternate between sending these two commands with a delay in between? If that doesn’t work, can you print out the exact bytes you are sending to make sure you are sending what you think you are? For example, if the program is treating the numbers as integers, you might really be sending two bytes with every serial write.

- Ben

Hi Ben,

Thanks for the response and clarification. In this code

   myPort.write(0x84); 
   myPort.write(0x00);
  
   servo_lowbyte = (0x70);
   servo_highbyte = (0x2E);
  
   myPort.write(servo_lowbyte);  
   myPort.write(servo_highbyte); 
   
   println(servo_lowbyte + " " + servo_highbyte);
   
   delay(1000);
   
   myPort.write(0x84); 
   myPort.write(0x00);
  
   servo_lowbyte = (0x10);
   servo_highbyte = (0x35);
  
   myPort.write(servo_lowbyte);  
   myPort.write(servo_highbyte); 
   
   println(servo_lowbyte + " " + servo_highbyte);
   
   delay(1000);

The servo connected to pin0 alternates back and forth slightly and “112 46” and “16 53” are printed out with each movement. Given this and your clarification about the servo range it seems logical that something like this should work for me

   background(constrain(mouseX / 2, 0, 255)); 
   servoX = int(map(mouseX,0,512,1000,2000));
   //Compact protocol: 0x84, channel number, target low bits, target high bits
  
   myPort.write(0x84); 
   myPort.write(0x00);
  
   servo_lowbyte = (servoX) & 0x7F;
   servo_highbyte = (servoX >> 7) & 0x7F;
  
   myPort.write(servo_lowbyte);  
   myPort.write(servo_highbyte); 
   
   println(servoX + " " + servo_lowbyte + " " + servo_highbyte);
   
   delay(20);

but with this code the servo only locks in a fixed position and does not move. The values that are being printed as a I scroll over the mouse are like: “1250 98 9”, “1828 36 14”, “1929 9 15” and “1035 11 8” Forgive my ignorance of separating integers into lowbits and highbits, but does this seem like they are being broken down correctly?

thank you,

In case anyone is interested, I got it to work.

import processing.serial.*;
Serial myPort;  // Create object from Serial class
int servoX;
byte[] serialBytes;

void setup()  
{
   size(512, 512);
   myPort = new Serial(this, "/dev/tty.usbmodem00054531", 115200, 'N', 8, 2.0);
}

void draw()
{
   background(constrain(mouseX / 2, 0, 255)); 
   servoX = int(map(mouseX,0,512,500,2000));
   
   //Compact protocol: 0x84, channel number, target low bits, target high bits
   myPort.write(0x84); 
   myPort.write(0x00);
 
   myPort.write(byte((servoX << 2) & 0x7F)); // Second byte holds the lower 7 bits of target.
   myPort.write(byte((servoX >> 5) & 0x7F));   // Third data byte holds the bits 7-13 of target.
   
   println(servoX);
   
   delay(20);
}

figured it out through trial and error… still a mystery why the bytes need to be broken down like this but… anyway it works…

Thanks to the Pololu folks for responding to me at odd hours over the weekend.

cheerio!

Hello.

I think you missed my earlier comment that the servo positions you were trying to send were not valid and that you need to use units of quarter microseconds. Similarly, these positions are not valid, either:

You need to multiply them all by four before sending them to the Maestro. This is what you stumbled on with your trial and error (bit-shifting to the left by two is the same as multiplying by four). I’m happy to hear you have it working now!

- Ben

Hej,
i also trying to move a servo with a Pololu 18 Servo-board.
I tried the posted codes but no one worked. (i changed the Adresse).
The Green LED is blinking rapidly while running the Programm.
I use an external voltage and sat the jumper to VSRV=VIN.
When i turn on the Power the servo shrugs so it isn’t broken.
Any Ideas?
I use a Mac.

Hello.

Can you get the servos to move by using the Maestro Control Center? If you have not tried this, could you test it and let me know what happens? Please note that the Maestro must be initially configured from a Windows or Linux computer before you can control it through the Maestro Control Center from a Mac.

Also, Could you post pictures of your setup, along with a diagram of your connections?

-Brandon