Unsupported Sensors? Try Arduino + Lua!

I think this will not work in my case because the Arduino will be together with my Pixhawk on the drone…

That’s exactly what those examples are showing. And then you simply use the gcs:send_named_float() binding to relay the data to the GCS (as I now see that @Eosbandi has suggested to you).

Serial data transfer is not relevant to this blog post and is diluting the information in it. Start a new topic or reply to one of your existing topics with this train of thought.

1 Like

Hello All,

First of all a big thank you to @Yuri_Rage for the excellent work on not only the concept but the thorough examples too. I came across this thread as I wanted to interface a strain guage and log the data on board a Pixhawk 1. I finally managed to do so after going through the entire thread and then some. So just for benefit of others who might come across this thread here is what worked for me.

  1. Set SCR_ENABLE parameter to 1. This enables LUA scripts stored in /APM/Scripts folder on SDCARD to run.
  2. My Pixhawk 1 (2.4.8) came with 2MB RAM. Still it was short of memory to run the scripts. I had to disable TERRAIN_ENABLE and SRTL_POINTS along with CAN_Dx_UC_POOL according to this:
    Firmware Limitations on AutoPilot Hardware — Copter documentation
  3. Set the SCR_HEAP_SIZE to 44032 or more. One can check the free memory on the status tab of MP under “freemem” parameter. I have about 20K left after running my script.
  4. In Yuri’s zip file, the extras folder has the LUA scipts for char, int and float examples that need to placed in the /APM/scripts folder as per ones requirement. I used the DS180 example and modified it to read float values sent across by arduino (Dumilanove, yes…).
  5. If sending data as text (hello_world example), the text appears in the messages tab of MP. If send as a int or float the variable needs to be selected for display by double clicking in the quick tab and selecting MAV_{param_name}. (I scratched my head for a few minutes why my sensor value is not showing up in messages! Silly Me).
  6. By default the parameter is not logged. To do so add the “logger.write” function call.

Again thanks to Yuri for such a great project. If anyone needs a simple code for sending float sensor values from arduino to Pixhawk here are my files.
scale_logger_AP.txt (953 Bytes)
readsens.lua (3.1 KB)

3 Likes

Excellent! Glad to see this in use!

Of note, the examples include some reasonably well written pack/unpack routines to create integer and floating point values from byte arrays, but Lua includes string.pack() and string.unpack() natively that would greatly simplify the serialization provided by the example functions. I’ll leave that as an exercise to the user for now…

EDIT:
I just asked ChatGPT to simplify the unpack_ieee754_float() function using Lua native serialization, and it only took two prompts to get a valid 3 line function (6 if you include some error checking) :smiley:

1 Like

@Yuri_Rage can you pr the changes you made?

I made no changes, and I hesitate to do so before testing well (ensuring endianness and such). I own the repo, so it’d be a simple push upstream.

1 Like

@Yuri_Rage Hi Yuri,
I am at random getting an error “attempt to perform arithmetic on nil value” on line 48 of my script posted earlier. Line 48 corresponds to “local val = unpack_ieee754_float(read_register_data())”. The read_register_data() function seems to check for nil condition. After encountering the error the script just hangs and i need to power cycle the pixhawk. Are there any other checks that need to be done in the function?. Also the number of bytes returned by read_register_data() is supposed to be 3 or 4? Thanks!

Update:
Found the bug. apparently if any of the bytes in the read_register_data() other than size byte is ‘nil’ then the unpack function gets stuck. so I modified the code thus with the help of CGPT:

local function read_register_data()
    local bytes = {}
    -- arduino i2c_slave library passes data size in register byte 0
    local size = arduino_i2c:read_registers(0)
    if not size then 
        return nil 
    end
    -- retrieve and store register data
    for idx = 1, size do
        local data = arduino_i2c:read_registers(idx)
        -- Check if any byte is nil
        if not data then
            return nil
        end
        bytes[idx - 1] = data
    end
    return bytes
end

I wrote a similar script, but it works through uart🙏