Help creating LUA script

Hey, so this is my first post here. I have been building RC for a couple of years now but new to Pixhawk. I have not done very much programming and none in LUA. Reading the documentation confuses me, but I only want to make a simple script that will turn on a neopixel LED ring on a drone I am using, like a floodlight, just by flipping a switch. How would I go about writing a script to do that? Any help would be appreciated.

The Ardupilot github repo has some examples for implementing a few basic functionalities using LUA scripting. Here is the link to the examples directory:

It has a few examples related to LEDs as well.
Hope it helps.

Thank you. So I looked through and tried a few of the scripts. I can’t seem to get the LEDs to turn on. I made a loop that outputs the channel that I have set to 94 like in the LED example but the LEDS are not turning on at all. I have attached a few photos of the LED ring and the wiring. I have no idea what could be wrong. Does the ring not work? Any help is appreciated.

led_test.lua (714 Bytes)



Screenshot 2023-10-07 141104

Most likely a wiring problem. The servo rail is an unpowered bus, and you must supply voltage from a BEC on any unused + pin.

Like using one of the power cables plugged into one of the open ports on the Pixhawk?

Maybe. Those pixels are probably 5V. Assuming that’s correct, you need a 5V source with enough current capacity to light the whole string. Ensure it has a common ground with the signal path.

Okay, so some weird stuff is happening now. I plugged 5V into it and nothing happened. But when I switch the channel to Neopixel instead of Script 1 one of the twelve LEDs blinks. This confuses me.

I deleted all of my scripts and just tested the LED Roll from the examples and the same thing, only 1 LED is working, but now when script 1 is used.

okay, now I got the ring to work, but only 1 LED turns on. I used the example LED_roll from Git with the same issue.

Hello @Taylor,
if you switch the SERVO8_FUNCTION to NeoPixel you’re no more using the Lua Script to control the LED and you need to set also NTF_LED_LEN to 12.
The parameter SERVO8_FUNCTION need to be set to 94 if you want to control LEDs via Lua Script. Be aware that on the Lua Script LED_roll.lua you should uncomment line 30 and comment line 31 to use NeoPixel LEDs.

Follow @beska’s advice and then the following script should probably do what you want. I didn’t test it, but it’s pretty simple.

Set RCx_FUNCTION=300 where x is the channel you want to use for controlling the LEDs.

On a 3-position switch, you should see the LEDs cycle from red to green to blue as you flip the switch. It may take a moment for the change to happen since the polling interval is 200ms, but there’s probably no need to run this script at a faster rate for such simple functionality.

If you’re using a 2-position switch, COLORS[1] (green in the example) will go unused.

If you want to turn the LEDs off in one of the switch positions, set the color to { 0, 0, 0 } for that position.

If you find for some reason that the LEDs misbehave (change color randomly or turn off) after some period of time, you can remove the if condition and just continually update them on every scheduled call.

local RUN_INTERVAL_MS = 200
local RC_FN = 300
local LED_FN = 94
local NUM_LEDS = 8
local COLORS = {
    [0] = { 255,   0,   0 },  -- color for switch position 0
    [1] = {   0, 255,   0 },  -- color for switch position 1
    [2] = {   0,   0, 255 }   -- color for switch position 2
}

local led_chan = assert(SRV_Channels:find_channel(LED_FN), "Scripting LED channel not set")
led_chan = led_chan + 1
assert(serialLED:set_num_neopixel(led_chan, NUM_LEDS), "Failed scripting LED setup")

local rc_chan = assert(rc:find_channel_for_option(RC_FN), "Scripting RC channel not set")

local last_sw_pos = -1

function update()
    local sw_pos = rc_chan:get_aux_switch_pos()
    if last_sw_pos ~= sw_pos then
        serialLED:set_RGB(led_chan, -1, table.unpack(COLORS[sw_pos]))
        serialLED:send(led_chan)
        last_sw_pos = sw_pos
    end

    return update, RUN_INTERVAL_MS
end

gcs:send_text(6, "NeoPixel LED script loaded")

return update()

Also of interest, if you want the LEDs to function as a status indicator while disarmed, you can add the following if block to the beginning of the update() function:

    if not arming:is_armed() then
        local r, g, b = LED:get_rgb()
        serialLED:set_RGB(led_chan, -1, r, g, b)
        serialLED:send(led_chan)
        return update, RUN_INTERVAL_MS
    end

Be sure to check the “Scripting” option in the NTF_LED_TYPES bitmask if you want to use this functionality.

It may help to run the script at 25-50ms in this case, since any blinking status indications will appear a little erratic at the slower rate.