Pololu maestro micro trigger subroutine with python

Dear Pololu community,
I’m here completely jammed with a problem.
I’m trying to trigger a subroutine saved in the chip via the pololu application.
When I call the subroutine via:

trigger_sequence(0x01)

declared as :

void trigger_sequence(int num){
  //Pololu protocol: 0xAA, device number, 0x27, subroutine number
  //Send a Pololu Protocol command
pololu.print(0xAA,BYTE); //start byte
pololu.print(0x0C,BYTE); //device id
pololu.print(0x27,BYTE); //command number
pololu.print(num,BYTE);  // sequence
  
}

The subroutine is activated but the red light is now on.
I figured out that the pololu subroutine shoudn’t have a RETURN but a quit.
Here is my Pololu script :

# Sequence 0
begin
  3000 6000 6000 6000 0 4784 4784 frame_0..5 # origine
  3000 8709 8381 6279 frame_0..2 # a1
  3000 6000 6000 6000 frame_0..2 # origine
  3000 6705 7497 9255 frame_0..2 # h8
  3000 6000 6000 6000 frame_0..2 # origine
  3000 6119 9014 6843 frame_0..2 # a8
  3000 6000 6000 6000 frame_0..2 # origine
  3000 8772 6291 8324 frame_0..2 # h1
repeat

sub frame_0..5
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  quit

sub frame_0..2
  2 servo
  1 servo
  0 servo
  delay
  quit

thank’s for helping,
Regards,
Albatros

Hello, Albatros.

It looks like you are trying to use the Micro Maestro’s “Restart Script at Subroutine” serial command. That command expects a data byte that specifies which subroutine to run. The user’s guide says “The subroutines are numbered in the order they are defined in your script, starting with 0 for the first subroutine.” Since you sent 0x01 for that data byte, it will run the second subroutine in your script, which is “frame_0…2”. This is not what you want. I recommend adding “sub begin” at the top of your program and changing the data byte to 0x00.

You should also change the “quit” commands back to “return”.

–David

Thank you David (very much),
But I will definitely need more tips.
First of all, you are true about the number of the triggered frame, but the frame 0x01 exists so what is the matter of the red light.
Second, why should I return back to ‘return’ instead of ‘quit’ as it is written in your docs.

Ok, may be I should explain the whole idea of my project.
I have a checker board (64 cases). I’d like to store 64 positions (saved in 64 frames) and trigger them on demand with a python code linked to Pololu micro maestro servo controller with Arduino (Uno).
Is the way I’m thinking possible? Is the code posted previously make sense ?

Again,
Regards,
Albatros (sorry for my poor english)

You are not triggering “frame 0x01”, you are triggering “subroutine 0x01”. Subroutines and frames are different. Subroutine 0x01 is “sub frame_0…2”. The first line of subroutine 0x01 is “2 servo”. The servo command consumes two values from the stack but there will only be one value when it runs, so you get a stack underflow error and the red LED turns on.

Changing “quit” to “return” will allow you to have multiple frames. If you leave it as “quit”, then the Maestro script will actually quit and stop running whenever you call a frame_* subroutine.

This is possible, but you will need to structure the code differently. You will need to make a new, distinct subroutine for each “frame” or position so they can be used individually. Something like this would work:

sub position0
  4000 0 servo
  6000 1 servo
  8000 2 servo
  quit

sub position1
  5000 0 servo
  6500 1 servo
  7000 2 servo
  quit

...

sub position63
  ...
  quit

Another (perhaps easier) option is that you could use the Sequence tab and store each position as its own sequence, then use the “Copy all Sequences to Script” button.

–David

Thank you again Mr David,

If I use the way you suggested to store my 64 positions with 64 subroutines, is the internal memory of the micro maestro servo controller will be enough to store them all ?
like you said :

    sub position0
      4000 0 servo
      6000 1 servo
      8000 2 servo
      quit

    sub position1
      5000 0 servo
      6500 1 servo
      7000 2 servo
      quit

    ...

    sub position63
      ...
      quit

Next question: is it an elegant way to do it?

regards,
Albatros

Actually it might be hard to fit all of that into the Micro Maestro using the scheme I suggest above. The maestro has 1 KB of script memory. You can see for yourself how much space the script takes up by clicking “Apply Settings to Device” and then looking in the script tab where it says “… or 1024 bytes used”.

A more efficient and more elegant way of storing the positions would be something like this:

