LoRa on Microbit truncates received messages

Hello,

I have set up a MicroBit as a LoRa receiver using LoRa module from Reyax RYLR890/896. These LoRa modules recieve/transmit information with AT commands over serial port.

At transmitter, I have an ESP32 in Arduino framework. The LoRa module (“Transmitter”) sends a message every few seconds with ‘AT+SEND’ command. I have verified that it transmits correctly with another Reyax RYLR890 module (“Receiver”) set up in the following ways:

  1. Hooked up to my Macbook via FTDI adapter and CoolTerm serial monitor.
  2. Wired to another ESP32 sending the received transmissions to the serial monitor.
    So transmissions are correctly sent and received.

Now I set up reception on Microbit using two pins (14, 15) for serial redirect. I am able to receive transmissions but they are truncated for some reason. Here is my code:

let preamble = ""
let sepOne = 0
let genericTx = ""
let sepTwo = 0
let sizeTx = 0
let coreTx = ""
let messageRx = ""
input.onButtonPressed(Button.A, function () {
    serial.redirect(
    SerialPin.P15,
    SerialPin.P14,
    BaudRate.BaudRate9600
    )
    basic.showIcon(IconNames.Yes)
})
function parseRx (message: string) {
    preamble = message.substr(1, 3)
    if (preamble == "RCV") {
        music.playTone(262, music.beat(BeatFraction.Whole))
        sepOne = message.indexOf(",")
        genericTx = message.substr(sepOne + 1, message.length - sepOne)
        sepTwo = genericTx.indexOf(",")
        sizeTx = parseFloat(genericTx.substr(0, sepTwo))
        coreTx = genericTx.substr(0 + 1, sizeTx)
        basic.showString("" + (coreTx.length))
        if (coreTx.includes("WOR")) {
            basic.showIcon(IconNames.SmallHeart)
        }
    }
}
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), function () {
    messageRx = serial.readUntil(serial.delimiters(Delimiters.NewLine))
    parseRx(messageRx)
    basic.clearScreen()
    basic.showIcon(IconNames.Happy)
    basic.clearScreen()
})

Appreciate any help figuring this out.

It appears that this is a problem with serial.demliters() and delimiters are not aligning. The transmission is terminated by CRLF (Carriage Return + Line Feed). The AT command is ‘AT+SEND=0,11,HELLO WORLD\r\n’. The message is received as ‘+RCV=120,11,HELLO WORD,-99,40\n’ where 120 is transmitter address, 11 is length of the payload, HELLO WORLD is the payload, and the remaining information pertains to signal strength and Signal-Noise ratio. When I query the length of the rec’d message at serial, it is 19, which is ‘’+RCV=120,11,HELLO W’. Somehow the delimiters don’t align.

Hi @sunbee . Welcome to the forum.

Are you using a micro:bit v1? It looks like its serial buffer was just 20 bytes (here), which fits suspiciously well with what you’re seeing. It looks like it will trigger an event either when it finds a delimiter or when the buffer is full (here).

You might try accumulating a string in a global variable. When the global variable has a newline, call your parse and reset the global variable to empty. (Might want to do some debugging and code review to confirm there aren’t any ways that you may end up with data after the newline).

1 Like

Hello @bsiever !

Sounds like your diagnosis is correct! I tried fixing it with an accumulator, but it seems like the serial buffer holds only the truncated message each time. I have included my code below.

let messageRxAccumulator = ""
let preamble = ""
let comma_first = 0
let generic_message = ""
let comma_second = 0
let sizeTx = 0
let payload = ""
let messageRx = ""
input.onButtonPressed(Button.A, function () {
    serial.redirect(
    SerialPin.P15,
    SerialPin.P14,
    BaudRate.BaudRate9600
    )
    messageRxAccumulator = "" // acumulate incoming Rx
    basic.showIcon(IconNames.Yes)
})
function parseRx (message: string) {
    preamble = message.substr(1, 3)
    if (preamble == "RCV") {
        music.playTone(988, music.beat(BeatFraction.Whole))
        comma_first = message.indexOf(",")
        generic_message = message.substr(comma_first + 1, message.length - comma_first)
        comma_second = generic_message.indexOf(",")
        sizeTx = parseFloat(generic_message.substr(0, comma_second))
        payload = generic_message.substr(comma_second + 1, sizeTx)
        basic.showString("" + (payload.length))
        if (payload.includes("WOR")) {
            basic.showIcon(IconNames.SmallHeart)
        }
    }
}
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), function () {
    messageRx = serial.readUntil(serial.delimiters(Delimiters.NewLine))
    messageRxAccumulator = "" + messageRxAccumulator + messageRx // Update accumulator
    if (messageRxAccumulator.includes("\n")) {  // Look for newline
// Never reaches this part 
        music.playTone(131, music.beat(BeatFraction.Whole))
        basic.showString("" + (messageRx.length))
        messageRx = messageRxAccumulator.substr(0, messageRxAccumulator.indexOf("\n")) // Grab the part upto newline
        messageRxAccumulator = ""  // Reset accumulator
        parseRx(messageRx)
        basic.clearScreen()
        basic.showIcon(IconNames.Happy)
        basic.clearScreen()
    }
})

I tried using set serial buffer size to 128 and it worked! That one line of code made all the difference! I have included the revised code below for reference.

Thank you @bseiver for point me in the right direction.

let preamble = ""
let comma_first = 0
let generic_message = ""
let comma_second = 0
let sizeTx = 0
let payload = ""
let messageRx = ""
input.onButtonPressed(Button.A, function () {
    serial.redirect(
    SerialPin.P15,
    SerialPin.P14,
    BaudRate.BaudRate9600
    )
    serial.setRxBufferSize(128)
    basic.showIcon(IconNames.Yes)
})
function parseRx (message: string) {
    preamble = message.substr(1, 3)
    if (preamble == "RCV") {
        music.playTone(988, music.beat(BeatFraction.Whole))
        comma_first = message.indexOf(",")
        generic_message = message.substr(comma_first + 1, message.length - comma_first)
        comma_second = generic_message.indexOf(",")
        sizeTx = parseFloat(generic_message.substr(0, comma_second))
        payload = generic_message.substr(comma_second + 1, sizeTx)
        basic.showString("" + (payload.length))
        if (payload.includes("WOR")) {
            basic.showIcon(IconNames.SmallHeart)
        }
    }
}
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), function () {
    messageRx = serial.readUntil(serial.delimiters(Delimiters.NewLine))
    parseRx(messageRx)
    basic.clearScreen()
    basic.showIcon(IconNames.Happy)
    basic.clearScreen()
})

Nice work @sunbee !

I didn’t know you could change the buffer size. Did you try just the larger buffer size with your original code (no accumulation)?