Controlling two maestros, one arduino

Hi, I saw something similar asked but the answer seemed really complicated… I’m not very good at programming but basically the code I came up with has 2 lines naming the softwareserial on my arduino, I have maestro1 set to 9600 baud and maestro2 to 19200. I’m still waiting on my second maestro to arrive but from testing with the one this seems to work. Is this an OK way to do this? Will it cause issues or can I send commands to them like this and be fine?

Hello.

You could use a separate serial line for each Maestro, but it would probably be simpler to control both Maestros from a single serial line by giving them unique device numbers.

Below this paragraph, I made some quick modifications to the “Basic.ino” example from our Maestro Arduino library that you can use as a reference. To use this method, you would set each Maestro’s serial mode to UART, fixed baud and set it to 9600, then configure the first Maestro with a device number of 12 and the second with a device number of 13. You can make those modifications from the “Serial Settings” tab of the Maestro Control Center.

#include <PololuMaestro.h>
#include <SoftwareSerial.h>

  SoftwareSerial maestroSerial(10, 11);

static const uint8_t noResetPin = 255; //tells the library you aren't using the reset pin

// Uncomment the lines that are relevant for the Maestros you are using

//MicroMaestro maestro1(maestroSerial, noResetPin, 12);
  MiniMaestro maestro1(maestroSerial, noResetPin, 12);

//MicroMaestro maestro2(maestroSerial, noResetPin, 13);
  MiniMaestro maestro2(maestroSerial, noResetPin, 13);

void setup()
{
  maestroSerial.begin(9600);
}

void loop()
{
  // Set the target of channel 0 on Maestro 1 to 1000 us
  maestro1.setTarget(0, 4000);
  // Set the target of channel 0 on Maestro 2 to 2000 us
  maestro2.setTarget(0, 8000);
  // Wait 2 seconds
  delay(2000);

  // Set the target of channel 0 on Maestro 1 to 2000 us
  maestro1.setTarget(0, 8000);
  // Set the target of channel 0 on Maestro 2 to 1000 us
  maestro2.setTarget(0, 4000);
  // Wait 2 seconds
  delay(2000);
}

You can refer to the “Daisy Chaining” section of the Maestro user’s guide for connection information.

By the way, if you decide to use two separate serial lines, you do not need to use different baud rates.

Brandon

Hey Brandon, thanks for the response. The reason why I thought it was best to use seperate baud rates and not daisy chain them is because my arduino sketch activates sequences by number, like button1 does restartmaestro(0) so I figured if they were chained or used the same baud rate then if I restarted script 0 for one maestro would it not activate that sequence on both boards instead of the one? Sorry if that was confusing lol.

Hello.

When you daisy chain the Maestro controllers, you can address them individually by assigning them different device numbers as I mentioned in my first post. As shown in my code example, the device number is assigned to the object. For example, MiniMaestro maestro1(maestroSerial, 12); sets the device number for the maestro1 object to 12. So, any commands sent using the maestro1 object will only be responded to by Maestros with the device number set to 12, any other Maestros in the chain with a device number other than 12 will receive the command but ignore it.

Brandon

Ohhhh well that makes perfect sense! Alright I’ll give it a try after work thank you!

Yeahhhhh that doesnt work sorry , maybe i’m just missing something but the commands only seem to activate on one maestro and not the chained one. I changed the code to match your example, changed the baud rates to the same, hooked my arduino tx pin to the first maestros rx, then the tx from that maestro to the txin to the second. The second one isnt recieving any commands. Im going to post my whole sketch, i hope its not too long

MiniMaestro maestroBody(maestroSerial, 12);
MiniMaestro maestroDome(maestroSerial, 13);//software serial
//MiniMaestro domesserial(domeSerial);

/////////////////////////////////////////////////////////////////
Sabertooth Sabertooth2x(128, Serial1);
Sabertooth Syren10(128, Serial2);

// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif

// Set some defaults for start up
// false = drive motors off ( right stick disabled ) at start
boolean isDriveEnabled = false;

// Automated functionality
// Used as a boolean to turn on/off automated functions like periodic random sounds and periodic dome turns
boolean isInAutomationMode = false;
unsigned long automateMillis = 0;
// Action number used to randomly choose a sound effect or a dome turn
byte automateAction = 0;