sub position0
  4000 5000 6000 7000 8000 4000 position

sub position1
  4000 5000 6200 7000 8000 4000 position

sub position2
  4000 5000 6000 7600 8000 4000 position

...

sub position
  0 servo
  1 servo
  2 servo
  3 servo
  4 servo
  5 servo
  quit

That’s almost the same as what you would get if you used the Sequence tab, so I recommend using the Sequence tab and storing each position as a 1-frame sequence.

–David

THANK YOU MR DAVID,
I’m gonna figure the rest by myself but you helped me A LOT !!! It’s kind of clear now in my head, a way more that it was a few hours ago.
Again, Thank you for your good work,
Albatros

good morning,

the suggestions made by Daniel was right, I’m now able to move everything the way I wanted using :

sub position_origine
      6000 6000 6000 position      
sub position_a1
      8709 8381 6279 position
sub position_h8
      6705 7497 9255 position
sub position_a8
      6119 9014 6843 position
sub position_h1
      8772 6291 8324 position
      
sub position_x
     6000 5000 7000 position # bidon
     
sub position
      2 servo
      1 servo
      0 servo
      quit

called with (on the Arduino’s side): (most of the code is from xevel.fr)

void trigger_subroutine(int sub_num){
  //Pololu protocol: 0xAA, device number, 0x27, subroutine number
  //Send a Pololu Protocol command
  
clearLCD();
LCD_goTo(0,0);
lcd.print("Subroutine #");
lcd.print(int(sub_num));
  
pololu.print(0xAA,BYTE); //start byte
pololu.print(0x0C,BYTE); //device id
pololu.print(0x27,BYTE); //command number
pololu.print(sub_num,BYTE);  // subroutine[/code]

but now, I have an other problem.
Just to double check everything, I wanted to use  (again from xevel.fr:
[code]int pololu_get_position(byte servo){
  // gets the current position of a servo
 
  pololu.print(0xAA,BYTE); //start byte
  pololu.print(0x0C,BYTE); //device id
  pololu.print(0x90,BYTE); //command number
  pololu.print(servo,BYTE);  // servo num
  
  return pololu_receive_int();
}

int pololu_receive_int(){
  int low, high;
 
  while(!pololu.available()); // wait until some data is present
 
  high = pololu.read();       // read the first byte
  while(pololu.available()){  // while the rx buffer is not empty
    low=high;                        // put the previous value read in "low"
    high = pololu.read();     // put the last value in "high"
  }
  // at this point, "high" contains the last value received, and "low" the one
  // before that. Any garbage that could have been in the rx buffer has been
  // effectively thrown away.
 
  return low | (high << 8);
}

called by :

pos = pololu_get_position(servo_number);
lcd.print(pos);

Now, the value printed on the LCD is the right one,
But the red error led goes ON and the servos are moving back to their ‘start at position’ with a serial protocol error…?

any help will be greatly appreciated,
Albatros

I’m glad you are making progress. The code above is incorrect because when you are using the Pololu Protocol (0xAA, device num, command num) the command number needs to have its most-significant bit cleared. To fix this problem, you can omit the 0xAA and 0x0C bytes and just use the compact protocol instead of the Pololu protocol.

–David

Ok Dan, thank’s again it’s working as expected.
But I have a few others questions :

As you understood i’m trying to build a delta robot.

#1. when I start de Pololu servo controller…the effector is moving up and down like crazy before going at the ‘start at’ position ???

#2 when I move the effector from A to B triggering a subroutine…the 3 servos are moving one after the other (sequentially), is there a way to move them simultanously to increase (with hardware) de fluidity of the movement?
Or should I increase the number of steps between A and B, if so, what is the procedure with the subroutines ?

thank you
Albatros

That doesn’t sound good. You should make sure that the Maestro’s “Run script on startup” box is not checked and make sure you aren’t sending it unintended commands from your Arduino. If you want more help solving this, please simplify your system to the simplest possible thing that causes the problem (e.g. can you disconnect the Arduino?) and tell us more details about that simplified system.

If you wrote your subroutine as we have been discussing, the servos should all move simultaneously because you didn’t add any delay commands or loops. I don’t know why your servos are moving sequentially. What order are they moving in? Do you have acceleration or speed limits enabled? If you could simplify your script and post the entire thing here and tell me which subroutine is not behaving properly, I might be able to figure out why.

–David