Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions docs/en/dronecan/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,15 @@ PX4 can control LEDs via DroneCAN [LightsCommand](https://dronecan.github.io/Spe

Configuration:

1. Set [UAVCAN_LGT_NUM](../advanced_config/parameter_reference.md#UAVCAN_LGT_NUM) to the number of lights (0 disables). You might need to reopen the ground station to have parameters for new instances available.
1. Set [UAVCAN_LGT_NUM](../advanced_config/parameter_reference.md#UAVCAN_LGT_NUM) to the number of lights (0-2, 0 disables).
You might need to reopen the ground station to have parameters for new instances available.
2. For each light slot (0 to NUM-1), set:
- `UAVCAN_LGT_IDx`: The `light_id` matching your peripheral.
- `UAVCAN_LGT_FNx`: `Status` for system status colours, or `Anti-collision` for white beacon.
3. For anti-collision lights, [UAVCAN_LGT_ANTCL](../advanced_config/parameter_reference.md#UAVCAN_LGT_ANTCL) controls when they illuminate (off, armed, prearmed, always on).
- `UAVCAN_LGT_FNx`: The light function. Available options:
- `Status`: System status colours from the LED controller.
- `Anti-collision` to `White Navigation`: Light functions controlled by `UAVCAN_LGT_MODE`.
- `Status / Anti-collision` to `Status / Off`: Hybrid modes that show status colours when `UAVCAN_LGT_MODE` is inactive, and switch to the second function when active.
3. [UAVCAN_LGT_MODE](../advanced_config/parameter_reference.md#UAVCAN_LGT_MODE) controls when navigation lights turn on (off, armed, prearmed, always on).
4. Reboot for any changes to take effect.

## QGC CANNODE Parameter Configuration
Expand Down
20 changes: 13 additions & 7 deletions src/drivers/uavcan/module.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
__max_num_uavcan_lights: &max_num_uavcan_lights 3 # Needs to be equal to MAX_NUM_UAVCAN_LIGHTS constant
__max_num_uavcan_lights: &max_num_uavcan_lights 2 # NOTE: This value must match MAX_NUM_UAVCAN_LIGHTS in rgbled.hpp


module_name: UAVCAN
parameters:
Expand Down Expand Up @@ -54,18 +55,23 @@ parameters:
description:
short: Light ${i} function
long: |
Function assigned to light ${i}.
0: Status - displays system status colors
1: Anti-collision - white beacon controlled by LGT_ANTCL parameter
Function for light ${i}.
UAVCAN_LGT_MODE turns navigation lights (1-3) on and hybrid functions (4-7) to second option.
type: enum
num_instances: *max_num_uavcan_lights
instance_start: 0
min: 0
max: 1
max: 9
default: 0
values:
0: Status Light
1: Anti-collision Light
0: Status
1: White Navigation
2: Red Navigation
3: Green Navigation
4: Status / White Navigation
5: Status / Red Navigation
6: Status / Green Navigation
7: Status / Off
Comment on lines +67 to +74
Copy link
Contributor

Choose a reason for hiding this comment

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

  1. What are the different navigation types? I.e. does white navigation mean anything vs red navigation? Is this standard aircraft terminology?
  2. What does anti-collision mean - is it just a warning that something is in anti collision mode?
  3. For 4-7 does this mean "nromally in colour navigation but perhaps display a status warning under some conditions? What status are possible.

It seems to me that we need a Led status harware section under https://docs.px4.io/main/en/hardware/drone_parts explaining all this, linking to UAVCAN, listing models that have been tested.

Copy link
Member

Choose a reason for hiding this comment

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

@hamishwillee Thanks for the feedback!

What are the different navigation types?

  1. Good point, it's meant for "navigation lights" that are either white red or green in color. But "Navigation" is confusing here I agree. Let's just specify the color and write navigation light in the description. ⚙️

anti-collision mean

  1. I removed it, was doing the exact same thing as the white LED, need to update docs.
    Background: There is a UAVCAN LED ID for "anti-collision lights" but with UAVCAN: Configurable LED Light Control with Flexible Addressing #26253 you can set any ID you want including that one and we don't need to carry any of this spcifically. I think the users per light ID are really sparse.

For 4-7

  1. Let me try to make a table that we can then put in docs:
    On or off is determined by UAVCAN_LGT_MODE (default when armed = on). And then it follows the table:
UAVCAN_LGT_FNx Off On
0 Off Status
1 Off White
2 Off Red
3 Off Green
4 Status White
5 Status Red
6 Status Green
7 Status Off

actuator_output:
show_subgroups_if: 'UAVCAN_ENABLE>=3'
config_parameters:
Expand Down
132 changes: 87 additions & 45 deletions src/drivers/uavcan/rgbled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ UavcanRGBController::UavcanRGBController(uavcan::INode &node) :
int UavcanRGBController::init()
{
// Cache number of lights (0 disables the feature)
_num_lights = math::min(static_cast<uint8_t>(_param_lgt_num.get()), MAX_NUM_UAVCAN_LIGHTS);
_num_lights = math::min(static_cast<uint8_t>(_param_uavcan_lgt_num.get()), MAX_NUM_UAVCAN_LIGHTS);

if (_num_lights == 0) {
return 0; // Disabled, don't start timer
Expand Down Expand Up @@ -98,74 +98,69 @@ void UavcanRGBController::periodic_update(const uavcan::TimerEvent &)
}

// Compute status color from led_control_data
uavcan::equipment::indication::RGB565 status_color{};
uint8_t brightness = led_control_data.leds[0].brightness;
uavcan::equipment::indication::RGB565 status_color = color_to_rgb565(led_control_data.leds[0].color, led_control_data.leds[0].brightness);

switch (led_control_data.leds[0].color) {
case led_control_s::COLOR_RED:
status_color = rgb888_to_rgb565(brightness, 0, 0);
break;

case led_control_s::COLOR_GREEN:
status_color = rgb888_to_rgb565(0, brightness, 0);
break;

case led_control_s::COLOR_BLUE:
status_color = rgb888_to_rgb565(0, 0, brightness);
break;
// Build and send light commands for all configured lights
uavcan::equipment::indication::LightsCommand light_command;
const bool light_on = is_light_on();

case led_control_s::COLOR_AMBER: // make it the same as yellow
case led_control_s::COLOR_YELLOW:
status_color = rgb888_to_rgb565(brightness, brightness, 0);
break;
for (uint8_t i = 0; i < _num_lights; i++) {
uavcan::equipment::indication::RGB565 color_on, color_off;
color_on = color_off = color_to_rgb565(led_control_s::COLOR_OFF);

case led_control_s::COLOR_PURPLE:
status_color = rgb888_to_rgb565(brightness, 0, brightness);
break;
switch (_light_functions[i]) {
case LightFunction::Status:
color_on = color_off = status_color;
break;

case led_control_s::COLOR_CYAN:
status_color = rgb888_to_rgb565(0, brightness, brightness);
break;
case LightFunction::WhiteNavigation:
color_on = color_to_rgb565(led_control_s::COLOR_WHITE);
break;

case led_control_s::COLOR_WHITE:
status_color = rgb888_to_rgb565(brightness, brightness, brightness);
break;
case LightFunction::RedNavigation:
color_on = color_to_rgb565(led_control_s::COLOR_RED);
break;

default:
case led_control_s::COLOR_OFF:
break;
}
case LightFunction::GreenNavigation:
color_on = color_to_rgb565(led_control_s::COLOR_GREEN);
break;

// Build and send light commands for all configured lights
uavcan::equipment::indication::LightsCommand light_command;
// Hybrid functions: show status when UAVCAN_LGT_MODE inactive, navigation light when active
case LightFunction::StatusOrWhiteNavigation:
color_on = color_to_rgb565(led_control_s::COLOR_WHITE);
color_off = status_color;
break;

for (uint8_t i = 0; i < _num_lights; i++) {
uavcan::equipment::indication::SingleLightCommand cmd;
cmd.light_id = _light_ids[i];
case LightFunction::StatusOrRedNavigation:
color_on = color_to_rgb565(led_control_s::COLOR_RED);
color_off = status_color;
break;

switch (_light_functions[i]) {
case LightFunction::Status:
cmd.color = status_color;
case LightFunction::StatusOrGreenNavigation:
color_on = color_to_rgb565(led_control_s::COLOR_GREEN);
color_off = status_color;
break;

case LightFunction::AntiCollision:
uint8_t brigtness = is_anticolision_on() ? 255 : 0;
cmd.color = rgb888_to_rgb565(brigtness, brigtness, brigtness);
case LightFunction::StatusOrOff:
color_off = status_color;
break;
}

uavcan::equipment::indication::SingleLightCommand cmd;
cmd.light_id = _light_ids[i];
cmd.color = light_on ? color_on : color_off;
light_command.commands.push_back(cmd);
}

_uavcan_pub_lights_cmd.broadcast(light_command);
}

bool UavcanRGBController::is_anticolision_on()
bool UavcanRGBController::is_light_on()
{
actuator_armed_s actuator_armed{};
_actuator_armed_sub.copy(&actuator_armed);

switch (_param_uavcan_lgt_antcl.get()) {
switch (_param_uavcan_lgt_mode.get()) {
case 3: // Always on
return true;

Expand All @@ -181,6 +176,53 @@ bool UavcanRGBController::is_anticolision_on()
}
}

uavcan::equipment::indication::RGB565 UavcanRGBController::color_to_rgb565(uint8_t color, uint8_t brightness)
{
uint8_t R = 0, G = 0, B = 0;

switch (color) {
case led_control_s::COLOR_RED:
R = brightness;
break;

case led_control_s::COLOR_GREEN:
G = brightness;
break;

case led_control_s::COLOR_BLUE:
B = brightness;
break;

case led_control_s::COLOR_AMBER: // make it the same as yellow
case led_control_s::COLOR_YELLOW:
R = brightness;
G = brightness;
break;

case led_control_s::COLOR_PURPLE:
R = brightness;
B = brightness;
break;

case led_control_s::COLOR_CYAN:
G = brightness;
B = brightness;
break;

case led_control_s::COLOR_WHITE:
R = brightness;
G = brightness;
B = brightness;
break;

default:
case led_control_s::COLOR_OFF:
break;
}

return rgb888_to_rgb565(R, G, B);
}

uavcan::equipment::indication::RGB565 UavcanRGBController::rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue)
{
// RGB565: Full brightness is (31, 63, 31), off is (0, 0, 0)
Expand Down
23 changes: 15 additions & 8 deletions src/drivers/uavcan/rgbled.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,26 @@ class UavcanRGBController : public ModuleParams
// Max update rate to avoid excessive bus traffic
static constexpr unsigned MAX_RATE_HZ = 20;

// Maximum number of configurable lights
static constexpr uint8_t MAX_NUM_UAVCAN_LIGHTS = 3;
// NOTE: This value must match __max_num_uavcan_lights in module.yaml
static constexpr uint8_t MAX_NUM_UAVCAN_LIGHTS = 2;

// Light function types
// Light function types - must match values in module.yaml UAVCAN_LGT_FN
enum class LightFunction : uint8_t {
Status = 0, // System status colors from led_control
AntiCollision = 1 // White beacon based on arm state
Status = 0,
WhiteNavigation = 1,
RedNavigation = 2,
GreenNavigation = 3,
StatusOrWhiteNavigation = 4,
StatusOrRedNavigation = 5,
StatusOrGreenNavigation = 6,
StatusOrOff = 7
};

void periodic_update(const uavcan::TimerEvent &);

bool is_anticolision_on(); ///< Evaluates current on state of collision lights accordingt to UAVCAN_LGT_ANTCL
bool is_light_on();

uavcan::equipment::indication::RGB565 color_to_rgb565(uint8_t color, uint8_t brightness = 255);
uavcan::equipment::indication::RGB565 rgb888_to_rgb565(uint8_t red, uint8_t green, uint8_t blue);

typedef uavcan::MethodBinder<UavcanRGBController *, void (UavcanRGBController::*)(const uavcan::TimerEvent &)>
Expand All @@ -90,7 +97,7 @@ class UavcanRGBController : public ModuleParams
param_t _light_fn_params[MAX_NUM_UAVCAN_LIGHTS] {};

DEFINE_PARAMETERS(
(ParamInt<px4::params::UAVCAN_LGT_NUM>) _param_lgt_num,
(ParamInt<px4::params::UAVCAN_LGT_ANTCL>) _param_uavcan_lgt_antcl
(ParamInt<px4::params::UAVCAN_LGT_NUM>) _param_uavcan_lgt_num,
(ParamInt<px4::params::UAVCAN_LGT_MODE>) _param_uavcan_lgt_mode
)
};
10 changes: 7 additions & 3 deletions src/drivers/uavcan/uavcan_params.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,14 @@ PARAM_DEFINE_FLOAT(UAVCAN_ECU_MAXF, 15.0f);
PARAM_DEFINE_INT32(UAVCAN_ECU_FUELT, 1);

/**
* UAVCAN ANTI_COLLISION light operating mode
* UAVCAN Navigation light operating mode
*
* This parameter defines the minimum condition under which the system will command
* lights with anti-collision function to turn on (white).
* Navigation lights to turn on. Affects lights with functions: Anti-collision, Colored Navigation Lights or Hybrid lights.
*
* For hybrid functions (StatusOrAntiCollision, etc.), the light
* displays status colors when this mode is inactive, and switches to the
* navigation light function when this mode becomes active.
*
* 0 - Always off
* 1 - When autopilot is armed
Expand All @@ -151,7 +155,7 @@ PARAM_DEFINE_INT32(UAVCAN_ECU_FUELT, 1);
* @reboot_required true
* @group UAVCAN
*/
PARAM_DEFINE_INT32(UAVCAN_LGT_ANTCL, 2);
PARAM_DEFINE_INT32(UAVCAN_LGT_MODE, 1);

/**
* publish Arming Status stream
Expand Down
Loading