3

I'm trying to do some fairly simple serial communication and have things partially working, but am pretty confused about a couple results I'm getting.

For a little background, I'm using an Arduino Mega 2560 to try to communicate with a Dynamixel servo (MX-64) over TTL (half-duplex, asynchronous) with Tx1 and Rx1. Basically I construct some byte arrays as instructions, send them over to the servo (with Serial1.write()), and then read back a reply. I've actually gotten it to work pretty well if I use Serial1.readBytes(), specifying the length of the buffer (number of bytes I'm expecting). I'm also reading back what I originally sent (first) as well as the response (second), since I have Tx1 and Rx1 tied together (required in my setup because this servo only has one data wire).

However I don't understand the difference between Serial.readBytes() and Serial.read(). If I do Serial.read() just prior to Serial.readBytes(), it comes back with -1, meaning no bytes to read... but then Serial.readBytes() gives me the byte stream I was expecting from the buffer! What's going on here?

Similarly, Serial.available() seems sort of broken in that it tells me there are no bytes to read (returns 0), but then I can read the bytes I'm expecting with Serial.readBytes(). Additionally, I can do Serial.readBytes() after there's nothing left (or rather, there shouldn't be any bytes left...) and it will give me some bytes, but they're total garbage.

I think maybe there's something I don't understand about the way the serial buffer works, but can't find a good resource on it and the Arduino reference pages are kind of useless. Any clues about the difference in how these operate would be much appreciated!

2
  • what IDE are you using. I recall that some of the 1.0.5'ish may be broke. I try to stick with 1.5.8 or 1.0.6
    – mpflaga
    Feb 5, 2015 at 22:28
  • I'm using 1.5.8
    – thkemp
    Feb 5, 2015 at 22:55

1 Answer 1

6

readBytes is blocking until the determined length has been read, or it times out (see Serial.setTimeout()). Where read grabs what has come, if it has come in. Hence available is used to query if it has.

Note that it takes time for a message to go out and to receive either the echo or response. So simply checking the RX buffer immediately after sending something, is expected to be empty for some time. That is where readBytes sites and waits. And I bet the default setTimeout of 1s is sufficient, to get the response.

This is why you see the Serial.read() inside a while or if Serial.available. Hence I typically employ something like the following: Which emulates readBytes (for the most part).

    #define TIMEOUT = 3000;
    loop {
        char inData[20];
        unsigned long timeout = millis() + TIMEOUT;
        uint8_t inIndex = 0;
        while ( ((int32_t)(millis() - timeout) < 0) && (inIndex < (sizeof(inData)/sizeof(inData[0])))) {
            if (Serial1.available() > 0) {
                // read the incoming byte:
                inData[inIndex] = Serial.read();
                if ((c == '\n') || (c == '\r')) {
                    break;
                }
                Serial.write(inData[inIndex++]);
            }
        }
    }

Above code was quickly written and untested. But gets the idea across.

1
  • Thanks, I think that mostly answers what I was wondering about. The servo should respond 500 microseconds after receiving its instruction (I can actually change that duration); I've played around with adding delays but the resulting availability of bytes still seems to be somewhat unpredictable. I will stick with using readBytes() because it seems to produce consistent results and I can predict the number of bytes I should receive back.
    – thkemp
    Feb 19, 2015 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.