serial half duplex

17 Feb 2011

The SerialHalfDuplex example in the cookbook does not work for me. I connected port 9 and 10. The example program sends one character and then hangs.

Is a pullup resistor required? Has anyone else successfully used the example?

g.

17 Feb 2011

Hi Glen,

Yep, I was able to use the SerialHalfDuplex in the AX12+ library

http://mbed.org/cookbook/Dynamixel-AX12-Servo

Silly question, but have you tied the two UART pins together? From memory, when you transmit a character the SerialHalfDuplex object will wait for it to be received again. This is because the Rx and Tx lines should be connected and you'll always get transmitted characters echoed back. If the lines are not tied together I'd expect it to hang, waiting for the echo.

Hope that helps.

Chris

21 Feb 2011

Tied UART pins together? Read post - pins 9 and 10 connected.

Here is code that works and (commented out) code that does not work. It appears that the SerialHalfDuplex in the example is incorrect.

g.

Send a byte as a master, and receive a byte as a slave

  1. include "mbed.h"

SerialHalfDuplex master(p9, p10); this does not work

Serial out(p9, NC); this works Serial in(NC, p10);

int main() { while (1) { int outbyte = master.putc(0x55); int outbyte = out.putc(0x55); int retbyte = master.getc(); if (in.readable()) { int retbyte = in.getc(); printf("Wrote: %02X Read: %02X\r\n", outbyte, retbyte); } else { printf("no char avail\r\n"); } } }

21 Feb 2011

Sorry for the format problems in the previous post. I don't know how to make it readable. It reads fine in the 'Post reply' window, but it does not post the way it was typed. Comment lines are deleted, as are newlines. The upshot is this:

The example SerialHalfDuplex does not work, but a simple workaround is to use these functions : Serial out(p9, NC);

Serial in(NC, p10);

int outbyte = out.putc(0x55);

in.readable();

int retbyte = in.getc();

g.

21 Feb 2011

Hi Glen,

The example for SerialHalfDuplex sends a byte, then reads a byte. If the device you are talking to doesn't return anything (or nothing is connected), then it will hang waiting for something.

You can also use readable() to see if it receives anything.

If you have nothing connected, that would be the expected behaviour. Assuming this is the case, I'll make a note to update the example to clarify that you need to be talking to something.

Simon

21 Feb 2011

You should surround the code fragments with <<code>> <</code>> tags when posting. Also, use "preview" button to see how it will look.

// Send a byte as a master, and receive a byte as a slave

#include "mbed.h"

//SerialHalfDuplex master(p9, p10); // this does not work

Serial out(p9, NC); // this works
Serial in(NC, p10);

int main() {
    while (1) {
       // int outbyte = master.putc(0x55);
       int outbyte = out.putc(0x55);
       // int retbyte = master.getc();
       if (in.readable()) {
            int retbyte = in.getc();
            printf("Wrote: %02X  Read: %02X\r\n", outbyte, retbyte);
       } else {
            printf("no char avail\r\n");
       }
   }
}
 
21 Feb 2011

Thanks to those who have responded. In order to help others who might have similar problems I am posting what I have learned. Here is the code and docs from the Handbook SerialHalfDuplex entry:

----------

A serial port (UART) for communication with other devices, with a single shared transmit and receive line.

If the device both transmits and receives, then both (separate) pins need to be defined, and tied together externally. Example

// Send a byte as a master, and receive a byte as a slave

#include "mbed.h"

SerialHalfDuplex master(p9, p10);

int main() {
    int outbyte = master.putc(0x55);
    int retbyte = master.getc();
    printf("Wrote: %02X  Read: %02X\n", outbyte, retbyte);
}

---------

Of course for this to work p9 has to be connected to p10. I thought I had made this clear in my first post, which indicated that I had done so, but as some did not understand this I will make it more obvious: in order to run this demo you need to connect p9 to p10. You need not do anything else.

The demo code, as I indicated, does not work. Because the documentation for SerialHalfDuplex is very sketchy and because the source code is not available (bad!) fixing this requires some trial-and-error, complicated for me by the fact that my scope is broken (new one on order). Were I to do serious code for the MBED I would just write my own drivers, at least until the MBED folks either publish library source code or make better docs.

Probably the outbyte() function puts the char in the xmit buffer and returns immediately. If getc() hangs when no char is available this would explain why the code does not work, because there would be no char in the input buffer until about 1 Ms (the default baud rate is 9600).

if getc() returned something, such as 0, when there is no char then the code should not hang. Likewise, if getc() just waits for a char to be in the buffer then we would expect the code to work, with a 1 mS delay before the printf does its thing. Since it does not work, it appears that getc() causes the program to crash if there is no char available in the receive buffer.

We would hope that if we check for a char in the buffer before trying to read it, the example code would work (code snippet):

    while !master.readable() {};
    int retbyte = master.getc();

But this code does not work either.

