Triggering sequences via serial commands

I am very new to programming, so please bear with me if I am asking very basic questions.

I have a robot and the main controller is capable of sending out I2C and serial in order to trigger different commands. I use the serial and the TX/RX/Ground pins to trigger other components of the robot. I purchased Maestros in order to handle the servo animations. From what I understand, the Maestro is able to accept serial commands.

I successfully created within the Maestro Control Center two sequences, to which I have a Maestro 24 and will add several more Maestros. When I have the Maestros connected to the Control Center, I am able to successfully trigger the sequences with the PC by means of the “Play Sequence” button on the Sequence tab. I have uploaded the script to the Maestro. Below is what I’ve uploaded.

My question is: when I send a serial command to the Maestro, what do I need to do in order to do trigger the Sequences to play?

  1. Am I able to direct connect the RX/TX and TX/RX and GND/GND to the Maestro and send it direct serial commands (which is how I have it currently configured), or do I need an Arduino Uno in between the boards to relay the command to the Maestro?
  2. How do I trigger a specific sequence? Is it as simple as sending just a sequence number to the Maestro or the sequence name? I have not been able to successfully trigger a sequence by this method.

I’m hoping it is a simple solution. I have a number of simple servo routines that I wish to trigger, so the number of sequences will grow beyond the 2 that I have only loaded below.

Respectfully,

### Sequence subroutines: ###

# Leia "only hope"
sub Leia_only_hope
  16000 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 0 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # All closed
  19000 4032 7936 frame_0_4 # Open LCD panel
  500 3968 3968 frame_0_4 # All closed
  return
# Mando
sub Mando
  500 3968 3968 3968 3968 3968 3968 
  8000 4736 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # Start -  All closed
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 frame_0..7 # All lower open
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All closed
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 2
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All closed - 2
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 3
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All lower closed - 3
  6000 8000 7936 7168 7789 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 4
  4800 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All lower closed - 4
  500 6720 6848 frame_8_11 # Outside upper open
  200 3968 5440 6912 3968 frame_8..11 # Switch
  200 8000 3968 frame_9_10 # End - All closed
  return

sub frame_0..23
  23 servo
  22 servo
  21 servo
  20 servo
  19 servo
  18 servo
  17 servo
  16 servo
  15 servo
  14 servo
  13 servo
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0_4
  4 servo
  0 servo
  delay
  return

sub frame_0..7
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0..12
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_8_11
  11 servo
  8 servo
  delay
  return

sub frame_8..11
  11 servo
  10 servo
  9 servo
  8 servo
  delay
  return

sub frame_9_10
  10 servo
  9 servo
  delay
  return

Hello.

If your robot’s main controller uses appropriate TTL serial signals, then you should be able to directly connect to the Maestro’s UART pins like you described. In general, I recommend reading through the “Serial Interface” section of the Maestro user’s guide, but you can find information about the Maestro’s serial formatting in the “TTL Serial”. Please note that you will also need to set the Maestro’s serial mode to one of the UART modes in the “Serial Settings” tab. You can find more information about those in the “Serial Settings” subsection.

