Raspberry Pi and Maestro Servo Controllers

I am having an issue controlling any of my Polulo Maestro server controllers connected to a Raspberry Pi.
My setup is completely powered and connected via a USB hub.
I have adapted my bootstrap so that the maestro devices create nodes in /dev as /dev/Maestro_001 etc …
Using the classic open, write and read functions as downloaded from the Polulu site I get a strange error. I have adapted the code (to highlight the error) to increment the server channel 1 position from a initial position of 4350 … The issue always starts occurring at the same value

All goes great until I get to a position of 4352 when the Polulu seems to modify its response, the following is my debug output.

Setting target to 4350 (1087 us).
Current position is 4350.
Setting target to 4351 (1087 us).
Current position is 4351.
Setting target to 4352 (1088 us).
Success
error reading: Success
Current position is -1.
Setting target to 4353 (1088 us).
„: Success
error reading: Success
Current position is -1.
Setting target to 4354 (1088 us).
„: Success
error reading: Success
Current position is -1.
Setting target to 4355 (1088 us).
„: Success
error reading: Success
Current position is -1.

I am posting to RPi site but has any one got any ideas …

I have tried adapting the tcsetattr to be more deterministic about the serial port settings but have not been able to move the issue, I have put sleep statements between position changes incase it is a timing issue.

If I raise the start position all is fine … viz

Setting target to 5350 (1337 us).
Current position is 5350.
Setting target to 5351 (1337 us).
Current position is 5351.
Setting target to 5352 (1338 us).
Current position is 5352.
Setting target to 5353 (1338 us).
Current position is 5353.

I have been struggling with this for quite some time and would love some help.

Richard
P.S. I have not uploaded the C code, but can if requested

Hello, Richard.

It seems like your code has trouble reading the servo position after it has been set to 4352. That number happens to be 0x1100 in hex, which means that one of the bytes received from the Maestro will be 0x00 (null). I suspect your code is accidentally treating null bytes specially, so you might check for that type of issue and post your code here if you cannot find the problem.

–David

Good spot David …

I’ll explore some more as it would appear there are other numeric values that cause the issue to check they have the same shape.

I just can’t help wondering where the Success message is coming from?

Richard

Here is the function that is having trouble, copied from the “Cross-Platform C” section in the Maestro User’s Guide:

int maestroGetPosition(int fd, unsigned char channel)
{
  unsigned char command[] = {0x90, channel};
  if(write(fd, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }
   
  unsigned char response[2];
  if(read(fd,response,2) != 2)
  {
    perror("error reading");
    return -1;
  }
   
  return response[0] + 256*response[1];
}

I suspect that the read command returned 1, so the code above called perror, but there wasn’t actually any error (the global error code was zero) so it just printed “Success” instead of an error message. I am not sure what is going on, but maybe if “read” returns 1 then you should call read again to get the second byte. However, a nicer solution would be to somehow configure the serial port so that all reads are blocking and will only complete after the desired number of bytes are received. You would also want to configure a timeout so that your application does not block forever when something goes wrong.

–David

Hi David
Excuse the delay in responding - I am currently working hard in Singapore but back in the UK soon. I have been reviewing the results and you are correct in suspecting that the read is only returning one byte. My query is why is it so predictable around the values 4352+.
I have modified the code to produce the following results ;

Sending 90 1 Received (2) fd 10 Current position is 4349. Setting target to 4350 (1087 us). Sending 84 1 7e 21 Sending 90 1 Received (2) fe 10 Current position is 4350. Setting target to 4351 (1087 us). Sending 84 1 7f 21 Sending 90 1 Received (2) ff 10 Current position is 4351. Setting target to 4352 (1088 us). Sending 84 1 0 22 Sending 90 1 Received (1) 0 0 ret is 1, Response is 0 Current position is -1. Setting target to 4353 (1088 us). Sending 84 1 1 22 Sending 90 1 Received (1) 1 0 ret is 1, Response is 1 Current position is -1. Setting target to 4354 (1088 us). Sending 84 1 2 22 Sending 90 1 Received (1) 2 0 ret is 1, Response is 2 Current position is -1. Setting target to 4355 (1088 us). Sending 84 1 3 22 Sending 90 1 Received (1) 3 0 ret is 1, Response is 3 Current position is -1. Setting target to 4356 (1089 us). Sending 84 1 4 22 Sending 90 1 Received (1) 4 0 ret is 1, Response is 4 Current position is -1. Setting target to 4357 (1089 us). Sending 84 1 5 22 Sending 90 1 Received (1) 5 0 ret is 1, Response is 5 Current position is -1. Setting target to 4358 (1089 us). Sending 84 1 6 22 Sending 90 1 Received (1) 6 0 ret is 1, Response is 6

The RPi goes into melt down (freezes) at values above 4368 and will never recover.
If I start the position increment above 5000 the code works a treat.

I wonder if the serial setting are reacting to the byte 0x11 & 0x12 etc

Still trying - have seen that you can set the read timeouts - but I can’t get out of thinking why it works so well with other values

RichG

After read returns 1, does your code try calling it again to get the second the byte? Also, could you post your full code? What operating system is your Raspberry Pi running?

–David

Hi

I have been experimenting with the stty settings and have cracked it …

The stty settings are :

root@Pi001:/railway/rail/debug# stty -a < /dev/Maestro_002
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ; quit = ; erase = ; kill = ; eof = ; eol = ; eol2 = ; swtch = ;
start = ; stop = ; susp = ; rprnt = ; werase = ; lnext = ; flush = ;
min = 1; time = 10;
-parenb -parodd cs7 hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke

I have changed most of these from the command line so now need to research how to set them with tset/get etc

I just have spotted another undocumented feature :- at first I thought I was seeing things :

Setting target to 4108 (1027 us).
Sending 84 1 c 20
Sending 90 1
Received (2) c 10
Current position is 4108.
Setting target to 4109 (1027 us).
Sending 84 1 d 20
Sending 90 1
Received (2) a 10
Current position is 4106.
Setting target to 4110 (1027 us).
Sending 84 1 e 20
Sending 90 1
Received (2) e 10
Current position is 4110.

Did you spot the issue - tying to set position 4109 it set position 4106 - this is the only one I’ve spotted and this I can live with. The original problem has stalled my railway project for months.

Onwards and Upwards

Hi David

My RPi is running Raspian Wheezy, hoping to run 12 & 24 channel Maestro as well as 3 k8055’s

RichG

The discrepancy with a target value of 4109 is most likely caused by your serial port trying to do something special with newlines and carriage returns. You could try disabling icrnl.

–David