Skip to content

Conversation

@Claudio-Chies
Copy link
Member

@Claudio-Chies Claudio-Chies commented Jan 5, 2026

Summary

Adds a new UAVCAN_LGT_MODE parameter to configure LED addressing for UAVCAN LightsCommand messages. This enables automatic LED control for Vertiq motor modules with integrated LEDs.

Changes

  • New parameter UAVCAN_LGT_MODE with two modes:

    • 0 (Generic): Uses standard UAVCAN convention for led assignment
    • 1 (Vertiq): Auto-calculates light_id values for Vertiq ESC index
  • Vertiq mode features:

    • RGB LED: light_id = esc_index * 3 + 1 (displays PX4 status colours)
    • White LED: light_id = esc_index * 3 + 2 (anti-collision lighting)
    • ESC count automatically detected from esc_status topic (no manual configuration required)
  • Documentation: Added LED configuration section to Vertiq peripheral docs

Motivation

Vertiq motor modules with the LED add-on require specific light_id addressing that doesn't match standard DroneCAN conventions.

Testing

  • Tested with 4 motors and LED Addons, status and anti-collision works as intended

@Claudio-Chies Claudio-Chies changed the title Add LED support with configurable light_id UAVCAN: Add LED support with configurable light_id Jan 5, 2026
@Claudio-Chies Claudio-Chies requested a review from MaEtUgR January 5, 2026 14:15
@github-actions
Copy link

github-actions bot commented Jan 5, 2026

🔎 FLASH Analysis

px4_fmu-v5x [Total VM Diff: 272 byte (0.01 %)]
    FILE SIZE        VM SIZE    
--------------  -------------- 
+0.0%    +272  +0.0%    +272    .text
  +0.1%    +152  +0.1%    +152    g_cromfs_image
   +13%     +96   +13%     +96    UavcanRGBController::periodic_update()
   +22%     +52   +22%     +52    UavcanRGBController::UavcanRGBController()
  +1.4%     +16  +1.4%     +16    UavcanNode::UavcanNode()
  +0.0%     +16  +0.0%     +16    [section .text]
   +21%     +12   +21%     +12    UavcanRGBController::updateParamsImpl()
  +1.9%      +8  +1.9%      +8    UavcanNode::handle_time_sync()
  +0.9%      +8  +0.9%      +8    UavcanNode::init()
   +12%      +8   +12%      +8    UavcanRGBController::~UavcanRGBController()
  +0.1%      +8  +0.1%      +8    px4::parameters
   +22%      +4   +22%      +4    uavcan::BitSet<>::BitSet()
  +3.6%      +2  +3.6%      +2    UavcanNode::get_next_active_node_id()
  +5.9%      +2  +5.9%      +2    uavcan::CanFrame::CanFrame()
  -2.5%      -4  -2.5%      -4    Commander::handleCommandsFromModeExecutors()
  -0.3%      -4  -0.3%      -4    UavcanNode::Run()
  -1.9%      -4  -1.9%      -4    UavcanNode::publish_can_interface_statuses()
  -4.1%     -12  -4.1%     -12    UavcanNode::publish_node_statuses()
  [DEL]     -88  [DEL]     -88    UavcanRGBController::brightness_to_rgb565()
+0.0%     +92  [ = ]       0    .debug_abbrev
+0.0%      +8  [ = ]       0    .debug_aranges
+0.0%     +40  [ = ]       0    .debug_frame
+0.0% +4.66Ki  [ = ]       0    .debug_info
+0.0%    +443  [ = ]       0    .debug_line
  [DEL]      -5  [ = ]       0    [Unmapped]
  +0.0%    +448  [ = ]       0    [section .debug_line]
+0.0%    +648  [ = ]       0    .debug_loclists
-0.0%     -67  [ = ]       0    .debug_rnglists
  +100%      +1  [ = ]       0    [Unmapped]
  -0.0%     -68  [ = ]       0    [section .debug_rnglists]
+0.0% +1.14Ki  [ = ]       0    .debug_str
-0.4%      -1  [ = ]       0    .shstrtab
+0.0%    +265  [ = ]       0    .strtab
  [DEL]     -49  [ = ]       0    UavcanRGBController::brightness_to_rgb565()
  [NEW]    +158  [ = ]       0    UavcanRGBController::periodic_update()::color_off
  [NEW]    +156  [ = ]       0    UavcanRGBController::periodic_update()::color_on
 -32.7%     -16  [ = ]       0    ___Z12get_orb_meta6ORB_ID_veneer
   +64%     +16  [ = ]       0    __nxsched_get_tcb_veneer
