UART readblob or readstring

I am porting some Arduino code of mine where I had used the readBytes function, so I wanted to use the readblob function but cannot understand how the readblob works in relation to the uart configured callback function.

uart.configure(baudRate, wordSize, parity, stopBits, flags, myCallbackFunction)

When exactly does the callback function fire. If it fires as soon as the first byte arrives then how does readblob/readstring work if it is not a blocking function. I was planning to set the numberOfBytes in the readblob function, but it's not clear if I need to also set the setrxfifosize() if this somehow linked to the timing of the uart callback function.

Comments

  • As the documentation says, "If fewer bytes than requested are available, the method will return a smaller blob containing as many bytes as there were in the UART receive FIFO. If no data is available, it will return a zero-length blob."

    It doesn't block, it just grabs whatever is in the buffer at the time and gives it to you.

    Personally, I find uart.readblob and uart.readstring of limited use if you are also using the callback. The callback function will be invoked as soon as one character has been received, so you cannot rely on a complete message being available to you when it is triggered. I find it much simpler to call uart.read until the buffer is empty. Each character returned by uart.read would then be appended to your own blob or string.
  • What I did that seemed to work well is to set a timer with imp.wakeup and at each callback of this timer I use uart.readblob.

    I also checked the flags to see if I had overflowed the fifo and changed it to be sufficiently large that this never happens.

    If you have very infrequent and not predictable information coming on the uart it might make more sense to use the uart callback. In my case the uart is always pretty busy and it would be rare for the buffer to have nothing in it.
  • @coverdriven yes I've read the documentation but not clear on use of callback function. The method you've described is the same method I have tended use too. However creating code which loops through uart.read until the buffer is empty is essentially blocking or if you simply rely on the callback just to read one byte then not blocking (but I found a very infrequent occurance of it missing the odd byte here and there). The readblob should be able to be used to do the same but not sure how.

    With the Arduino code it loops and simply checks to see if anything available in buffer and then uses the readbytes (or readbytesuntil) function. With the readbytes there is a timeout function if not enough bytes read.

    In my application it is critical that I grab the first 56 bytes. These same 56 bytes can repeat up to 5 times (like a rapid burst of data to make sure you get it - its received via wireless transmission) and then there is a gap of a couple of seconds that confirms that batch of data complete. You validate by comparing as need to have at least 2 matching 56bytes of data etc. The data via wireless receiver is triggered by an infrequent alarm event.

    Hence want to tweak methodology to ensure I capture all this data all of the time. Looks like @mjkuwp94 methodology may well be the way to go where you increase the buffer to make sure no overflow etc. but this requires a little (somewhat unnecessary IMO) trial and error.
  • Basically, the callback fires when there's a byte ready in the buffer. If you're using the callback, you probably don't need uart.readblob(). As an example, this is what I do in my XBee class (comments removed for to keep the size small):
       function _dataReceivedAPI() {
    local b = _uart.read();

    if (b == 0x7E && _frameByteCount != 0 && _escapeFlag == false) {
    server.error("Malformed frame: new start marker detected; ignoring received data");
    _buffer = blob();
    _frameByteCount = 0;
    _frameSize = 0;
    }

    if (b == 0x7D && _escaped) {
    _escapeFlag = true;
    return;
    }

    if (_escapeFlag) {
    _escapeFlag = false;
    b = b ^ 0x20;
    }

    _buffer.writen(b, 'b');
    _frameByteCount++;

    if (_frameByteCount == 2) _frameSize = b << 8;
    if (_frameByteCount == 3) _frameSize = _frameSize + b + 4;

    if (_frameByteCount < 5 || _frameByteCount < _frameSize) return;

    ...
    Callback fires, I read the byte, check its value and process as necessary or write to my own buffer blob. If the last line doesn't return, I go on to process the contents of the blob (an XBee API frame). I can't use uart.readblob() because I need to check the value of each byte as it comes in to find the start of each frame.
  • Generally you should loop in your callback to empty the buffer. The callback *does* fire multiple times if you don't, but it's less efficient to restart the callback for every byte.
  • Thanks all for the insight.

    So my take on it is that unlike the Arduino readbyte which waits for the buffer to fill or times out, the Imp readblob / readstring simply pulls out bytes from the buffer if they are there. If not it returns 0 length.

    So in my application the better method to use is loop in callback to empty buffer.
Sign In or Register to comment.