MicroMaestro Serial Problems

Hello,

The project I’m working on is to move two servos with a PlayStation 4 Controller, and I’m having problems with simultaneous serial connections.

I have both servos connected to a MicroMaestro. The Maestro is connected to my computer, and the servos are powered by an external power supply.

I can move the servos normally from the Maestro Control Center.

I also have an Arduino Uno, with a USB Host Shield attached and a Bluetooth dongle plugged into the USB Host Shield.
(GitHub - felis/USB_Host_Shield_2.0: Revision 2.0 of USB Host Library for Arduino.)

The Maestro serial pins are connected to pin 10 (to maestro TX) and pin 11 (to maestro RX) of the Uno board. Vin and Gnd are also connected between the Uno and Maestro.

I am attempting to combine elements of two examples, Your ‘Basic’ Maestro example and USB Host Shield’s ‘PS4BT’ example. I’m sure the problem is something I don’t understand about these serial connections.

Both examples are working independently. Maestro ‘Basic’ moves the servos.

The PS4BT example uses Serial.begin to connect to the serial monitor at 115200. When you move the analog on the ps4 controller, it begins dumping readings instantly to the Serial Monitor.

Now the problem:

When I add the basic Maestro elements into the program, it introduces a delay in the PS4 readings sent to the Serial Monitor. Now when I move the analog, the readings in the Serial Monitor are delayed by approximately 1 second.

The readings also seem to be coming out of a buffer, because they continue for about 1 second after the analog is released. They also seem to come in at the same 9600 baud rate the MaestroSerial connects at.

If I comment out ‘maestroSerial.begin(9600)’, the delay is gone.

If I change ‘Serial.begin’ to connect at 9600 instead of 115200, the delay is gone.

BUT…I know that isn’t the whole issue, because when I combine the parts, the Maestro Control Center throws a Serial Protocol Error (0x0010) and I can no longer control the servos programmatically.

Here is the code. Any help you can offer would be greatly appreciated.

Jared

#include <PololuMaestro.h>
#include <PS4BT.h>
#include <usbhub.h>
#include <SPI.h>
#include <SoftwareSerial.h>


USB Usb;
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so

/* You can create the instance of the PS4BT class in two ways */
// This will start an inquiry and then pair with the PS4 controller - you only have to do this once
// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in pairing mode
//PS4BT PS4(&Btd, PAIR);

// After that you can simply create the instance like so and then press the PS button on the device
PS4BT PS4(&Btd);


SoftwareSerial maestroSerial(10, 11);

// Next, create a Maestro object using the serial port.

MicroMaestro maestro(maestroSerial);

int Xvalue = 1525;
int Yvalue = 1525;


void setup()
{
  Serial.begin(115200);
#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\nPS4 Bluetooth Library Started"));

  // Set the serial baud rate.
  maestroSerial.begin(9600); 
}

void loop()
{
  Usb.Task();

  maestro.setSpeed(0, 0);
  maestro.setAcceleration(0, 0);
  maestro.setSpeed(1, 0);
  maestro.setAcceleration(1, 0);


  if (PS4.connected()) {

    if (PS4.getButtonClick(PS)) { //Shut down PS4 controller
      Serial.print(F("\r\nPS"));
      PS4.disconnect();
    }

    if (PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) { 
      //Serial.print(F("\r\nLeftHatX: "));
      //Serial.print(PS4.getAnalogHat(LeftHatX));
      //Serial.print(F("\tLeftHatY: "));
      //Serial.print(PS4.getAnalogHat(LeftHatY));
      Serial.print(F("\tRightHatX: "));
      Serial.print(PS4.getAnalogHat(RightHatX));
      Serial.print(F("\tRightHatY: "));
      Serial.print(PS4.getAnalogHat(RightHatY));

      Xvalue = map(PS4.getAnalogHat(RightHatX), 0, 255, 5400, 6800); //Map PS4 right analog stick range to acceptable servo min/max
      Yvalue = map(PS4.getAnalogHat(RightHatY), 0, 255, 5400, 6800);

      Serial.print(F("\r\nServoX: "));
      Serial.print(Xvalue);              // Correct values appear in serial monitor for X and Y.
      Serial.print(F("\r\nServoY: "));
      Serial.print(Yvalue);


      //maestro.setTarget(0, Xvalue); // This doesn't work, I don't know why.
      //maestro.setTarget(1, Yvalue);


    }
  }
}

