Reading analog input over USB (micro maestro)

I would like to use the micro maestro as a simple analog input for my computer, but I am having trouble finding out how to read a servo position or access the analog input with the USB interface.

Starting from some code that carrotSnack posted earlier [libusb] linux/windows set position with unmanaged C++ I have my micro maestro up and running on my mac. I have no issues updating positions, but I have been unable to find any examples of reading the analog inputs over USB. I see lots of examples of how to do this in a script, but I would like to be able to read this value over USB. It looks like the serial commands of COMMAND_GET_POSITION would not work over USB because of the way the value is returned. Does REQUEST_GET_SERVO_SETTINGS return the position, or does it just have the channel settings?

It seems like there must be an easy way to do this, but I am obviously missing it. I think there should be a command called REQUEST_GET_POSITION but it does not exist. What is the best way to read the value of channel 5 over USB?

Thanks for your help,

Chris

For the Micro Maestro, you can use the REQUEST_GET_VARIABLES USB control transfer to get all the variables, including the positions of all the channels. Fore more information, see the getVariablesMicroMaestro function in the Usc class in the Pololu USB SDK.

If your computer is good enough to run mono C# programs, you could just download the Pololu USB SDK, compile UscCmd, and run UscCmd --status. That command will print out all the variables, including the positions of all the channels.

–David

Thank you, I think that will get me on track. I am going to have to use either C or C++ based on my system, and I will let you know how it ends up.

From what I understand now, the data that I get from REQUEST_GET_VARIABLES will be the stuct uscVariables described in protocol.h that includes the information on all 6 servos as an array of struct servoSetting[].

That makes sense to me know.

-Chris

I got a follow up question about this, so here is a short piece of code that I used poll the analog input over USB.
I did have one issue where the variables appeared to be offset from the correct locations in the uscVariables struct, and I just pulled them out manually

retVal = libusb_control_transfer(device_handle, 0xC0, REQUEST_GET_VARIABLES, 0, 0, (unsigned char*)&tmp, (ushort)sizeof(uscVariables), (ushort)5000);

printf("%5u\n", tmp[64]);

where tmp was an appropriately sized buffer and tmp[64] corresponds to the analog channel 4.
The mechanics of the command are straight forward, but not what I expected. Instead of getting a return variable you give the USB system a buffer that it fills with the requested data. The retVal is the size returned.
Using this code with libusb-1.0 I have been able to poll the analog input at a few kHz with a small arm based computer.

Hi, could you give me your code ? I’m trying to retreive servo positions but it doesn’t work, retVal give me 8 and my array is empty, maybe a pointer issue…

You can get a zip my code here: https://www.dropbox.com/s/ga9je2sjrbess5m/maestroReadWriteExample.zip

main.cpp is an example for reading the analog value of one channel.
main_original was a program I used to test writing to a servo channel.

I don’t claim that either of these programs is good, but they do work. The writing program is especially inefficient because if searches the entire usb tree each time you send a position :confused: .

Please note that you should setup the maestro using the pololu supplied program to set the channel input/output before you use this.

I am also not sure what your goal is.

You can’t read the actual position of the servo. At best this would return the last command you sent for the servo, which you should probably know already. Servos are generally considered to be a closed loop control mechanism when viewed from outside the black box because the PID controller is built in.

If you need to actually measure the current servo position you would need something like this http://www.adafruit.com/products/1404 This servo has the position broken out so that you can read it externally and verify that it went where you want.

On a side note: Reading from the maestro worked fine, but I ended up moving the whole project to an ATMega microcontroller because after a few hours of constant analog reads the micro maestro would always drop off and I would get a seg-fault in the program. The microcontroller solution is much more robust, and removes the computer requirement.

Yes the idea was to get the initial position when powering the maestro but in fact the servos go to aother position when connected…
But I also want to read analog input voltages, thank you for the code I will try again.

I see you commented the code using structure instead of unsigned shorts, didn’t it work ?
I am getting some numbers in my short list but don’t see something understandable, and using the structure it doesn’t seems to mach :frowning:

I don’t remember exactly what the problem was, but I do remember having a problem with the structure. I ended up writing a program that displayed the value of each byte of the returned data. Then I could easily ground some channels and apply voltage to one and see what changes.

I never tried to reconcile this issue, and instead just found the values that I tested to work.

My best guess is that the issue comes from different variable sizes on different machines. I was doing this all on a RPi and some of the variables may have different sizes on the different systems. sizeof(unsigned int) isn’t guaranteed.

I use it on a rpi too, I think I will also search for a changing value to see where are the one I need.
There’s on thing I don’t understand, in protocol.h inside the uscVariables structure there’s a servoSetting array supposed to receive the values for each servo, but its size is of 6, I wonder if it is just not suitable for more than 6 servos, it’s strange…

I only tried working with the 6-channel micro maestro, so I am not sure, but the example programs they provide should work with both so you can check there.

I tried and tried again but I found no way to get the input value also I tried the “Cross-platform C” example here: https://www.pololu.com/docs/0J40/all#5.h.1 and it’s really simpler… and works ! (for those with the same problem than me)