Using GPIO relays to power LEDs

I’m finally getting around to digging into the ArduPilot support for external LEDs. I’m building another EDU-450 - and I’m planning on using them for the first time.

Searching through the wiki about this - everything seems to point to using the ProfiLED - a CubePilot product that is fairly specialized.

From what I can tell, the ProfiLED product has it’s own microcontroller that takes two PWM signals and those signals determine how the microcontroller illuminates the LEDs.

Pretty fancy. And it requires a LUA script to send the right PWM signals.

What I’m wondering is what about just setting a GPIO pin to “high” and using that to power an LED - or several in series.

The ProfiLED has a separate power connection - so it’s not dependent on the power from the AUX port. Maybe that’s the reason - perhaps there’s simply not enough power on a GPIO to illuminate an LED.

But if that’s the case - I’m surprised there isn’t some sort of transistorized relay designed to allow a GPIO to control power to an LED. It seems to me that’s all you’d need for a simple ON or OFF.

Of course if all one wanted was simple LED running lights that were always illuminated when the aircraft was powered, you could just power LEDs directly from an onboard BEC.

I’m going to go ahead and give the LEDs that come with the EDU-450 - which appear to follow the ProfiLED design/protocol. But I’m curious about more simple options and alternatives.

I’d appreciate all comments.

Simple, single color LEDs can be controlled via GPIO. If you run enough of them in series (or use high powered variants), a relay would be well advised to avoid drawing too much current on any given GPIO pin. You may need to use current limiting resistors to avoid early failures/burnouts.

NeoPixel (WS28xx) or ProfiLED-style devices require specific signal protocols and will typically not respond to simple GPIO (persisted logic high/low) signaling. Scripting is the typical method for control, though AP does provide a simple (scriptless) notification feature for basic needs.

Thanks Yuri - Yes, this matches what I’ve picked up so far.

I don’t recall seeing a current limit on GPIO pins. But as GPIO is more about presence or absence of voltage, it can’t be much.

The thing that’s been on my mind is simple on/off functionality.

For example, it’s common practice to use a GPIO/Relay to trigger a camera via a signal assignment from an RC channel.

Similarly - landing gear raising or lowering.

I’m surprised I’ve seen no reference to someone assigning an RC channel to “turn the lights on” - or “off”.

The ProfiLED functionality is pretty cool. But it’s way too advanced for simple DIY projects.

And the CubePilot documentation for ProfiLED is so minimal I doubt few could use it and write their own LUA script from scratch. Of course it’s common practice to write new code using other code as a template. But there isn’t a lot out there to copy.

Some buddies of mine are using LED’s and LUA scripts to provide a LED blinking as a visual indication of battery voltage. It’s on my to-do list to talk with them and figure out how the went about doing that. (And they’re not using ProfiLED’s.)

I think there are numerous examples where folks use direct GPIO power and/or simple relays for single color lights. That configuration should be very straightforward (configure the desired output as an RC controlled relay pin).

I don’t specifically see an FMU current limit on the Cube’s documentation, but the IOMCU pins are limited to 50mA each, with a further limit of 100mA total, across all 8. Since even the simplest LEDs often draw 10-20mA, it’d be good practice to use a separate power supply or relay if you intend to drive more than a couple in series.

As for scripting, it might be easier than you think to customize behavior. I know the documentation is sparse, but there are several examples that bolster the docs. There’s a bit of elegance in the LED bindings, where, once the initial configuration is complete, the same function calls are used for both NeoPixel and ProfiLED control. In general, you simply call serialLED:set_RGB(channel, address, r, g, b), where channel is derived from the config, address is the LED to change (-1 for all on the string), and r/g/b are 8 bit brightness per color (0-255). Then you commit the change using serialLED:send(channel) to send the correct message to the LEDs to update their values.

1 Like

You can set:

NTF_LED_LEN,{number of LEDs}
SERVOx_FUNCTION,120 or 129

and connect your Neopixel LED string to a suitable output.
Ardupilot will automatically use them to indicate all the normal status conditions.
So you dont even need to get into scripting unless you want to.

The Neopixel (WS2812B) lengths are easy to find, and even local electronics stores should have some for Arduino experimenters - usually a length of 8 LEDs, sometime more.
Be mindful of the current they can draw when all fully lit.


Attached is a slight modification of the applet script from GitHub. I use this on my EDU450.

When disarmed, ArduPilot’s NTF LED colors are displayed. When armed, the colors transition to nav/strobes.

This script takes an almost insignificant amount more processing time and RAM over the existing applet, and I find it far more useful.

There’s an additional feature that is easily commented out, where channel 5’s status is monitored for use with ExpressLRS. A GCS message is sent when channel 5’s status changes, indicating the ELRS arming state (useful to me because I use a transmitter mix to set Ch5 high or low based on “synthetic” rudder arming detection on the RC radio side of things).

Hexsoon_LEDs_yuri.lua (2.0 KB)

LEDs can be trivially powered from the servo rail using a low side logic voltage MOSFET (don’t use power MOSFET with high required gate voltage).

Doing a bit of searching on the general case of using GPIO pins for LED’s, I found quite a bit targeting the Raspberry Pi and Arduino community.

These devices have different GPIO voltages, which requires some accommodation. 3V versus 5V.

I’m wondering if the BRD_PWM_VOLT_SEL parameter can be used to set the voltage of the GPIO pins as well as the PWM signals.

I thought this article was helpful.

The answer to your base question is likely yes…but the reality is more complicated:

BRD_PWM_VOLT_SEL only affects IOMCU pins (main out), which cannot be used for relay output on the Cube Orange.

Any LED that you intend to drive directly from GPIO will almost certainly have a forward voltage less than 3v3, meaning that you would simply choose appropriately sized current limiting resistors whether driving with 3v3 or 5V. The output brightness would be the same, so long as the current limiting resistor is chosen properly. Anything more powerful (i.e., “high powered LEDs”) would almost certainly require relay/MOSFET switching.

I think you may be overthinking this a bit…

If you want to switch simple LEDs via RC channels on any available output, you might consider RC-based relays such as this one. Configure an output as RCINx, connect the relay input to the configured output, and then drive your peripheral via power through the relay.

I believe after release 4.2 main ports are available as output GPIO.

I don’t think so. On Cube Orange anyway.

Might be worth a test.

I have some friends here locally who use it on a Holybro Pixhawk.

If it doesn’t, the wiki needs an update.

I did test it. Any configuration of GPIO on the main outputs still show PWM in the Banner message.