Maestro serial control with Arduino & USB Shield

I’m trying to control a Micro Maestro servo controller via serial from an Arduino Uno that also has a USB host shield. The ‘Basic’ example provided by Pololu works fine. But when I initialize the USB host, the serial communication to the Maestro stops working. The USB seems to work fine. I’m communicating to the Pololu serial pins from channels 10, 11 just like in the example and nothing else is connected to the board. This code is added to the Pololu ‘Basic’ example to include the USB libraries:

#include <XBOXRECV.h> USB Usb; XBOXRECV Xbox(&Usb);

With just that, it compiles fine. But when I initialize the USB with this command, the Maestro stops responding (or the Arduino has stopped sending commands, not sure which):

if (Usb.Init() == -1) { while(1); }

I’ve tested it with these lines commented out and it works fine. As soon as Usb.Init is called, the serial to the Maestro stops working. I realize an infinite loop is created if the Usb.init fails, but that is not happening. I can still see commands from the virtual com port over the USB connection to the computer after this point in the code, and I can get the inputs from the Xbox controller, I just can’t seem to talk to the Maestro and read the USB at the same time. I’d greatly appreciate any suggestions.
Thanks,
Jason

Hello, Jason.

It sounds like you are using the Arduino USB Host Shield. It is likely that the USB host shield library is using the same pin(s) as the Maestro’s Arduino library. It will probably be easier for you to change the RX and TX pins for the SoftwareSerial object that defines the UART pins between your Maestro and Arduino in the code. To do that, change the parameters for RX and TX of maestroSerial in the conditional preprocessing block (near the top in each of the Maestro Arduino examples) to another set of pins on your Arduino that are not in use:

...
#else
  #include <SoftwareSerial.h>
  SoftwareSerial maestroSerial(10, 11);	// change RX and TX pin values
#endif

- Amanda

Hello, I have a similar question.

I am using the circuits@home usb 2.0 host shield and the 6ch micro maestro with an Arduino UNO. A while back I had a servo controlled via some switches. I thought it would be fun to get rid of the breadboard switches and use the xbox360 usb controller I have laying around. Not being the most competent when it comes to microcontrollers, I have been gradually increasing the complexity of my system.

I can load the example code from the USB host shield library to use the xbox controller no problem, even when the micro maestro is included in the system. Vice versa works too; I can run my old code even if the USB shield is connected.

However, when I modify the example code to have a button press move the servo, it never moves. Sometimes, but not always, the red light appears on the maestro. Using the serial monitor, I can confirm that the button was pushed, and what the expected servo position should be. I have tried changing up my RX/TX connections with little luck. The host shield is only using pins 9 and 10. Originally I had the maestro hooked up to 5 and 11 using the SoftwareSerial object, but testing with 1 and 0 did not help either.

The modified sample program is below. Any thoughts? Note: Most of the code is irrelevant, copied from the example program to test the functions of the game controller. Down toward the bottom I have the buttonclick for the x button call a “xbutton” function.

#include <XBOXUSB.h>

#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif

USB Usb;
XBOXUSB Xbox(&Usb);

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

SoftwareSerial maestroSerial(5,11);

MicroMaestro maestro(maestroSerial);

//code for random angle generation
int ypos;
int ynew;

void setup() {

  Serial.begin(9600);
  maestroSerial.begin(9600); 
  ypos = random(3200,8000);

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

  Usb.Task();
  if (Xbox.Xbox360Connected) {
    if (Xbox.getButtonPress(L2) || Xbox.getButtonPress(R2)) {
      Serial.print("L2: ");
      Serial.print(Xbox.getButtonPress(L2));
      Serial.print("\tR2: ");
      Serial.println(Xbox.getButtonPress(R2));
      Xbox.setRumbleOn(Xbox.getButtonPress(L2), Xbox.getButtonPress(R2));
    } else
      Xbox.setRumbleOn(0, 0);

    if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
      if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {
        Serial.print(F("LeftHatX: "));
        Serial.print(Xbox.getAnalogHat(LeftHatX));
        Serial.print("\t");
      }
      if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {
        Serial.print(F("LeftHatY: "));
        Serial.print(Xbox.getAnalogHat(LeftHatY));
        Serial.print("\t");
      }
      if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {
        Serial.print(F("RightHatX: "));
        Serial.print(Xbox.getAnalogHat(RightHatX));
        Serial.print("\t");
      }
      if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
        Serial.print(F("RightHatY: "));
        Serial.print(Xbox.getAnalogHat(RightHatY));
      }
      Serial.println();
    }

    if (Xbox.getButtonClick(UP)) {
      Xbox.setLedOn(LED1);
      Serial.println(F("Up"));
    }
    if (Xbox.getButtonClick(DOWN)) {
      Xbox.setLedOn(LED4);
      Serial.println(F("Down"));
    }
    if (Xbox.getButtonClick(LEFT)) {
      Xbox.setLedOn(LED3);
      Serial.println(F("Left"));
    }
    if (Xbox.getButtonClick(RIGHT)) {
      Xbox.setLedOn(LED2);
      Serial.println(F("Right"));
    }

    if (Xbox.getButtonClick(START)) {
      Xbox.setLedMode(ALTERNATING);
      Serial.println(F("Start"));
    }
    if (Xbox.getButtonClick(BACK)) {
      Xbox.setLedBlink(ALL);
      Serial.println(F("Back"));
    }
    if (Xbox.getButtonClick(L3))
      Serial.println(F("L3"));
    if (Xbox.getButtonClick(R3))
      Serial.println(F("R3"));

    if (Xbox.getButtonClick(L1))
      Serial.println(F("L1"));
    if (Xbox.getButtonClick(R1))
      Serial.println(F("R1"));
    if (Xbox.getButtonClick(XBOX)) {
      Xbox.setLedMode(ROTATING);
      Serial.println(F("Xbox"));
    }

    if (Xbox.getButtonClick(A))
      Serial.println(F("A"));
    if (Xbox.getButtonClick(B))
      Serial.println(F("B"));
    if (Xbox.getButtonClick(X))    { 
      Serial.println(F("X"));
      xbutton();}
    if (Xbox.getButtonClick(Y))    
      Serial.println(F("Y"));
  }
  delay(1);
}