This is most likely the problem.

I found this on the GitHub - felis/USB_Host_Shield_2.0: Revision 2.0 of USB Host Library for Arduino. page:

Interface modifications

The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board.

Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else than SPI communication!

Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively.

Can the MicroMaestro use different SoftSerial pins?

Maybe I should use a different board with more than one hardware serial?

Jared

Hello, Jared.

That definitely seems like it could be causing the problem and is a good place to start. The limitation on which pins you can use for software serial comes from your Arduino (not the Maestro). It sounds like you are using an Arduino Uno; if that is the case, then you should be able to use any of its I/O pins with software serial.

Brandon

Hi Brandon,

Thanks for the help. I’m still getting a strange delay in the response of the Maestro.

The project is to use a PS4 gamepad to control the eyes (and eventually more) in an animatronic baby for a movie.

I changed the MicroMaestro software serial to 6 and 7, and eliminated the PS4 serial monitor stuff, so Maestro is the only serial connection.

I’ve simplified the code as much as I can to eliminate possibilities. However, I’m still getting an unusable delay between the movement of the control and the servo.

Here is a video demonstrating the problem:

https://youtube.com/shorts/gbCcAhdHk4o

The Arduino responds to the PS4 controller nearly instantly when the Maestro serial calls are removed.

Do you see anything in this code that would cause this delay?


#include <PololuMaestro.h>
#include <PS4BT.h>
#include <usbhub.h>
#include <SPI.h>
#include <SoftwareSerial.h>


USB Usb;
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
PS4BT PS4(&Btd); // After that you can simply create the instance like so and then press the PS button on the device


SoftwareSerial maestroSerial(6, 7);
MicroMaestro maestro(maestroSerial);

int Xvalue = 6100;
int Yvalue = 6100;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  
  if (Usb.Init() == -1) {
   while (1); // Halt
  }
  digitalWrite(LED_BUILTIN, HIGH); //Use built in led to indicate successful starting of PS4 Bluetooth Library
  
  // Set the serial baud rate.
  maestroSerial.begin(9600);
}

void loop()
{
  Usb.Task();

  maestro.setSpeed(0, 0);
  maestro.setAcceleration(0, 8);
  maestro.setSpeed(1, 0);
  maestro.setAcceleration(1, 8);


  if (PS4.connected()) {

    if (PS4.getButtonClick(PS)) { //Shut down PS4 controller
      PS4.disconnect();
    }

    if (PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) { 
      Xvalue = map(PS4.getAnalogHat(RightHatX), 0, 255, 5400, 6800); //Map PS4 right analog stick range to acceptable servo min/max
      Yvalue = map(PS4.getAnalogHat(RightHatY), 0, 255, 6800, 5400);
      maestro.setTarget(0, Xvalue); // Servo movements are delayed by .5 sec to 1 sec after analog movement.
      maestro.setTarget(1, Yvalue);


    }
  }
}

Thank you for posting a video and your code. I am not seeing anything obviously problematic in your code that would cause that delay. Since the acceleration and speed are not changing, those commands only need to be sent once instead of every loop. So, you could try moving the setSpeed() and setAcceleration() commands to the end of setup() as well as increasing the baud rate (up to 115200) to see if those things make a difference.

In general software serial might incur some overhead, or it could be interacting with some of the other hardware or libraries you are using, but it is difficult to say for sure since I am not very familiar with that hardware and do not have it here to test. You might try testing it by turning on and off an LED at certain points in the main loop; if you find a segment that, when surrounded by the LED code, keeps the LED lit most of the time, that indicates the code is spending a lot of time in that segment (even better would be toggling different free I/O pins and looking at it with a scope).

Brandon

1 Like

Thanks Brandon,

Increasing the baud rate to 115200 mostly eliminated the delay. Now it’s much more usable.

Thanks for the help, and I really like the idea of troubleshooting the loop using leds. Even If I don’t use that trick this time, I’m sure it will come in useful in the future.

Thanks again,

Jared

2 Likes