Skip to content

AP_Scripting: add CircuitStatus DroneCAN battery driver#33763

Open
tridge wants to merge 3 commits into
ArduPilot:masterfrom
tridge:circuit-status
Open

AP_Scripting: add CircuitStatus DroneCAN battery driver#33763
tridge wants to merge 3 commits into
ArduPilot:masterfrom
tridge:circuit-status

Conversation

@tridge

@tridge tridge commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a lua driver for the DroneCAN uavcan.equipment.power.CircuitStatus message, mapping individual circuits onto ArduPilot battery monitor instances, with SITL support and an autotest.

Classification & Testing (check all that apply and add your own)

  • Checked by a human programmer
  • Non-functional change
  • No-binary change
  • Infrastructure change (e.g. unit tests, helper scripts)
  • Automated test(s) verify changes (e.g. unit test, autotest)
  • Tested manually, description below (e.g. SITL)
  • Tested on hardware
  • Logs attached
  • Logs available on request

The new QuadPlane.CircuitStatusScript autotest boots the quadplane-can frame with the driver installed and checks that two scripting monitors fed from CircuitStatus match a DroneCAN reference monitor on the same periph battery for both voltage and current, which also covers the float16 decoding.

Description

This allows per-circuit voltage and current from a CAN power distribution board to be monitored, logged and reported as batteries.

The number of circuits is set with DCS_NUM_CIRCUITS, which dynamically creates DCSx_CIRCUIT_ID and DCSx_BATT_IDX parameters mapping each circuit_id to a battery monitor instance with BATTn_MONITOR=29 (scripting). Circuit mappings are picked up at runtime, only DCS_NUM_CIRCUITS needs a reboot.

To enable testing, the SITL AP_Periph build now sends a CircuitStatus message per active battery backend, and the quadplane-can frame gained a periph_board entry so restart_SITL_frame() can spawn the periph companion in autotests (sim_vehicle.py already defaulted to sitl_periph_universal for this frame).

Tested in SITL and on a CubeOrangePlus with HFE engine which has 3 CircuitStatus messages

tridge added 2 commits July 18, 2026 08:37
maps uavcan.equipment.power.CircuitStatus circuits onto scripting
battery monitor instances, giving per-circuit voltage and current
monitoring from CAN power distribution nodes
sends a CircuitStatus message per active battery backend with
circuit_id of the instance number plus one, allowing testing of the
CircuitStatus lua driver
adds periph_board to the quadplane-can frame so restart_SITL_frame
spawns the AP_Periph companion, driver script install helpers and a
plane test checking that scripting monitors fed from CircuitStatus
match a DroneCAN reference monitor on the same periph battery
@Hwurzburg

Copy link
Copy Markdown
Contributor

Is there an actual device/product that can use this? we could add into the wiki

@tridge

tridge commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

Is there an actual device/product that can use this? we could add into the wiki

CircuitStatus is used by quite a few devices, its a generic DroneCAN way of reporting a voltage and current. I've seen it on quite a few devices, although the motivation for this work was for a HFE EFI setup on a large quadplane.


The script uses the following parameters:

## DCS_NUM_CIRCUITS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be nested more deeply

Comment on lines +33 to +34
This driver should be loaded by placing the lua script in the
APM/SCRIPTS directory on the microSD card, which can be done either

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably not. Probably should be built into ROMFS on systems advanced enough to use it.

#endif
void can_battery_update();
void can_battery_send_cells(uint8_t instance);
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
#if AP_PERIPH_CAN_CIRCUIT_SENDING_ENABLED

.... make that new define dependent on AP_PERIPH_BATTERY_ENABLED at the very least

void can_battery_send_cells(uint8_t instance);
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
void can_circuit_status_update();
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
#endif
#endif // AP_PERIPH_CAN_CIRCUIT_SENDING_ENABLED

useful for conflict resolution - several bugs fixed recently because this wasn't done

struct {
uint32_t last_read_ms;
uint32_t last_can_send_ms;
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
#if AP_PERIPH_CAN_CIRCUIT_SENDING_ENABLED

etc

for _, h in ipairs(handles) do
-- drain all pending messages
while true do
local payload, _ = h:check_message()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We're dropping information about the source here. Meaning circuitstatus id must be unique on the bus. Worth documenting, at least.

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