Help with Propeller accessing meccano smart servos
I'm trying to teach myself to program the Propeller in C. I figured a good project to try would be accessing some old Meccano smart servos that we had lying around from a Meccanoid as the protocol seems to be well defined so I wired up the circuit in the protocol and am using the board's USB supplied power @(~4.8V) to power the servo and P26 as the communication line. However, I'm getting some unexpected behavior. I've attached the protocols for reference (there is an error in the receive protocol documentation). There is also some code written already for the arduino to send and receive the bit information. The first is for sending bits to the servos:
void MeccaBrain :: sendByte(byte servoData){
pinMode(_pmwPin, OUTPUT);
digitalWrite(_pmwPin,LOW);
delayMicroseconds(bitDelay); // start bit - 417us LOW
for (byte mask = 00000001; mask>0; mask <<= 1) { // iterate through bit mask
if (servoData & mask){ // if bitwise AND resolves to true
digitalWrite(_pmwPin,HIGH); // send 1 }else{ // if bitwise and resolves to false digitalWrite(_pmwPin,LOW); // send 0 } delayMicroseconds(bitDelay); //delay
}
digitalWrite(_pmwPin,HIGH);
delayMicroseconds(bitDelay); // stop bit - 417us HIGH
digitalWrite(_pmwPin,HIGH);
delayMicroseconds(bitDelay); // stop bit - 417us HIGH
}
I have a propeller quickstart board running at CLKFRQ=80000000 and I took a crack at turning this into C and came up with the follow:
void sendToSmartModule(char data,char pin)
{
int bitDelay=417;// 417us
int ticks=1000000;
set_pause_dt(CLKFREQ/ticks); //1 microsecond?
set_direction(pin,1);
low(pin);//set input/output pin to low
pause(bitDelay);
for(char maskByte=0x1;maskByte>0;maskByte <<=1)
{
if(data&maskByte)
{
high(pin);
}
else
{
low(pin);
};
pause(bitDelay);
};
high(pin);//set input/output pin to low
pause(bitDelay);
high(pin);//set input/output pin to low
pause(bitDelay);
};
My first observation is 'set_pause_dt(CLKFREQ/ticks)' isn't behaving as expected. According to the documentation here: https://david.zemon.name/PropWare/api-develop/simpletools_8h.xhtml#a04c171fd47bc9149c306576c349de680
set_pause_dt(CLKFREQ/1000000) should be 1 microsecond so that the total HIGH/LOW time is 417 microseconds, but its not. In fact I get no response from the servo until I pick something like set_pause_dt(CLKFREQ/3000000) .
I am starting off in the simple case where I am sending a byte at a time, with the sequence {FF,FE,FE,FE,FE,A0}, and I think the appropriate start LOW, and stop HIGH bits at each byte (I believe its effectively using the 2400 baud 8N2 serial format).
I feel like I am misunderstanding how pause/high/low commands are supposed to work. I would appreciate help with the receiving section (based on measuring pulse widths) as well, but I wanted to make sure I am understanding the send section first as what I am getting back from the receiving section is even stranger.
Comments
From what I understand, the Meccano Smart Servos are commanded using a normal serial protocol at the baud you described. The communication protocol gets strange when it receives data.
I don't use C with the Propeller much myself so I'm not familiar with the correct syntax to use in this example.
In case you're not aware, the Meccano Smart Servos were discussed in the Arduino forum back in 2015.
I'd suggest using a serial driver to send commands to the servo. If you want to receive information back from the servo, you may need to disable the serial driver after a command has been issued and then watch for the returned bits with an appropriate algorithm.
Hopefully by bumping this thread, someone will see it who can answer your syntax questions.
Edit: The forum thread was from 2015 not 2017. Time does NOT slip into the future; time careens into the future.
Based on what I read in the spec document, it's 2400 baud, half-duplex serial. Easy-peasy. There is no need for you to bit-bang the serial stream, there should be a serial object available to C that will let you configure it for half-duplex, open-true mode. You will need a pull-up (10K will work) between 3.3v and the TX/RX pin.
If you don't have a logic analyzer, this would be good time to acquire one. Here's a really cheap starter logic analyzer that will work well with this project:
-- https://www.amazon.com/gp/product/B077LSG5P2
For less than the price of lunch you can have a tool that will help you sort out what's happening with the Meccano coms. I use a piece of freeware called PulseView to display an analyze what the logic analyzer. Here's a capture of serial data using that $13 LA and PulseView.
By connecting the LA to the TX/RX pin and setting the protocol analyzer in PulseView for 2400 baud serial, you'll be able to "spy" on the system and suss out all its secrets.
Jon, I'm pretty sure the only easy part is the transmit to the servo. The servos can also respond with their position information. This position information isn't sent back with same protocol.
Here's a quote from page 10 of the pdf:
Unlike the bits from the MeccaBrain™ which are just HIGH and LOW for 1 and 0, the bits from the Smart Modules are based on high pulse widths. A “1” bit is when a High pulse is > 400ms; a “0” bit is when the High pulse is < 400ms.
I have no idea why they designed these servos his way. It sure seems like normal serial would have been a lot easier for users.
Hi Jon, the Pulsview software you mentioned seems to be quite interesting. Will need to look at it,
Thanks,
Mike
It's quite nice -- and you can't beat the price. It also runs on any OS. PulseView + $13 logic analyzer makes a really cheap investment in one's own education.
Well, that's kind of silly, isn't it? It's an unnecessary complication, but would make picking out traffic from an LA trace easy, though you wouldn't be able to use the LA's protocol analyzers with any reliability.