//x button runs random code 
void xbutton(){
       Serial.println(" Random Swing ON ");
      ynew = random(3200,8000);
      if(ypos != ynew) {          //if current and new positions differ
        ypos = ynew;              //then change ypos value to new
        maestro.setTarget(1,ypos); //and move servo to that position
        Serial.print(ypos);
        Serial.println(" degrees");
        delay (500);
}


}

Thanks,
Mike

Hello, Mike.

I looked at your code briefly and did not notice anything obviously wrong. What code example are you talking about? Can you verify that the connections between your Arduino and Maestro are working and that you are able to move the servo connected to the Maestro by running Basic.ino? If you run into problems when trying to run Basic.ino, can you check the Maestro’s settings to see if they are like the settings described in the comments near the top of the example? Can you take pictures of your setup that clearly show all your connections and post them here?

- Amanda

Hi Amanda,

Thank you for taking the time to look over the code. The bulk of it is an example xbox controller sketch from the usb host shield 2.0 library. I have no problems running basic.ino, and I can get the servo to move with the maestro.setTarget commands that I call from the xbutton function. When I try to merge the two (as in the code posted above), the code executes properly (AFAIK, judging from the serial monitor) but the servo does not move, and (usually) the red light goes on. The host shield is mounted directly on to the Arduino UNO, and the maestro is connected via pins 5 and 11.

Could there be an issue with using serial commands at the same time communicating with the xbox controller over USB? I think I will try commenting those parts out and test it.

Also, I mentioned in my first post that I tried connecting the maestro to pins 0 and 1 as well, but I’m not sure if I did that correctly. I used the same code above, except

SoftwareSerial maestroSerial(5,11);

became

SoftwareSerial maestroSerial(1,0);

Is it necessary to use SoftwareSerial when using the predefined RX and TX pins on the UNO? If not, how would this portion change?

SoftwareSerial maestroSerial(5,11);
MicroMaestro maestro(maestroSerial);

Thanks,
Mike

I looked at your code again and (just) realized that you are using the Arduino’s SPI library. It looks like MOSI on the Arduino Uno’s ICSP header shares pin 11, which is probably causing a conflict with the PololuMaestro library (since TX is defined as pin 11). For more information about the Arduino’s SPI library, see the “SPI library” page on the Arduino website. Can you try using a different pin for TX, redefining the TX parameter for the object maestroSerial, and running your code again to see if that helps?

As for your questions about using the Arduino Uno’s pins 0 and 1 (or UART), it is not necessary to use the Arduino’s SoftwareSerial library if you are using a hardware serial port. (The Arduino’s SoftwareSerial library was created to allow serial communication on other digital pins if there are limited hardware serial ports available.) We do not recommend using the Uno’s hardware serial port because those pins are used by the Arduino IDE’s Serial Monitor and for programming your board. It would be best to use another pin on your Uno that is not being used anywhere else in your code, including libraries.

- Amanda

Hi Amanda,

That sounds like a very likely culprit! I will change TX to a pin not in conflict with the SPI library (or anywhere else). I will test that out this weekend and get back to you.

Thanks!
Mike

Amanda,

Yup, that fixed it!
I see where I was confused. The specs for the shield say it uses pins 9 and 10 for INT and SS interface signals in its default configuration, but when coupled with the Ardunio UNO, the SPI signals are routed to pins 11-13 (along with the ICSP), so anything connected to those pins will interfere with the SPI. Thanks for clearing that up for me.

Now its time to really beef up this code!
Best regards,
Mike

2 Likes