You can send a “Restart Script at Subroutine” command to run a specific subroutine. You can find information about that command in the “Serial Script Commands” subsection of the guide. Please note that the command takes a subroutine number; this is denoted by the order that the subroutines appear in the script. The first subroutine will be subroutine number 0, the second subroutine number 1 and so on. The subroutine numbers are also listed at the bottom of the compiled code (which you can see by clicking the “View Complied Code…” button in the “Script” tab of the Maestro Control Center.

Lastly, please note that if you leave your subroutines as-is, it will result in an error when you try to run them by calling the “Restart Script at Subroutine” command because they end with a RETURN command, and the script does not have anywhere to return to. If you want the subroutine to only run once when it is called, you can add a QUIT command before RETURN.

Brandon

OK. So it should be pretty easy. Am I correct, then, that the command I need to get to the Maestro would look exactly like this:

 0xA7, 0x01

in order to run the second subroutine?

Right, [0xA7, 0x01] should restart the Maestro script at your second subroutine. Please note that this is using the compact protocol, which means if you have multiple Maestros connected, they will all respond to that command. Since you mentioned something about adding several more Maestros, you might want to use the Pololu Protocol instead, which allows you to specify that device number of the Maestro you want to respond to the command.

The bytes for the Restart Script at Subroutine command in the Pololu Protocol would be [0xAA, device number, 0x27, subroutine number]. So, if your Maestro had the default device number of 12 and you wanted to start at the second subroutine, the bytes for the Pololu Protocol would be [0xAA, 0x0C, 0x27, 0x01].

Brandon

I have not been able to trigger my Maestro 24.

I am sending a serial command from my system to an Arduino Uno via the Uno’s 10/11 (Rx/Tx) pins, with the intent of the Uno sending a corresponding Hex command sequence to the Maestro. I have a Ground hooked up to the Uno GND pin on the digital side.

  • Uno Pin 0 (RX) is attached to the Maestro TX.
  • Uno Pin 1 (TX) is attached to the Maestro RX.
  • Uno GND on the GND side is attached to Maestro GND.
  • Maestro VIN is not connected.
  • I am running 10V to the servo power block on the Maestro.
  • I have the shorting block on the VSRV=VIN.

I downloaded the Pololu Serial command program and am able to successfully trigger my sequence by sending the appropriate 2 hex commands.

When I send command “2” to the Uno, I see “0xA7,0x01” print in the Serial Monitor.
This is the code I have on my Uno:

#include <SoftwareSerial.h>

const int rxPin = 10; // Define Rx pin for mySerial
const int txPin = 11; // Define Tx pin for mySerial

SoftwareSerial mySerial(rxPin, txPin); // Create a new mySerial instance

void setup() {
  Serial.begin(9600); // Initialize serial communication at 9600 baud
  mySerial.begin(9600); // Initialize mySerial communication at 9600 baud
}

void loop() {
  if (mySerial.available() > 0) { // Check if data is available to read on Serial
    char incomingChar = mySerial.read(); // Read the incoming byte from Serial
    
    // Send the corresponding second command based on the first command received
    switch(incomingChar) {
      case '1':
        Serial.println("0xA7,0x00");
        break;
      case '2':
        Serial.println("0xA7,0x01");
        break;
      case '3':
        Serial.println("0xA7,0x02");
        break;
      case '4':
        Serial.println("0xA7,0x03");
        break;
      case '5':
        Serial.println("0xA7,0x04");
        break;
      case '6':
        Serial.println("0xA7,0x05");
        break;
      case '7':
        Serial.println("0xA7,0x06");
        break;
      case '8':
        Serial.println("0xA7,0x07");
        break;
      case '9':
        Serial.println("0xA7,0x08");
        break;
      case 'A':
        Serial.println("0xA7,0x09");
        break;
      case 'B':
        Serial.println("0xA7,0x0A");
        break;
      case 'C':
        Serial.println("0xA7,0x0B");
        break;
      case 'D':
        Serial.println("0xA7,0x0C");
        break;
      case 'E':
        Serial.println("0xA7,0x0D");
        break;
      case 'F':
        Serial.println("0xA7,0x0E");
        break;
      default:
        // Do nothing if an invalid command is received
        break;
    }
  }
}

What am I doing wrong?

Hello.

It looks like you’re using Serial.print() (which sends ASCII characters for each digit) and have your commands all combined into a single string, including a comma. Instead, could you try using Serial.write() and only send the command bytes, like this?

  case '1':
    Serial.write(0xA7);
    Serial.write(0x00);
  break;

Additionally, you should make sure your Maestro’s serial mode is set to “UART, fixed baud rate” with the baud rate set to 9600. You can do this in the “Serial Settings” tab of the Maestro Control Center.

You could also consider refactoring your code to use our Maestro Servo Controller library for Arduino.

By the way, 10V is pretty high for standard servos, which usually have a 4.8-6V nominal voltage range. You might consider double checking your servo specs to make sure 10V is safe for them.

Brandon

I made the changes below and am not getting a response still from the Maestro.

I dialed down my regulator from 10v to 6v.
I reconfirmed that I have UART, fixed baud rate 9600.

I changed the code to:

#include <SoftwareSerial.h>

const int rxPin = 10; // Define Rx pin for mySerial
const int txPin = 11; // Define Tx pin for mySerial

SoftwareSerial mySerial(rxPin, txPin); // Create a new mySerial instance

void setup() {
  Serial.begin(9600); // Initialize serial communication at 9600 baud
  mySerial.begin(9600); // Initialize mySerial communication at 9600 baud
}

void loop() {
  if (mySerial.available() > 0) { // Check if data is available to read on Serial
    char incomingChar = mySerial.read(); // Read the incoming byte from Serial
    
    // Send the corresponding second command based on the first command received
    switch(incomingChar) {
      case '1':
        Serial.write(0xA7);
        Serial.write(0x00);
        break;
      case '2':
        Serial.write(0xA7);
        Serial.write(0x01);
        break;
      case '3':
        Serial.write(0xA7);
        Serial.write(0x02);
        break;
      case '4':
        Serial.write(0xA7);
        Serial.write(0x03);
        break;
      case '5':
        Serial.write(0xA7);
        Serial.write(0x04);
        break;
      case '6':
        Serial.write(0xA7);
        Serial.write(0x05);
        break;
      case '7':
        Serial.write(0xA7);
        Serial.write(0x06);
        break;
      case '8':
        Serial.write(0xA7);
        Serial.write(0x07);
        break;
      case '9':
        Serial.write(0xA7);
        Serial.write(0x08);
        break;
      case 'A':
        Serial.write(0xA7);
        Serial.write(0x09);
        break;
      case 'B':
        Serial.write(0xA7);
        Serial.write(0x0A);
        break;
      case 'C':
        Serial.write(0xA7);
        Serial.write(0x0B);
        break;
      case 'D':
        Serial.write(0xA7);
        Serial.write(0x0C);
        break;
      case 'E':
        Serial.write(0xA7);
        Serial.write(0x0D);
        break;
      case 'F':
        Serial.write(0xA7);
        Serial.write(0x0E);
        break;
      default:
        // Do nothing if an invalid command is received
        break;
    }
  }
}

In my serial monitor, I see the following when I trigger the Uno now:

ďż˝

This is what I have loaded onto the Maestro:

### Sequence subroutines: ###

# Leia "only hope"
sub Leia_only_hope
  16000 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 0 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # All closed
  19000 4032 7936 frame_0_4 # Open LCD panel
  500 3968 3968 frame_0_4 # All closed
  quit
  return
  
# Mando
sub Mando
  500 3968 3968 3968 3968 3968 3968 
  8000 4736 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # Start -  All closed
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 frame_0..7 # All lower open
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All closed
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 2
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All closed - 2
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 3
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All lower closed - 3
  6000 8000 7936 7168 7789 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 4
  4800 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All lower closed - 4
  500 6720 6848 frame_8_11 # Outside upper open
  200 3968 5440 6912 3968 frame_8..11 # Switch
  200 8000 3968 frame_9_10 # End - All closed
  quit
  return

sub frame_0..23
  23 servo
  22 servo
  21 servo
  20 servo
  19 servo
  18 servo
  17 servo
  16 servo
  15 servo
  14 servo
  13 servo
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0_4
  4 servo
  0 servo
  delay
  return

sub frame_0..7
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0..12
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_8_11
  11 servo
  8 servo
  delay
  return

sub frame_8..11
  11 servo
  10 servo
  9 servo
  8 servo
  delay
  return

sub frame_9_10
  10 servo
  9 servo
  delay
  return

Disregard…the above works!! (I had to disconnect my maestro in order to upload my arduino and forgot to reconnect it).

This is exciting…thank you very much!!

2 Likes

I added an additional sequence to my script, and then added a speed change to the first two sequences. I am now getting a stack overflow/underflow error: 0x0040. What did I do wrong?

### Sequence subroutines: ###

# Leia "only hope"
sub Leia_only_hope
  speed 10  # Set servo speed to 10
  16000 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 0 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # All closed
  19000 4032 7936 frame_0_4 # Open LCD panel
  500 3968 3968 frame_0_4 # All closed
  quit
  return

# Mando
sub Mando
  speed 10  # Set servo speed to 10
  1500 3968 3968 3968 3968 3968 3968 
  8000 4736 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # Start -  All closed
  6000 8000 7872 7168 7808 7680 8000 
  5120 7552 frame_0..7 # All lower open
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All closed
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 2
  5500 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All closed - 2
  6000 8000 7936 7168 7808 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 3
  5500 4032 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All lower closed - 3
  6000 8000 7936 7168 7789 7936 8000 
  5120 8000 0 0 0 0 
  0 frame_0..12 # All lower open - 4
  4800 3968 3968 3968 3968 3968 3968 
  8000 4736 3968 8000 3968 3968 
  6016 frame_0..12 # All lower closed - 4
  700 4032 6720 6848 frame_0_8_11 # Outside upper open
  200 3968 5440 6912 3968 frame_8..11 # Switch
  200 3968 8000 3968 frame_0_9_10 # End - All closed
	  quit
  return

# Short circuit
sub Short_circuit
  100 4032 3968 3968 3968 3968 3968 
  8000 8000 3968 8000 3968 3968 
  6016 4245 0 0 0 0 
  0 0 0 0 0 0 frame_0..23 # Frame 0
  200 7168 7808 frame_2_3 # Frame 1
  200 8000 5874 3968 3968 8000 6532 
  4736 frame_0..3_5..7 # Frame 2
  200 5958 7936 7168 7808 5971 5925 
  5120 8000 0 frame_0..7_13 # Frame 3
  100 4032 3968 3968 3968 3968 3968 
  8000 4736 frame_0..7 # Frame 4
  100 8000 frame_0 # Frame 5
  100 7936 frame_1 # Frame 6
  100 7168 frame_2 # Frame 7
  100 7808 frame_3 # Frame 8
  100 7936 frame_4 # Frame 9
  100 8000 frame_5 # Frame 10
  100 5120 frame_6 # Frame 11
  100 8000 frame_7 # Frame 12
  100 4032 frame_0 # Frame 13
  100 3968 frame_1 # Frame 14
  100 3968 frame_2 # Frame 15
  100 3968 frame_3 # Frame 16
  100 3968 frame_4 # Frame 17
  100 3968 frame_5 # Frame 18
  100 8000 4736 frame_6_7 # Frame 19
  100 8000 5913 7121 5888 7936 6003 
  5120 6336 frame_0..7 # Frame 20
  100 4032 3968 3968 3968 3968 3968 
  8000 4736 frame_0..7 # Frame 21
  quit
  return

sub frame_0..23
  23 servo
  22 servo
  21 servo
  20 servo
  19 servo
  18 servo
  17 servo
  16 servo
  15 servo
  14 servo
  13 servo
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0_4
  4 servo
  0 servo
  delay
  return

sub frame_0..7
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0..12
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0_8_11
  11 servo
  8 servo
  0 servo
  delay
  return

sub frame_8..11
  11 servo
  10 servo
  9 servo
  8 servo
  delay
  return

sub frame_0_9_10
  10 servo
  9 servo
  0 servo
  delay
  return

sub frame_2_3
  3 servo
  2 servo
  delay
  return

sub frame_0..3_5..7
  7 servo
  6 servo
  5 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0..7_13
  13 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0
  0 servo
  delay
  return

sub frame_1
  1 servo
  delay
  return

sub frame_2
  2 servo
  delay
  return

sub frame_3
  3 servo
  delay
  return

sub frame_4
  4 servo
  delay
  return

sub frame_5
  5 servo
  delay
  return

sub frame_6
  6 servo
  delay
  return

sub frame_7
  7 servo
  delay
  return

sub frame_6_7
  7 servo
  6 servo
  delay
  return

It looks like you’re using the wrong syntax for the SPEED command. The SPEED command takes two arguments and sets the speed of the channel specified by the top element of the stack to the value in the second element. So, for example 10 0 speedwould set the speed of channel 0 to 10 and 15 1 speed would set the speed of channel 1 to 15.

It looks like you wanted to set the speed of all of the servo channels, so you would need to call the SPEED command for each of them. You can do this in a more compact way by using a WHILE loop like this:

#Set the speed of all 24 servo channels to 10:

24 begin dup while
dup 1 minus 10 swap speed 
1 minus
repeat

Additionally, please note that all subsequent moves will use the new speed value, even in different sequences. So, you might consider setting the speed back to your normal value at the end of your sequence, or make sure to set the desired speed at the start of each sequence.

Brandon

What would the code for resetting the speed back to normal value look like?

You can use the same WHILE loop in my previous post and just change the 10 to whatever value you want. If you’re not using a speed limit for your other movements, you can set it to 0 to disable the speed limiting.

Brandon