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?
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?
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.
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.
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].
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;
}
}
}
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.
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.
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:
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?
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.
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.