Lua Script for Sensor that needs delay

Hello! I would like to implement a sensor on a plane, but it seems to need a 20ms delay for it to work! It works perfectly fine with an arduino (i used a delay function), but I am confused if there are any workarounds for the needed delay through lua scripts. Is there a possibility to just start the measuring process with LUA and readout at a later time?

here are some context:

The sensor tested is HDC1080 from Texas Instruments. It is tested on an Arduino Uno and it works perfectly fine, I tried testing it on Pixhawk4, ArduPlane V4.4.0 but it is not being detected, with the reasoning eventually found that the sensor data gathering was initiated by the sample script, because it starts a read on the address 0x00.

The Arduino script is the one that is given as a sample code from Texas Instruments

And the scan script is from the Lua example code

The same scan script can detect another sensor, Bosch BME280 and Bosch BME680. The bus address is set as 3 during the testing, as the sensors are plugged to I2CA port but it is not detecting the HDC1080.

here are the oscilloscope results:

  1. Bosch 680 connected to pixhawk (scanBoschTI.lua is used)

  1. HDC1080 connected to pixhawk (scanBoschTI.lua is used)

  1. scanBoschTI.lua loop while HDC1080 is connected to pixhawk

  1. HDC1080 connected to Arduino:

as in the arduino script 20ms delay :

Image conclusions:

-the scan.lua script does not have a 20ms delay (as far as I know there is no such function in the lua ardupilot wrapper).

-the address read on 0x00 for HDC1080 is to initiate the temperature and pressure readings

-the scan.lua sample code triggers HDC1080 temperature and pressure sensing

These are the datasheets for the sensors :

  1. HDC1080
  1. BME680

Thank you so much for your help!!

here is the scanBosch.lua code that I used

scanBoschTI.lua (819 Bytes)

Make use of the script scheduler to effect the poll rate and delay:

local POLL_TIME_MS = 1000
local READ_TIME_MS = 20

local last_action = millis()

local function get_timing(timestamp)
    local diff = millis() - timestamp
    return diff:tofloat()
end

function read_sensor()
    -- read the sensor here
    gcs:send_named_float('TIME', get_timing(last_action))
    last_action = millis()
    return poll_sensor, POLL_TIME_MS
end

function poll_sensor()
    -- initiate sensor measurement here
    gcs:send_named_float('TIME', get_timing(last_action))
    last_action = millis()
    return read_sensor, READ_TIME_MS
end

return poll_sensor()

The script above has all the underpinnings for what you need, and if you run it as is, you can monitor MAV_TIME in Mission Planner’s Quick tab to see what’s happening with the timing. It calls poll_sensor at ~1Hz, and read_sensor happens ~20ms after a poll call.

I’ll leave it to you to implement the I2C specifics, as I am a bit busy with other projects and work.

3 Likes
local POLL_TIME_MS = 1000
local READ_TIME_MS = 20
local dataTemp,dataHum

local last_action = millis()

local function get_timing(timestamp)
    local diff = millis() - timestamp
    return diff:tofloat()
end

local function read_temperature(device,dataTemp)
    gcs:send_text(0, "temp pass"..tostring(dataTemp))
    local temperature = ((dataTemp / 65536.0) * 165.0) - 40.0
    return temperature
end

-- Function to read humidity
local function read_humidity(device,dataHum)
    
 
    gcs:send_text(0, "hum pass " .. tostring(dataHum))
    local humidity = (dataHum / 65536.0) * 100.0
    
    return humidity
end

function read_sensor()
    -- read the sensor here
    dataTemp = device:read_registers(0)
    dataHum = device:read_registers(1)

    gcs:send_named_float('TIME', get_timing(last_action))
    last_action = millis()
    return poll_sensor, POLL_TIME_MS
end

function poll_sensor()
    -- initiate sensor measurement here
    local temperature = read_temperature(device,dataTemp)
    local humidity = read_humidity(device,dataHum)
    gcs:send_named_float('TIME', get_timing(last_action))
    last_action = millis()
    return read_sensor, READ_TIME_MS
end

return poll_sensor()

Hello!

Thank you so much for your reply!!!

So above is the updated script, I didnt get any error messages from the console so I hope I am doing everything alright, it seems that the device isnt being “got” it is still the same situation as the scan.lua script up above.

You never declare or assign the variable device to anything, so there’s nothing to do…reference the example you already showed, where the i2c binding is used to scan for devices on the bus.

I read the datasheet and used this Arduino code as an example to follow.

I think the following script should work. I may have the raw byte ordering backwards, and I’ll leave that as an exercise for you to sort out.

If you want to post code blocks, use the “</>” button to surround them with 3 backticks.

local POLL_TIME_MS = 1000
local READ_TIME_MS = 20

local hdc1080 = i2c:get_device(0, 0x40) -- HDC1080 address (binary 1000000)
assert(hdc1080 ~= nil, 'I2C get_device error: no HDC1080 found')

function read_sensor()
    local raw = hdc1080:read_registers(0x00, 4)  -- read 4 bytes
    local rawTemp = raw & 0xFFFF 
    local rawHumidity = raw >> 16
    local temperature = rawTemp * 165 / 65536 - 40
    local humidity = rawHumidity * 100 / 65536
    gcs:send_named_float('TEMP', temperature)
    gcs:send_named_float('HUM', humidity)
    return poll_sensor, POLL_TIME_MS
end

function poll_sensor()
    hdc1080:write_register(0x02, 0x10)  -- start measurement
    return read_sensor, READ_TIME_MS
end

return poll_sensor()

Ah thank you so much! But it is unfortunately still not working, no feedback whatsoever in the messages. If I can provide any information, please let me know! At this point I am so lost :smiling_face_with_tear:. Thank you so much!

There are no messages. You need to monitor MAV_TEMP and MAV_HUM on the Quick tab. The only possible text messages would indicate errors.