Lua scripting problem

Good day,

Hope someone can help me with a lua scripting problem.

I am running ardurover V4.6.0 on a Holybro kakute H7, i have a 32gb SD card inserted in the slot. What I want to achieve is that the RC5 stick when pushed to the left the LH servo must swing to drop bait from boat, the same for the RHS. when pushing stick left RH servo must not move and when pushing stick to right LH servo should not move.

I have enabled lua scripting and i am able to succesfully write baitdrop left, bait drop right in the messages in missionplanner but it seems like the script cant control the servo outputs for some reason. if i go to servo outputs tab there is no movement when i set the servos to run from script1. if i map the servos directly to the rc channel it works and servos move.

What am I missing? I am very new to this so it might be a simple fix.

  • I confirmed wiring as it works when set directly to rc5
  • LUA is working as it gives correct (expected messages).

Here is the code I use:

– Independent bait drop control from RC channel 4 (rudder)
– Left servo on SERVO3, Right servo on SERVO6
– Set SERVO3_FUNCTION = 94, SERVO6_FUNCTION = 94
– Requires: SCR_ENABLE = 1

local left_dropped = false
local right_dropped = false

function update()

local rc4 = RC:channel(4) -- RC4 input (rudder)

if rc4 == nil then
    gcs:send_text(6, "RC4 is nil")
    return update, 100
end

local pwm = rc4:pwm()

-- Drop left bait if rudder pushed left
if pwm < 1300 and not left_dropped then
    SRV_Channels:set_output_pwm(3, 2000)  -- Extend left servo
    gcs:send_text(6, "Left bait dropped")
    left_dropped = true
elseif pwm >= 1300 and left_dropped then
    SRV_Channels:set_output_pwm(3, 1000)  -- Retract left servo
    left_dropped = false
end

-- Drop right bait if rudder pushed right
if pwm > 1700 and not right_dropped then
    SRV_Channels:set_output_pwm(6, 2000)  -- Extend right servo
    gcs:send_text(6, "Right bait dropped")
    right_dropped = true
elseif pwm <= 1700 and right_dropped then
    SRV_Channels:set_output_pwm(6, 1000)  -- Retract right servo
    right_dropped = false
end

return update, 100 -- Repeat every 100 ms

end

return update()

set_output_pwm takes the function number not the channel number. Set SERVO3_FUNCTION to 94 and SERVO6_FUNCTION to 95

