Reading identifier from Mini Maestro

Hello!

I’m working on a project that involves a using a large number of 24 channel Mini Maestros to drive a large grid of servos. There will be 24 of them for a total of 576 servos. They will need to be daisy chained together, and I’ll probably split it into two or more chains to improve performance, with masters connected to a Raspberry Pi via USB. I’m writing a program in C++ that will control all of these chains simultaneously. That program runs on both OSX and Raspbian, for ease of development.

I have four Mini Maestros to test with at the moment, and one problem I’m encountering during development is that it’s not very easy to tell which device is which. On OSX, they get predictable names like /dev/cu.usbmodem00xxxxx1, where the name is based on the serial number. However, on Raspbian, they get mounted at /dev/ttyACMx. I imagine they’re likely to get mounted in a random order, so I can’t be sure that ACM0 is really the first Maestro in my sequence.

So here’s the question: is it possible for my program to ask each Maestro for either its serial number or its address? I see there’s c# code here that can talk directly to the Maestro to get this information:

Unfortunately, it requires libusb, and that seems to be a bit of a nuisance to set up for C++ on OSX.

It’d be great if there were an undocumented command that returns this information, but I bet there isn’t! Is there any other way to do it? For example, could I put a script on the Maestros that outputs the device number and read that back on the computer?

Hello.

It sounds like you are using serial commands to control your Maestros from your Raspberry Pi and Mac computer. If so, there is no serial command for getting the serial number from a Maestro, but as you already discovered, you can get that data via the Maestro’s native USB interface using the Pololu USB SDK.

One way to predictably talk to each Maestro individually is to assign your Maestro units different Device Numbers and use the Pololu protocol (or Mini SSC protocol). You can find more information about the Device Number setting under the “Serial Settings” section in the Maestro user’s guide. If you have access to a Linux or Windows computer, it would be easier to configure that setting using the Maestro Control Center under the “Status” tab. Alternatively, you can use the command-line utility, UscCmd, to read the Maestro’s setting into a specified file with its “–getconf” option. Then, in the file modify the “SerialDeviceNumber” field, save, and load the new configurations on to the Maestro using the UscCmd’s “–configure” option. (For more details on how the UscCmd works, see its source code.)

By the way, your project sounds interesting and ambitious! Can you share more details about it?

- Amanda

You’re right, I’m sending serial commands over USB.

I have indeed set up all of my test Maestros with different device numbers, from 12 to 15. The tricky bit is that if I have two separate chains, I can’t be sure which numbers are on which chain. For example, if I write my code to assume that 12 and 13 are on /dev/ttyACM0 and 14 and 15 are on /dev/ttyACM2, it won’t work if the OS subsequently decides to mount Maestro number 14 on ttyACM0. I wanted to automatically detect the arrangement of the devices so that it works in any order.

I’m reaching a bit here, but I noticed that in the scripting reference, there’s a SERIAL_SEND_BYTE command which is intended to control further devices by sending commands out of the TX line. Would it be possible to write a script that uses that to send the device number (hardcoded in the script) back to the computer, then read the bytes back in the same way as I would for the GetErrrors command?

The finished piece will be a kind of big video screen formed by a grid of discs turned by servos. The discs will have a gradient pattern on them so that as they rotate, their visible part will show a lighter or darker shade of grey. My program will turn them to appropriate angles to display (very low resolution!) video, animations and pictures. We made one five years ago using different technology and it was rather slow, updating at one frame per second… I’m hoping this one will be able to run ten times faster!

I think I’ve figured out a solution. I can just open every likely-looking serial port and send, for example, the GetErrors command to every possible device number in turn and see which ones respond. I’ll give that a try tomorrow.

Thanks for your advice!

Hello.

On Linux (e.g. Raspbian), I think it would be simpler to access the Maestros’ serial ports using the entries found in /dev/serial/by-id/. Those entries include the name of the corresponding Maestro and its USB serial number, so they will be stable. Each entry is a symbolic link, so you can run ls -l /dev/serial/by-id to see the correspondence between those names and the /dev/ttyACM* names. This way, there is no need for extra code that detects Maestros, and there is no risk of sending invalid bytes to some other serial device connected to your Linux system.

–David

Fantastic, that does the job nicely! Thank you.

One further question while I’m writing automatic device discovery code:

As far as I can tell, on OSX, the device names are always /dev/cu.usbmodem, followed by the serial number with the last digit replaced with either 1 for the command port or 3 for the data port. So, for example, if I have a Mini Maestro with serial number 00123456, its ports will be /dev/cu.usbmodem00123451 and /dev/cu.usbmodem00123453.

The four Maestros I have so far are numbered 00187182, 00187250, 00187266 and 00187272, so each of them gets predictable names ending in 1 and 3. But what happens if I get two Mini Maestros whose serial numbers differ only by the last digit? Does it relocate one to a different number, or use something other than 1 and 3 for the last digit, or just fail to mount?

Hello.

I programmed two Wixels to have USB descriptors somewhat similar to the Maestro, while having Maestro-style serial numbers that only differed in the last digit, so I could test this out on a macOS computer here. If there is a serial port naming conflict, the second device plugged in seems to get assigned a port name of the form /dev/cu.usbmodem followed by an arbitrary decimal number. The arbitrary number seems to start at 0 when the computer starts up and increases whenever a USB CDC ACM device is plugged in. I didn’t do enough testing to know if it increments once for every CDC ACM interface it sees or just once for every USB device with CDC ACM interfaces, but it’s probably the former.

If you happen to have two Maestros whose serial numbers only differ in the last digit, this behavior by macOS could be a problem. In that case, you might want to compile and run the lsport example from libusbp, which prints out the names of all of the USB serial ports along with identifying information about the USB device it belongs to. It might be useful to use the lsport program so that it creates symbolic links similar to the ones created automatically by Linux in /dev/serial/by-id.

–David

Ah, that’s more or less what I expected! I think I’ll work around that problem the simple way for now, just by using Maestros with non-clashing numbers as the masters.

Thanks for the libusbp link, that sounds really useful. I’ll take a look, and maybe it’ll help to make things more robust when I get around to cleaning up this code and making it open source.