+0.0%     +80  [ = ]       0    .symtab
  [DEL]     -48  [ = ]       0    UavcanRGBController::brightness_to_rgb565()
  [NEW]     +80  [ = ]       0    UavcanRGBController::periodic_update()::color_off
  [NEW]     +64  [ = ]       0    UavcanRGBController::periodic_update()::color_on
  -0.3%     -32  [ = ]       0    [section .symtab]
   +33%     +16  [ = ]       0    _GLOBAL__sub_I__ZN19UavcanRGBControllerC2ERN6uavcan5INodeE
 -40.0%     -32  [ = ]       0    ___Z12get_orb_meta6ORB_ID_veneer
   +33%     +16  [ = ]       0    __fs_getfilep_veneer
   +67%     +32  [ = ]       0    __nxsched_get_tcb_veneer
   +50%     +16  [ = ]       0    __nxsig_lowest_veneer
 -33.3%     -16  [ = ]       0    __stm32_i2c_sendstart_veneer
 -25.0%     -16  [ = ]       0    __stm32_recvfifo_veneer
 -33.3%     -16  [ = ]       0    uavcan::CanFrame::CanFrame()
   +50%     +16  [ = ]       0    uavcan::fill<>()
-3.0%    -272  [ = ]       0    [Unmapped]
+0.0% +7.27Ki  +0.0%    +272    TOTAL

px4_fmu-v6x [Total VM Diff: 336 byte (0.02 %)]
    FILE SIZE        VM SIZE    
--------------  -------------- 
+0.0%    +272  +0.0%    +272    .text
  +0.1%    +140  +0.1%    +140    g_cromfs_image
   +13%     +96   +13%     +96    UavcanRGBController::periodic_update()
   +22%     +52   +22%     +52    UavcanRGBController::UavcanRGBController()
  +0.0%     +24  +0.0%     +24    [section .text]
  +1.1%     +12  +1.1%     +12    UavcanNode::UavcanNode()
   +21%     +12   +21%     +12    UavcanRGBController::updateParamsImpl()
  +1.9%      +8  +1.9%      +8    UavcanNode::handle_time_sync()
  +0.9%      +8  +0.9%      +8    UavcanNode::init()
   +12%      +8   +12%      +8    UavcanRGBController::~UavcanRGBController()
  +0.1%      +8  +0.1%      +8    px4::parameters
  +4.8%      +4  +4.8%      +4    FlightTask
   +22%      +4   +22%      +4    uavcan::BitSet<>::BitSet()
   +17%      +4   +17%      +4    uavcan::Multiset<>::isEmpty()
  +3.6%      +2  +3.6%      +2    UavcanNode::get_next_active_node_id()
  +5.9%      +2  +5.9%      +2    uavcan::CanFrame::CanFrame()
  -2.5%      -4  -2.5%      -4    Commander::handleCommandsFromModeExecutors()
  -0.3%      -4  -0.3%      -4    UavcanNode::Run()
  -1.9%      -4  -1.9%      -4    UavcanNode::publish_can_interface_statuses()
  -4.1%     -12  -4.1%     -12    UavcanNode::publish_node_statuses()
  [DEL]     -88  [DEL]     -88    UavcanRGBController::brightness_to_rgb565()
[ = ]       0  +0.1%     +64    .bss
  [ = ]       0  +106%     +51    [section .bss]
  [ = ]       0  [NEW]      +8    UavcanRGBController::periodic_update()::color_off
  [ = ]       0  [NEW]      +8    UavcanRGBController::periodic_update()::color_on
  [ = ]       0 -75.0%      -3    _bidirectional
+0.0%     +92  [ = ]       0    .debug_abbrev
+0.0%      +8  [ = ]       0    .debug_aranges
+0.0%     +40  [ = ]       0    .debug_frame
+0.0% +4.60Ki  [ = ]       0    .debug_info
+0.0%    +450  [ = ]       0    .debug_line
   +50%      +2  [ = ]       0    [Unmapped]
  +0.0%    +448  [ = ]       0    [section .debug_line]
+0.0%    +608  [ = ]       0    .debug_loclists
-0.0%     -71  [ = ]       0    .debug_rnglists
  [DEL]      -3  [ = ]       0    [Unmapped]
  -0.0%     -68  [ = ]       0    [section .debug_rnglists]