int driveThrottle = 0;
int throttleStickValue = 0;
int domeThrottle = 0;
int turnThrottle = 0;


boolean firstLoadOnConnect = false;

AnalogHatEnum throttleAxis;
AnalogHatEnum turnAxis;
AnalogHatEnum domeAxis;

ButtonEnum speedSelectButton;
ButtonEnum hpLightToggleButton;



boolean isHPOn = false;

//#define SFX_TX 5
//#define SFX_RX 6
#define SFX_RST 4
// software serial enable
//SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
// Hardware serial enable
Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial3, NULL, SFX_RST);

//Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
//MP3Trigger mp3Trigger;
USB Usb;
XBOXRECV Xbox(&Usb);

void setup() {
  //ss.begin(9600);
  Serial3.begin(9600);
  Serial1.begin(SABERTOOTHBAUDRATE);
  Serial2.begin(DOMEBAUDRATE);
  //Serial3.begin(9600); //start serial3 for the body Maestro
  maestroSerial.begin(9600);
 // domeSerial.begin(19200);

#if defined(SYRENSIMPLE)
  Syren10.motor(0);
#else
  Syren10.autobaud();
#endif

  Sabertooth2x.autobaud();
  // The Sabertooth won't act on mixed mode packet serial commands until
  // it has received power levels for BOTH throttle and turning, since it
  // mixes the two together to get diff-drive power levels for both motors.
  Sabertooth2x.drive(0);
  Sabertooth2x.turn(0);


  Sabertooth2x.setTimeout(950);
  Syren10.setTimeout(950);

  pinMode(EXTINGUISHERPIN, OUTPUT);
  digitalWrite(EXTINGUISHERPIN, HIGH);

  //mp3Trigger.setup();
  //mp3Trigger.setVolume(vol);

  
  if(isLeftStickDrive) {
    throttleAxis = LeftHatY;
    turnAxis = LeftHatX;
    domeAxis = RightHatX;
   
    speedSelectButton = L3;
    hpLightToggleButton = R3;

  } else {
    throttleAxis = RightHatY;
    turnAxis = RightHatX;
    domeAxis = LeftHatX;
    
    speedSelectButton = L3;
    hpLightToggleButton = R3;
  }


 // Start I2C Bus. The body is the master.
  Wire.begin();

//  Serial.begin(9600);
  // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
  while (!Serial);
  if (Usb.Init() == -1) {
    //Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
 // Serial.print(F("\r\nXbox Wireless Receiver Library Started"));
}


void loop() {
  Usb.Task();
  // if we're not connected, return so we don't bother doing anything else.
  // set all movement to 0 so if we lose connection we don't have a runaway droid!
  // a restraining bolt and jawa droid caller won't save us here!
  if (!Xbox.XboxReceiverConnected || !Xbox.Xbox360Connected[0]) {
    Sabertooth2x.drive(0);
    Sabertooth2x.turn(0);
    Syren10.motor(1, 0);
    firstLoadOnConnect = false;
    return;
  }

  // After the controller connects, Blink all the LEDs so we know drives are disengaged at start
  if (!firstLoadOnConnect) {
    firstLoadOnConnect = true;
   sfx.playTrack("START   OGG");
    Xbox.setLedMode(ROTATING, 0);
  }
 
  if (Xbox.getButtonClick(XBOX, 0)) {
    if(Xbox.getButtonPress(L1, 0) && Xbox.getButtonPress(R1, 0)){
      Xbox.disconnect(0);
    }
  }

  // enable / disable right stick (droid movement) & play a sound to signal motor state
  if (Xbox.getButtonClick(START, 0)) {
    if (isDriveEnabled) {
      isDriveEnabled = false;
      Xbox.setLedMode(ROTATING, 0);
      sfx.playTrack("WILHELM OGG");
      Serial.println ("Start pressed");
    } else {
      isDriveEnabled = true;
      sfx.playTrack("VADER   OGG");
       Serial.println ("Start pressed");
      // //When the drive is enabled, set our LED accordingly to indicate speed
      if (drivespeed == DRIVESPEED1) {
        Xbox.setLedOn(LED1, 0);
      } else if (drivespeed == DRIVESPEED2 && (DRIVESPEED3 != 0)) {
        Xbox.setLedOn(LED2, 0);
      } else {
        Xbox.setLedOn(LED3, 0);
      }
    }
  }

  //Toggle automation mode with the BACK button
  if (Xbox.getButtonClick(BACK, 0)) {
    if (isInAutomationMode) {
      isInAutomationMode = false;
      automateAction = 0;
      sfx.playTrack("AUTOF   OGG");
       Serial.println ("Back button pressed");
    } else {
      isInAutomationMode = true;
      sfx.playTrack("AUTOT   OGG");
       Serial.println ("Back button pressed");
    }
  }


// Plays a random track from sfx.playTrack when in automation mode
if (isInAutomationMode) {
  unsigned long currentMillis = millis();

  if (currentMillis - automateMillis > (automateDelay * 1000)) {
  automateMillis = millis();
  automateAction = random(1, 12); // Change the upper limit to match the number of tracks you have

  if (automateAction == 1) {
    sfx.playTrack("AcrostarOGG");
  }
  else if (automateAction == 2) {
    sfx.playTrack("SCREAM   OGG"); // Replace TRACK2.OGG with the name of your second track
  }
  else if (automateAction == 3) {
    sfx.playTrack("LAUGH1  OGG"); // Replace TRACK3.OGG with the name of your third track
  }
  else if (automateAction == 4) {
    sfx.playTrack("SPEED   OGG"); // Replace TRACK4.OGG with the name of your fourth track
  }
  else if (automateAction == 5) {
    sfx.playTrack("START   OGG"); // Replace TRACK5.OGG with the name of your fifth track
  }
  else if (automateAction == 6) {
    sfx.playTrack("DOODOO  OGG"); // Replace TRACK2.OGG with the name of your second track
  }
  else if (automateAction == 7) {
    sfx.playTrack("WOLFWSTLOGG"); 
  }
  else if (automateAction == 8) {
    sfx.playTrack("SHORTCKTOGG"); 
  }
  else if (automateAction == 9) {
    sfx.playTrack("LEIA123 OGG"); 
  }
  else if (automateAction == 10) {
    sfx.playTrack("SENT1   OGG"); 
  }    
  else if (automateAction == 11) {
    sfx.playTrack("FART1   OGG"); 
  }


      //if (automateAction < 4) {
#if defined(SYRENSIMPLE)
        Syren10.motor(turnDirection);
#else
        Syren10.motor(1, turnDirection);
#endif

        delay(750);

#if defined(SYRENSIMPLE)
        Syren10.motor(0);
#else
        Syren10.motor(1, 0);
#endif

        if (turnDirection > 0) {
          turnDirection = -45;
        } else {
          turnDirection = 45;
        }
      }

      // sets the mix, max seconds between automation actions - sounds and dome movement
      automateDelay = random(3,10);
    }
  

  // Maestro Body Panels
  
  if (Xbox.getButtonClick(UP, 0)) {
    if (Xbox.getButtonPress(R1, 0)) {
     maestroBody.restartScript(1);
      }
    }
  
  if (Xbox.getButtonClick(DOWN, 0)) {
    if (Xbox.getButtonPress(R1, 0)) {
      maestroBody.restartScript(0);
      }
    }
   

  if (Xbox.getButtonClick(UP, 0)) {
    if (Xbox.getButtonPress(L1, 0)) {
      
    }
  }
  if (Xbox.getButtonClick(DOWN, 0)) {
    if (Xbox.getButtonPress(L1, 0)) {
      
    }
  }

//Maestro Dome Panels

if (Xbox.getButtonPress(R2, 0)) {
    if (Xbox.getButtonPress(UP, 0)) {
     maestroDome.restartScript(0);
     
    } 
  }

if (Xbox.getButtonPress(R2, 0)) {
    if (Xbox.getButtonPress(RIGHT, 0)) {
     maestroDome.restartScript(2);
     
    } 
  }
if (Xbox.getButtonPress(R2, 0)) {
    if (Xbox.getButtonPress(DOWN, 0)) {
     maestroDome.restartScript(1);
     
    } 
  }

Ok after reading someone elses post i think i got it! I needed to make a special connector to split the same arduino pin to both rx pins and add the 255 no reset value when naming the maestros. Thanks for the help, much appreciated!

1 Like

I am glad to hear you got it working! Thank you for letting us know. Sorry for the confusion; you are right, my example should have included a declaration for the reset pin (I have corrected it now for future reference).

Brandon