114 lines
3.2 KiB
Lua
114 lines
3.2 KiB
Lua
|
-- led-control.lua: Control serial LEDs with ArduPilot parameters and RC switch
|
||
|
|
||
|
-- Constants
|
||
|
local PIXEL_GROUPING = Parameter("PIXEL_GROUPING", 1) -- LEDs per arm
|
||
|
local PIXEL_DEFAULT = Parameter("PIXEL_DEFAULT", 0) -- Default behavior (0: arming-based, 1: always active)
|
||
|
local PIXEL_ARM = {
|
||
|
Parameter("PIXEL_ARM1", 1),
|
||
|
Parameter("PIXEL_ARM2", 1),
|
||
|
Parameter("PIXEL_ARM3", 1),
|
||
|
Parameter("PIXEL_ARM4", 1)
|
||
|
}
|
||
|
local RC_SWITCH_CHANNEL = 300 -- Use RC channel set in ArduPilot parameters
|
||
|
local AuxSwitchPos = {LOW=0, MIDDLE=1, HIGH=2} -- Switch positions
|
||
|
|
||
|
local RGB_COLORS = {
|
||
|
{0, 255, 0}, -- Green
|
||
|
{255, 0, 0}, -- Red
|
||
|
{255, 255, 255}, -- White
|
||
|
{128, 0, 128} -- Purple
|
||
|
}
|
||
|
|
||
|
local NUM_ARMS = 4
|
||
|
local prev_pos = -1
|
||
|
local leds_enabled = true
|
||
|
|
||
|
-- Initialize serial LED channel
|
||
|
local led_chan = assert(SRV_Channels:find_channel(94), "LED: channel not set") + 1
|
||
|
gcs:send_text(6, "LED strip: chan=" .. tostring(led_chan))
|
||
|
assert(serialLED:set_num_profiled(led_chan, 8), "Failed LED setup")
|
||
|
|
||
|
-- Validate parameters to ensure safe behavior
|
||
|
local function validate_params()
|
||
|
if PIXEL_GROUPING:get() < 1 then
|
||
|
gcs:send_text(3, "Invalid PIXEL_GROUPING. Defaulting to 1.")
|
||
|
PIXEL_GROUPING:set(1)
|
||
|
end
|
||
|
|
||
|
for i = 1, NUM_ARMS do
|
||
|
local arm_behavior = PIXEL_ARM[i]:get()
|
||
|
if arm_behavior < 1 or arm_behavior > #RGB_COLORS then
|
||
|
gcs:send_text(3, "Invalid PIXEL_ARM" .. i .. ". Defaulting to 1 (Green).")
|
||
|
PIXEL_ARM[i]:set(1)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Set LEDs
|
||
|
local function set_leds(color, start, count)
|
||
|
for i = start, start + count - 1 do
|
||
|
serialLED:set_RGB(led_chan, i, color[1], color[2], color[3]) -- RGB values
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- Update LED behavior
|
||
|
local function update_leds()
|
||
|
local armed = arming:is_armed()
|
||
|
local grouping = PIXEL_GROUPING:get()
|
||
|
|
||
|
for arm = 1, NUM_ARMS do
|
||
|
local behavior = PIXEL_ARM[arm]:get()
|
||
|
local color = RGB_COLORS[behavior]
|
||
|
|
||
|
-- Default to red if disarmed and PIXEL_DEFAULT is 0
|
||
|
if not armed and PIXEL_DEFAULT:get() == 0 then
|
||
|
color = RGB_COLORS[2] -- Red
|
||
|
end
|
||
|
|
||
|
local start_idx = (arm - 1) * grouping
|
||
|
set_leds(color, start_idx, grouping)
|
||
|
end
|
||
|
|
||
|
serialLED:send(led_chan)
|
||
|
end
|
||
|
|
||
|
-- Main update loop
|
||
|
local function update()
|
||
|
-- Get the current RC switch position
|
||
|
local sw_pos = rc:get_aux_cached(RC_SWITCH_CHANNEL)
|
||
|
|
||
|
if sw_pos == nil then
|
||
|
gcs:send_text(3, "RC_SWITCH_CHANNEL not configured.")
|
||
|
return update, 1000
|
||
|
end
|
||
|
|
||
|
if sw_pos ~= prev_pos then
|
||
|
if sw_pos == AuxSwitchPos.LOW then
|
||
|
leds_enabled = false
|
||
|
serialLED:clear(led_chan)
|
||
|
gcs:send_text(6, "LEDs turned OFF")
|
||
|
elseif sw_pos == AuxSwitchPos.MIDDLE then
|
||
|
leds_enabled = true
|
||
|
gcs:send_text(6, "LEDs turned ON (Dimmed)") -- Dimming logic can be added later
|
||
|
elseif sw_pos == AuxSwitchPos.HIGH then
|
||
|
leds_enabled = true
|
||
|
gcs:send_text(6, "LEDs turned ON (Full Brightness)")
|
||
|
end
|
||
|
prev_pos = sw_pos
|
||
|
end
|
||
|
|
||
|
if leds_enabled then
|
||
|
update_leds()
|
||
|
end
|
||
|
|
||
|
return update, 1000 -- Run every 1 second
|
||
|
end
|
||
|
|
||
|
-- Initialization
|
||
|
serialLED:clear(led_chan)
|
||
|
validate_params()
|
||
|
if leds_enabled then
|
||
|
update_leds()
|
||
|
end
|
||
|
|
||
|
return update()
|