Using the Serial library, things work OK - except that the actual behavior of getc() is not documented very well. The following code indicates that getc() waits until a char is in the receiver before continuing. This is OK, tho it should be documented.

Here is code using Serial instead of SerialHalfDuplex. It works, and shows that getc() waits until a char is in the buffer. If this is not what you want, you could use an interrupt routine or could check the status of the buffer using readable(), tho I have not tested that to make sure it works.

// Send a byte and receive a byte. Connect p9 and p10.
// Glen Worstell 21-Feb-2011

#include "mbed.h"

Serial out(p9, NC);
Serial in(NC, p10);
Ticker tUsec;
DigitalOut myled1(LED1);

volatile static unsigned int  count = 0; // the global count, 100 uS per count

void inc_tUsec_func(void) { // the function called by ticker interrupts every 100 uS
   count += 1;
}

int main() {
   volatile static unsigned int start;
   tUsec.attach(&inc_tUsec_func, 100.0e-6); // ISR to increment secs every 100 uS
   unsigned char toPut = 0xF0;
   while(1) {
   
        int outbyte = out.putc(toPut);
        start = count;
        int retbyte = in.getc();
        printf("count - start = %i\r\n",count-start);    // if getc() waits until a char is ready,
        // this should take about 1 mS, or 10 counts, at 9600 baud.
        // It would be easier to just use a scope for this - mine is broken.
        printf("Wrote: %02X  Read: %02X\r\n\r\n",toPut, retbyte);
        start = count;
        while ((count-start) < 10000) {}; // wait for a second
        toPut += 1;
        myled1 = !myled1; // toggle the led once per second
   }
}

21 Feb 2011

Hi Glen,

I'll investigate this for you, and see if we can track down the problem. Thanks for the report. I'll also update the documentation to be more precise about the behaviour you highlighted as unclear.

Thanks!

Simon

23 Feb 2011

Thanks, Simon. You probably already figured out that my comment about incrementing secs should have been incrementing count.

I've done more serial port work, and I find that for my purposes the mbed Serial routines are unusable because of lack of source code and/or completely insufficient docs. For example, I was trying to work with parity and with the buffers, but there is no info on whether buffers are used, how to test parity, etc.

I do not understand why you don't make the source code available. If it were I could use it, modifying it for my purposes if necessary. As the hardware is well-documented I fail to see why the software routines should be proprietary - it isn't rocket science.

I will have to write my own serial drivers, and this means I will need to figure out how to do assembly language with the mbed, which if I understand correctly may not be easy. It might be possible to do it all in c, but assembly is so much easier (for me) to use for this sort of thing...

Note that the mbed Serial routines allow one to set parity but give no way to test it. This seems strange...

Because my new scope has not yet arrived I cannot easily test to see if the parity options do anything or not.

g.

01 Mar 2011

It may be completely unconnected (as I think it is more likely to be a dodgy ground connection!) but I have been having a few problems with the AX12+ servos I have been using - they sometime stop or hang for a few seconds. Could this be down to the half-duplex issue here?

04 Mar 2011

Hi Martin,

I've been doing some improvements on the characteristics of the SerialHalfDuplex with regard to signalling, so will post a test library update later which could well solve issues you are seeing. I don't think it is actually related to the previous questions, as I think these are more about documentation and clarity in the application/distinction between Simplex and Half Duplex connections and what library element you would use to achieve them; I'll aim to update that too.

Will post again when we have something available.

Simon

05 Mar 2011

Hi Simon,

Thanks for looking into this. To be a bit more specific I'm sending positional updates to 3 AX-12 servos at about 50Hz. Sometimes it runs for only a second or two before a problem occurs sometimes a minute or longer, so whatever problem I'm getting is happening <1% of the time. Mainly I get checksum errors on the last servo on the bus (which it generally recovers from) but often it just hangs suggesting that either comms have been lost or a servo received a garbage message. The code is running in an infinite loop so it should run forever. I can post the code if this would help?

Martin

19 Sep 2012

Hi

My AX-12 don't work more! I don't have any idea why it stopped, I didn't change nothing about my circuit and suddenly when I tryed use them nothing happened and since that moment it doesn't move anymore.

Someone have any idea what could be happened? Or give me any suggestion to do it return to work.

thanks

Carla

19 Sep 2012

Hi Carla,

Maybe you could start a new forum thread for this? This is probably going off topic.

Anyway, how many servos are you using? Could you have changed their ID?

Martin

19 Sep 2012

Hi Martin,

Sorry start this kind of topic in this forum. I'll do this.

Well, about my problem... I'm working with 2 servos and I don't changed their ID, I just turn off and turn on and they stopped! =[

Carla

30 Sep 2012

What is the status with this issue? I have the same problem with the latest version of the mbed library. Using two Serials instead of one SerialHalfDuplex works.

05 Nov 2013

where is the SerialHalfDuplex library now?