Lua script - how to add delay

Hi all,

I am developing a driver for a device communicating over half duplex uart. An example dataframe is shown below (request from pixhawk and respond from device). The problem is that pixhawk does not read the respond. In fact it reads it sometimes, rarely and randomly.

I have developed the following lua script which in the case of full duplex uart works perfectly (used an extra board to convert half to full duplex). My understanding is that due to the delay between request and respond, port:available() does not find any data and the script exits. How can I add a delay to synchronize it? Or maybe any other better ideas?

local port = serial:find_serial(0)
assert(port, 'No scripting serial port found!')

port:begin(1000000)
port:set_flow_control(0)

function update ()

    port:write(0xFF)
    port:write(0xFF)
    port:write(0x01)
    port:write(0x04)
    port:write(0x02)
    port:write(0x38)
    port:write(0x02)
    port:write(0xBE)
    
    local n_bytes = port:available()

    while n_bytes > 0 do
        local byte = port:read()
        gcs:send_text(0, 'received ' .. byte)
        n_bytes = n_bytes - 1
    end

    gcs:send_text(0, "Exiting!")

    return update, 1000
end

return update, 100

Try this:

local SEND_INTERVAL_MS = 1000 -- how often to send a message
local POLL_INTERVAL_MS = 20   -- how fast to poll for a response
local TIMEOUT_MS = 100        -- how long to wait for a response

local MESSAGE = { 0xFF, 0xFF, 0x01, 0x04, 0x02, 0x38, 0x02, 0xBE }

local port = serial:find_serial(0)
assert(port, 'No scripting serial port found!')

port:begin(uint32_t(1000000))
port:set_flow_control(0)

local message_timeout = uint32_t(0)
local message_count = 0
local response_count = 0
local error_count = 0

function send_message ()

    -- send all bytes in the message table
    for _, b in ipairs(MESSAGE) do
        port:write(b)
    end

    -- report number of messages sent
    message_count = message_count + 1
    gcs:send_named_float('SENT', message_count)

    -- set a timeout for perihpheral response
    message_timeout = millis() + TIMEOUT_MS

    -- schedule the receiver function
    return receive_message, POLL_INTERVAL_MS
end

function receive_message()

    -- read all available bytes
    local received = {}
    while port:available() > 0 do
        received[#received + 1] = port:read()
    end

    -- report packet size and response count upon receipt
    if #received > 0 then
        response_count = response_count + 1
        gcs:send_named_float('RCVD', response_count)
        gcs:send_named_float('BYTES', #received)
        return send_message, SEND_INTERVAL_MS
    end

    -- check for timeout rather than polling forever
    if millis() > message_timeout then
        error_count = error_count + 1
        gcs:send_named_float('ERRS', error_count)
        return send_message, SEND_INTERVAL_MS
    end

    -- continue to poll for a response until timeout
    return receive_message, POLL_INTERVAL_MS
end

return send_message, SEND_INTERVAL_MS
1 Like

Hi Yuri,

thanks for your response. I tried your script and works perfectly in the case of full duplex UART. Unfortunately with half duplex it does not. In fact it does not read any bytes though I can see them with a logic analyzer. This is exactly the situation I faced with my script. So i am thinking of the the following possible scenarios:

  1. Wrong configuration for half duplex??
    I have configured serialx_protocol = 28 and serialx_options = 4.
    I tried serial port 1 to 4.
  2. Voltage levels not enough for pixhawk 4??
    The actual voltage is seen below and logic analyzer reads it correctly.
    (2v/div)

Anything else that could go wrong here?

No idea why that isn’t working. But it’s certainly a hardware issue at this point and not one that I can solve with more lines of code.

Turns out half duplex is not supported by DMA so at such high rates communication is not possible. Lower bandwidth worked.

Hi @Yuri_Rage,

by the way, is it possible to visualize in the Graph Log Tool the various named float variable of your script? I only can see just one. If not, is there any other way? Perhaps some tlog file parser?

Use the logger:write() binding to properly data log to the onboard .bin file.

Ignore the .tlog files.

1 Like

Thank you for the recommendation i ll try that. So named float variables are only for use in the “Quick” tab?

The named float binding is a way for you to get a scripted value sent across the telemetry link. Anything that happens after that is up to the GCS software (Mission Planner, in this case).