From 12745baf6cf8c30ecd9bf565583eb7e69ed2f57e Mon Sep 17 00:00:00 2001 From: Alex Klimaj Date: Fri, 12 Dec 2025 11:31:19 -0700 Subject: [PATCH] Adds configurable I2C address for PCA9685 PWM driver (#26051) * Adds configurable I2C address for PCA9685 PWM driver Introduces a parameter to set the I2C address for the PCA9685 PWM output driver, enhancing flexibility for hardware variations. Updates documentation and board initialization scripts to support the new configuration and streamline device startup. * Update src/drivers/pca9685_pwm_out/module.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/drivers/pca9685_pwm_out/module.yaml --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jacob Dahl <37091262+dakejahl@users.noreply.github.com> --- boards/ark/fmu-v6x/default.px4board | 1 + boards/ark/fmu-v6x/init/rc.board_sensors | 6 +++++ boards/ark/fpv/default.px4board | 1 + boards/ark/fpv/init/rc.board_sensors | 6 +++++ boards/ark/pi6x/default.px4board | 1 + boards/ark/pi6x/init/rc.board_sensors | 6 +++++ boards/auterion/fmu-v6s/init/rc.board_sensors | 2 +- .../navigator/init/rc.board_defaults | 4 +++ .../navigator/init/rc.board_sensors | 2 +- .../en/advanced_config/parameter_reference.md | 10 +++++++ docs/en/modules/modules_driver.md | 2 ++ src/drivers/pca9685_pwm_out/main.cpp | 27 +++++++++++++++++-- src/drivers/pca9685_pwm_out/module.yaml | 10 +++++++ 13 files changed, 74 insertions(+), 4 deletions(-) diff --git a/boards/ark/fmu-v6x/default.px4board b/boards/ark/fmu-v6x/default.px4board index e2433a53cb..d72a3f8a4e 100644 --- a/boards/ark/fmu-v6x/default.px4board +++ b/boards/ark/fmu-v6x/default.px4board @@ -40,6 +40,7 @@ CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y CONFIG_DRIVERS_POWER_MONITOR_INA226=y CONFIG_DRIVERS_POWER_MONITOR_INA228=y CONFIG_DRIVERS_POWER_MONITOR_INA238=y +CONFIG_DRIVERS_PCA9685_PWM_OUT=y CONFIG_DRIVERS_PWM_OUT=y CONFIG_DRIVERS_PX4IO=y CONFIG_COMMON_RC=y diff --git a/boards/ark/fmu-v6x/init/rc.board_sensors b/boards/ark/fmu-v6x/init/rc.board_sensors index c16ed31f69..7b2259f8ad 100644 --- a/boards/ark/fmu-v6x/init/rc.board_sensors +++ b/boards/ark/fmu-v6x/init/rc.board_sensors @@ -97,5 +97,11 @@ bmm150 -I start # Internal Baro on I2C bmp388 -I start +# Start an external PWM generator +if param greater PCA9685_EN_BUS 0 +then + pca9685_pwm_out start +fi + unset HAVE_PM2 unset HAVE_PM3 diff --git a/boards/ark/fpv/default.px4board b/boards/ark/fpv/default.px4board index abea5574b0..d4515d5f67 100644 --- a/boards/ark/fpv/default.px4board +++ b/boards/ark/fpv/default.px4board @@ -21,6 +21,7 @@ CONFIG_DRIVERS_IMU_MURATA_SCH16T=y CONFIG_COMMON_LIGHT=y CONFIG_COMMON_MAGNETOMETER=y CONFIG_DRIVERS_OSD_MSP_OSD=y +CONFIG_DRIVERS_PCA9685_PWM_OUT=y CONFIG_DRIVERS_PWM_OUT=y CONFIG_COMMON_RC=y CONFIG_DRIVERS_UAVCAN=y diff --git a/boards/ark/fpv/init/rc.board_sensors b/boards/ark/fpv/init/rc.board_sensors index 896b9ffd7d..e719938f86 100644 --- a/boards/ark/fpv/init/rc.board_sensors +++ b/boards/ark/fpv/init/rc.board_sensors @@ -16,3 +16,9 @@ iis2mdc -R 0 -I -b 4 start # Internal Baro on I2C bmp388 -I -b 2 start + +# Start an external PWM generator +if param greater PCA9685_EN_BUS 0 +then + pca9685_pwm_out start +fi diff --git a/boards/ark/pi6x/default.px4board b/boards/ark/pi6x/default.px4board index dda45cdf23..6ad26366b3 100644 --- a/boards/ark/pi6x/default.px4board +++ b/boards/ark/pi6x/default.px4board @@ -19,6 +19,7 @@ CONFIG_COMMON_LIGHT=y CONFIG_DRIVERS_MAGNETOMETER_MEMSIC_MMC5983MA=y CONFIG_DRIVERS_MAGNETOMETER_ST_IIS2MDC=y CONFIG_DRIVERS_OPTICAL_FLOW_PAW3902=y +CONFIG_DRIVERS_PCA9685_PWM_OUT=y CONFIG_DRIVERS_POWER_MONITOR_INA226=y CONFIG_DRIVERS_PWM_OUT=y CONFIG_COMMON_RC=y diff --git a/boards/ark/pi6x/init/rc.board_sensors b/boards/ark/pi6x/init/rc.board_sensors index cc97b1d601..c128fbca35 100644 --- a/boards/ark/pi6x/init/rc.board_sensors +++ b/boards/ark/pi6x/init/rc.board_sensors @@ -34,3 +34,9 @@ paw3902 -s -b 3 start -Y 90 # Internal distance sensor afbrs50 start + +# Start an external PWM generator +if param greater PCA9685_EN_BUS 0 +then + pca9685_pwm_out start +fi diff --git a/boards/auterion/fmu-v6s/init/rc.board_sensors b/boards/auterion/fmu-v6s/init/rc.board_sensors index 4c4be283d7..ccf6536cf0 100644 --- a/boards/auterion/fmu-v6s/init/rc.board_sensors +++ b/boards/auterion/fmu-v6s/init/rc.board_sensors @@ -74,5 +74,5 @@ ist8310 -X -b 1 -R 10 start # Start an external PWM generator if param greater PCA9685_EN_BUS 0 then - pca9685_pwm_out start -b 1 + pca9685_pwm_out start fi diff --git a/boards/bluerobotics/navigator/init/rc.board_defaults b/boards/bluerobotics/navigator/init/rc.board_defaults index 18dc930ba7..ca136db1e3 100644 --- a/boards/bluerobotics/navigator/init/rc.board_defaults +++ b/boards/bluerobotics/navigator/init/rc.board_defaults @@ -11,3 +11,7 @@ param set BAT1_V_DIV 5.7 # Always keep current config param set SYS_AUTOCONFIG 0 + +# PCA9685 PWM Out defaults +param set-default PCA9685_EN_BUS 4 +param set-default PCA9685_I2C_ADDR 64 diff --git a/boards/bluerobotics/navigator/init/rc.board_sensors b/boards/bluerobotics/navigator/init/rc.board_sensors index 411995664b..790099d8af 100644 --- a/boards/bluerobotics/navigator/init/rc.board_sensors +++ b/boards/bluerobotics/navigator/init/rc.board_sensors @@ -28,7 +28,7 @@ then echo "ads1115 not found." fi -if ! pca9685_pwm_out start -a 0x40 -b 4 +if ! pca9685_pwm_out start then echo "pca9685_pwm_out not found." fi diff --git a/docs/en/advanced_config/parameter_reference.md b/docs/en/advanced_config/parameter_reference.md index a9a13e4984..aa05292a85 100644 --- a/docs/en/advanced_config/parameter_reference.md +++ b/docs/en/advanced_config/parameter_reference.md @@ -486,6 +486,16 @@ The integer refers to the I2C bus number where PCA9685 is connected. | ------ | -------- | -------- | --------- | ------- | ---- | |   | 0 | 10 | | 0 | +### PCA9685_I2C_ADDR (`INT32`) {#PCA9685_I2C_ADDR} + +I2C address of PCA9685. + +The default address is 0x40 (64). + +| Reboot | minValue | maxValue | increment | default | unit | +| ------ | -------- | -------- | --------- | ------- | ---- | +|   | 0 | 127 | | 64 | + ### PCA9685_FAIL1 (`INT32`) {#PCA9685_FAIL1} PCA9685 Output Channel 1 Failsafe Value. diff --git a/docs/en/modules/modules_driver.md b/docs/en/modules/modules_driver.md index 2b0b2a6b7e..9db2c26c0c 100644 --- a/docs/en/modules/modules_driver.md +++ b/docs/en/modules/modules_driver.md @@ -899,6 +899,8 @@ fetching the latest mixing result and write them to PCA9685 at its scheduling ti It can do full 12bits output as duty-cycle mode, while also able to output precious pulse width that can be accepted by most ESCs and servos. +The I2C bus and address can be configured via parameters `PCA9685_EN_BUS` and `PCA9685_I2C_ADDR`, or via command line arguments. + ### Examples It is typically started with: diff --git a/src/drivers/pca9685_pwm_out/main.cpp b/src/drivers/pca9685_pwm_out/main.cpp index 2d22c36a77..44464e9511 100644 --- a/src/drivers/pca9685_pwm_out/main.cpp +++ b/src/drivers/pca9685_pwm_out/main.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include "PCA9685.h" @@ -356,8 +357,30 @@ int PCA9685Wrapper::custom_command(int argc, char **argv) { int PCA9685Wrapper::task_spawn(int argc, char **argv) { int ch; - int address=PCA9685_DEFAULT_ADDRESS; - int iicbus=PCA9685_DEFAULT_IICBUS; + int address = PCA9685_DEFAULT_ADDRESS; + int iicbus = PCA9685_DEFAULT_IICBUS; + + int32_t en_bus = 0; + param_t param_handle = param_find("PCA9685_EN_BUS"); + + if (param_handle != PARAM_INVALID) { + param_get(param_handle, &en_bus); + + if (en_bus > 0) { + iicbus = en_bus; + } + } + + int32_t i2c_addr = 0; + param_handle = param_find("PCA9685_I2C_ADDR"); + + if (param_handle != PARAM_INVALID) { + param_get(param_handle, &i2c_addr); + + if (i2c_addr > 0) { + address = i2c_addr; + } + } int myoptind = 1; const char *myoptarg = nullptr; diff --git a/src/drivers/pca9685_pwm_out/module.yaml b/src/drivers/pca9685_pwm_out/module.yaml index 57294c0c81..18d999830a 100644 --- a/src/drivers/pca9685_pwm_out/module.yaml +++ b/src/drivers/pca9685_pwm_out/module.yaml @@ -29,6 +29,16 @@ parameters: min: 0 max: 10 default: 0 + PCA9685_I2C_ADDR: + description: + short: I2C address of PCA9685 + long: | + I2C address of PCA9685. + The default address is 0x40 (64). + type: int32 + min: 1 + max: 127 + default: 64 PCA9685_SCHD_HZ: description: short: PWM update rate