Then set_output_pwm(3, ... should be set_output_pwm(94, ... and set_output_pwm(6, ... should be set_output_pwm(95, ...

Thanks so much, this fixed the problem.

Ran into another problem.

Due to the fact that i use LUA script to drop the LH and RH bait buckets (I have to control via LUA because i use a single throttle stick on remote to drop both, one when stick is left the other when stick is right).

What I need is when there is a RTL condition triggered the first step must be both bait buckets must drop before the RTL starts (I managed to get this working).

Secondly I must be able to manually drop both buckets independently (This is also working fine from LUA script).

The third function I need is to be able to plan a drop at a certain point when sending the boat on a mission. I started by using the DO_SET_SERVO command but if failed to trigger the drop due to the fact that the servos is controlled by the script and commands is not recognised (Or so I assume). I now tried adding virtual pins via relay 1 and 2 to the script so I can use DO_SET_RELAY in planning and trigger the drop as such but I am failing to accomplish this. Is there an easier way to achieve this?

I will attach my script for more information.

-- RC4 stick + RTL + DO_SET_RELAY (via PWM) bait dropper

local left_dropped = false
local right_dropped = false
local rtl_dropped = false
local last_mode = -1
local relay1_last_pwm = 0
local relay2_last_pwm = 0

function update()
    local pwm = rc:get_pwm(4)
    if pwm == nil then
        gcs:send_text(6, "RC4 not available")
        return update, 100
    end

    local mode = vehicle:get_mode()

    -- === Auto RTL Drop ===
    if mode == 11 and last_mode ~= 11 and not rtl_dropped then
        SRV_Channels:set_output_pwm(95, 1000)
        SRV_Channels:set_output_pwm(94, 1000)
        gcs:send_text(6, "Auto RTL: Dropped both bait buckets")
        rtl_dropped = true
    elseif mode ~= 11 then
        rtl_dropped = false
    end
    last_mode = mode

    -- === Manual RC Stick Drop ===
    if pwm < 1300 and not left_dropped then
        SRV_Channels:set_output_pwm(95, 1000)
        gcs:send_text(6, "Manual: Left bait dropped")
        left_dropped = true
    elseif pwm >= 1300 and left_dropped then
        SRV_Channels:set_output_pwm(95, 1500)
        left_dropped = false
    end

    if pwm > 1700 and not right_dropped then
        SRV_Channels:set_output_pwm(94, 1000)
        gcs:send_text(6, "Manual: Right bait dropped")
        right_dropped = true
    elseif pwm <= 1700 and right_dropped then
        SRV_Channels:set_output_pwm(94, 1500)
        right_dropped = false
    end

    -- === Mission DO_SET_RELAY (via PWM detection) ===
    local pwm_relay1 = SRV_Channels:get_output_pwm(9)  
Relay 0
    local pwm_relay2 = SRV_Channels:get_output_pwm(10) 

    if pwm_relay1 ~= nil and pwm_relay1 > 1800 and relay1_last_pwm <= 1800 then
        SRV_Channels:set_output_pwm(95, 1000)
        gcs:send_text(6, "Mission: Left bait dropped")
    end
    relay1_last_pwm = pwm_relay1 or relay1_last_pwm

    if pwm_relay2 ~= nil and pwm_relay2 > 1800 and relay2_last_pwm <= 1800 then
        SRV_Channels:set_output_pwm(94, 1000)
        gcs:send_text(6, "Mission: Right bait dropped")
    end
    relay2_last_pwm = pwm_relay2 or relay2_last_pwm

    return update, 100
end

return update()

Thanks.

Do_SET_SERVO requires the servo not to be assigned function.

You can either use direct PWM commands on unassigned “Disabled” servos or use DO_SEND_SCRIPT_MESSAGE commands in mission to trigger droppers.

1 Like

Thanks for the info, I wrote a seperate LUA script for the dropping when on a mission. I cant get the mission to enter the scrypt as it goes into the mission but does not display the set messages and also dont activate the servos.

I think I am setting up the program incorrectly, see screenshot of plan.

Here is the code I am using for the drop.

-- Mission-only bait dropper, triggered via DO_SEND_SCRIPT_MESSAGE

function handle_script_message(cmd_id)
    if cmd_id == 101 then
        SRV_Channels:set_output_pwm(95, 1000)  -- Left drop
        gcs:send_text(6, "Mission: Left bait dropped")
    elseif cmd_id == 102 then
        SRV_Channels:set_output_pwm(94, 1000)  -- Right drop
        gcs:send_text(6, "Mission: Right bait dropped")
    end
end

return nil, handle_script_message

I also kept the original manual drop and rtl drop as a seperate scipt if that makes any difference.

-- RC4 Stick-controlled + Auto drop on RTL (mode 11)

local left_dropped = false
local right_dropped = false
local rtl_dropped = false
local last_mode = -1

function update()
    local pwm = rc:get_pwm(4)
    if pwm == nil then
        gcs:send_text(6, "RC4 not available")
        return update, 100
    end

    local mode = vehicle:get_mode()
    
    -- Detect switch to RTL mode
    if mode == 11 and last_mode ~= 11 and not rtl_dropped then
        -- Drop both bait buckets before RTL action
        SRV_Channels:set_output_pwm(95, 1000)  -- Left drop
        SRV_Channels:set_output_pwm(94, 1000)  -- Right drop
        gcs:send_text(6, "Auto RTL: Dropped both bait buckets")
        rtl_dropped = true
    elseif mode ~= 11 then
        rtl_dropped = false
    end

    last_mode = mode

    -- Manual Left bait drop (turn left)
    if pwm < 1300 and not left_dropped then
        SRV_Channels:set_output_pwm(95, 1000)
        gcs:send_text(6, "Manual: Left bait dropped")
        left_dropped = true
    elseif pwm >= 1300 and left_dropped then
        SRV_Channels:set_output_pwm(95, 1500)
        left_dropped = false
    end

    -- Manual Right bait drop (turn right)
    if pwm > 1700 and not right_dropped then
        SRV_Channels:set_output_pwm(94, 1000)
        gcs:send_text(6, "Manual: Right bait dropped")
        right_dropped = true
    elseif pwm <= 1700 and right_dropped then
        SRV_Channels:set_output_pwm(94, 1500)
        right_dropped = false
    end

    return update, 100
end

return update()

Please advise.

Mission bait dropper needs to run in a loop, I personally would unify them.

Thanks, is it possible to do them separate as when i combine them I screw up even the manual and rtl functions (maybe something I can do after I get it to actually work). Am I setting the script up correctly in missionplanner on the planning tab?

I am not sure about the id and P1 values.

This is the example for receiving DO_SEND_SCRIPT_MESSAGE commands:

Thanks so much, for future reference this worked for me.

function update()
  -- check for scripting DO commands in the mission
  local time_ms, p1, p2, p3, p4 = mission_receive()

  if time_ms then
    gcs:send_text(6, string.format("Mission CMD: p1=%d", p1))

    if p1 == 101 then
      -- Drop left bait
      SRV_Channels:set_output_pwm(95, 1000)
      gcs:send_text(6, "Mission: Dropped LEFT bait")
    elseif p1 == 102 then
      -- Drop right bait
      SRV_Channels:set_output_pwm(94, 1000)
      gcs:send_text(6, "Mission: Dropped RIGHT bait")
    end
  end

  return update, 100
end

return update()