+0.0% +1.14Ki  [ = ]       0    .debug_str
+1.3%      +3  [ = ]       0    .shstrtab
+0.0%    +265  [ = ]       0    .strtab
  [DEL]     -49  [ = ]       0    UavcanRGBController::brightness_to_rgb565()
  [NEW]    +158  [ = ]       0    UavcanRGBController::periodic_update()::color_off
  [NEW]    +156  [ = ]       0    UavcanRGBController::periodic_update()::color_on
+0.0%     +80  [ = ]       0    .symtab
  [DEL]     -48  [ = ]       0    UavcanRGBController::brightness_to_rgb565()
  [NEW]     +80  [ = ]       0    UavcanRGBController::periodic_update()::color_off
  [NEW]     +64  [ = ]       0    UavcanRGBController::periodic_update()::color_on
  -0.3%     -32  [ = ]       0    [section .symtab]
   +33%     +16  [ = ]       0    _GLOBAL__sub_I__ZN19UavcanRGBControllerC2ERN6uavcan5INodeE
 -33.3%     -16  [ = ]       0    uavcan::CanFrame::CanFrame()
 -50.0%     -16  [ = ]       0    uavcan::Multiset<>::isEmpty()
   +50%     +16  [ = ]       0    uavcan::dynamic_node_id_server::NodeDiscoverer::pickNextNodeToQueryAndCleanupMap()
   +50%     +16  [ = ]       0    uavcan::fill<>()
-3.9%    -272  [ = ]       0    [Unmapped]
+0.0% +7.18Ki  +0.0%    +336    TOTAL

Updated: 2026-01-08T13:53:09

@Claudio-Chies Claudio-Chies marked this pull request as draft January 8, 2026 07:47
@Claudio-Chies Claudio-Chies changed the title UAVCAN: Add LED support with configurable light_id UAVCAN: Add LED Addressing Mode with Vertiq Support Jan 8, 2026
@Claudio-Chies Claudio-Chies marked this pull request as ready for review January 8, 2026 11:14
uint8_t _esc_count{0};

DEFINE_PARAMETERS(
(ParamInt<px4::params::UAVCAN_LGT_MODE>) _param_lgt_mode,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the convention, I know the other fields here were not corrected yet.

Suggested change
(ParamInt<px4::params::UAVCAN_LGT_MODE>) _param_lgt_mode,
(ParamInt<px4::params::UAVCAN_LGT_MODE>) _param_uavcan_lgt_mode,

cmd.color = brightness_to_rgb565(_param_mode_nav.get() >= control_mode ? 255 : 0);
cmds.commands.push_back(cmd);
for (uint8_t esc = 0; esc < _esc_count; esc++) {
cmd.light_id = esc * 3 + VERTIQ_WHITE_BASE_ID;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again the light_id is the only difference, can we not duplicate the rest of the logic?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not because you sent to all ESCs instead of just one ID 🙈

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

/en/peripherals/vertiq.md

  • LinkedFileMissingAnchor: #UAVCAN_LGT_MODE not found in ../advanced_config/parameter_reference.md (/home/runner/work/PX4-Autopilot/PX4-Autopilot/docs/en/advanced_config/parameter_reference.md)

if (vertiq_mode) {
// Vertiq mode: send RGB status to all ESC RGB LEDs
for (uint8_t esc = 0; esc < _vertiq_esc_count; ++esc) {
cmd.light_id = esc * 3 + VERTIQ_RGB_BASE_ID;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you know that the ESC ids are [0, esc_status.esc_count - 1]. This might usually be the case but should at least be noted to be a requirement no?

Comment on lines +189 to +205
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_ANTI_COLLISION;
cmds.commands.push_back(cmd);

// Strobes
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_STROBE;
cmd.color = _param_uavcan_lgt_strob.get() >= control_mode ? color_on : color_off;
cmds.commands.push_back(cmd);

// Nav lights
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_RIGHT_OF_WAY;
cmd.color = _param_uavcan_lgt_nav.get() >= control_mode ? color_on : color_off;
cmds.commands.push_back(cmd);

// Landing lights
cmd.light_id = uavcan::equipment::indication::SingleLightCommand::LIGHT_ID_LANDING;
cmd.color = _param_uavcan_lgt_land.get() >= control_mode ? color_on : color_off;
cmds.commands.push_back(cmd);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not your fault but I'm unsure why these LED types would all need to be configurable to on, off, on arm independently. What are the odds someone has these types and all sets them differently... I'd understand if the land one is on during landing but otherwise I'd just send them out either way or have a bitmask parameter which ones even exist to not flood the CAN bus for the case someone has a light of a certain type 🤷‍♂️

@Claudio-Chies
Copy link
Member Author

Superseeded by #26253

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants