serialLED only working on first cycle thru script

Hello,

I created a custom lua script to change the color some WS2812B LED’s via my RC transmitter. Upon powering on the colors will display correctly but they will not update. If I toggle RC7, the messages are displayed correctly thru MP but there are no changes to the LED’s.

I am using a Matek H743 slim FC running V4.2.3, with 4 WS2812b LED’s wired in series.

Can someone please let me know what I am doing wrong?

RCControlLEDs with patternsOK.lua (3.7 KB)

I removed the script altogether and set the LEDs with NTF_LED_TYPES. LED’s work just fine that way. Appears the hardware and soldering are OK. I will keep digging into the lua code.

Is anyone willing to try my Lua script on their FC? Or perhaps look thru my code and see if they can find anything wrong?

At a glance, it appears it should continue to work after the first pass.

You have potential scope issues with the pwmXX variables as well as r, g, and b. Declare them as local to the update function.

Rather than nesting the logic so deeply, perhaps declare a function for each behavior. This may make debugging easier. Like so:

local function color_blend(pwm_brt, pwm_r, pwm_b, pwm_g)
	local LED_br = math.floor((pwm_brt - 982) * 255 / 1024)
	local r_val = math.floor((pwm_r - 982) * LED_br / 1024)
	local g_val = math.floor((pwm_g - 982) * LED_br / 1024)
	local b_val = math.floor((pwm_b - 982) * LED_br / 1024)
	if msg_sent == 1 or msg_sent == 0 then
		gcs:send_text(6, "LED Function = 0, Custom color")
		msg_sent = msg_sent + 1
	end
	return r_val, g_val, b_val
end

Then your update function would have the statements:

elseif led_function == 0 then -- Calculate color blend based on RC input
    r, g, b = color_blend(pwm11, pwm12, pwm13, pwm14)

Your function increment variable can be made to wrap around using the modulo operator, avoiding the entire first conditional logic below its assignment.

led_function = (led_function + 1) % 6

Additionally, you can use the RC_Channel_ud:norm_input() binding to get a value for each channel between -1.0 and 1.0, thus avoiding the pwm math that you’re doing. Like so:

local norm11 = rc:get_channel(11):get_norm_input()

To avoid dynamic object creation with this method, you can assign the RC_Channel_ud variables in the initialization section like this:

local chan11 = rc:get_channel(11)

And then use it in the update function like this:

local norm11 = chan11:norm_input()

Similarly, there is a get_aux_switch_pos() binding as well, so you could get channel 7’s value as a discrete 0, 1, or 2 rather than raw pwm.

Lastly, consider your naming convention a bit better. If pwm11 is intended to be the brightness factor, simply name it brightness_factor.

I took a stab at rewriting your script to show some examples of how things can be done in different ways with Lua and our bindings. I tested in SITL, and it seems to work.

Creating a table of functions sort of mimics C/C++ switch/case statements, thus avoiding a lot of if/then/else logic.

I added a GCS text message just before the entry call to the update() function, which I find to be good practice. If you see the LED Script Active message displayed, then it’s confirmation that the script was successfully loaded.

You’ll need to set RCx_OPTION to 300, 301, 302, 303, and 304 for switch select, brightness, red, green, and blue, respectively. If your RC channels are already mapped to other options, simply replace the 300-series values in the script with the options you’re using (for example, if you’re modulating the red color with the landing gear switch, use 29 in place of 302).

See if this gets you any farther along.

led_rewrite.lua (3.7 KB)

EDIT: This second example shows how you can embed functions directly into a table, though I’m not sure it reads any better. Functionality should be identical. Note the minor changes to the way the table is indexed in the update() function, since Lua tables are 1-based by default.

led_rewrite2.lua (3.6 KB)

@Yuri_Rage Yuri, thank you very much for responding and taking the time to rewrite the script.

Unfortunately, I am getting the same symptom as my original script. If I adjust the corresponding inputs, then power on the color will take but after that the script will not work. I did adjust the RCx_OPTIONs per your instructions. Also looking at Mission planner messages I do see the LED Script Active message.

I can also see at first the NeoP is not shown but after 2 seconds you can see it shown properly. Would this imply I have settings incorrectly set?

@Yuri_Rage I was able to add those debug items to the Quick message like you have noted. They are changing properly but no change to leds.

LEDs can be very finicky. First, let’s change BOOT_DELAY to something between 2000 and 5000.

EDIT, there’s a parameter to delay booting as well, which has proven helpful in some cases with stubborn peripherals. You can try increasing BRD_BOOT_DELAY to 5000 instead of delaying script execution.

If that doesn’t work, see here for some level shifting magic that may be required:
NeoPixel — Copter documentation (ardupilot.org)

If you don’t have a signal diode on hand, you could try using a 3v3 supply on the LEDs, which will reduce their brightness but may help isolate the issue.

1 Like

I swapped the power supply from the FC to the ESC BEC and now the lua scripting is working properly. My original script was correct as well. Thanks for the help Yuri, I will apply your suggestions.

1 Like

Ah yes. Powering LEDs directly from the autopilot’s own 5V supply is a very bad idea! They can easily draw too much current and cause more issues than just color display inconsistencies.