[pca9685] Allow to disable the phase balancer for PCA9685 (#9792)

This commit is contained in:
Johannes Nau
2025-12-08 16:34:26 +01:00
committed by GitHub
parent eda743ee48
commit 7e486b1c25
4 changed files with 36 additions and 2 deletions

View File

@@ -1,7 +1,12 @@
import esphome.codegen as cg
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import CONF_EXTERNAL_CLOCK_INPUT, CONF_FREQUENCY, CONF_ID
from esphome.const import (
CONF_EXTERNAL_CLOCK_INPUT,
CONF_FREQUENCY,
CONF_ID,
CONF_PHASE_BALANCER,
)
DEPENDENCIES = ["i2c"]
MULTI_CONF = True
@@ -9,6 +14,12 @@ MULTI_CONF = True
pca9685_ns = cg.esphome_ns.namespace("pca9685")
PCA9685Output = pca9685_ns.class_("PCA9685Output", cg.Component, i2c.I2CDevice)
phase_balancer = pca9685_ns.enum("PhaseBalancer", is_class=True)
PHASE_BALANCERS = {
"none": phase_balancer.NONE,
"linear": phase_balancer.LINEAR,
}
def validate_frequency(config):
if config[CONF_EXTERNAL_CLOCK_INPUT]:
@@ -30,6 +41,9 @@ CONFIG_SCHEMA = cv.All(
cv.frequency, cv.Range(min=23.84, max=1525.88)
),
cv.Optional(CONF_EXTERNAL_CLOCK_INPUT, default=False): cv.boolean,
cv.Optional(CONF_PHASE_BALANCER, default="linear"): cv.enum(
PHASE_BALANCERS
),
}
)
.extend(cv.COMPONENT_SCHEMA)
@@ -43,5 +57,6 @@ async def to_code(config):
if CONF_FREQUENCY in config:
cg.add(var.set_frequency(config[CONF_FREQUENCY]))
cg.add(var.set_extclk(config[CONF_EXTERNAL_CLOCK_INPUT]))
cg.add(var.set_phase_balancer(config[CONF_PHASE_BALANCER]))
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)

View File

@@ -105,7 +105,18 @@ void PCA9685Output::loop() {
const uint16_t num_channels = this->max_channel_ - this->min_channel_ + 1;
const uint16_t phase_delta_begin = 4096 / num_channels;
for (uint8_t channel = this->min_channel_; channel <= this->max_channel_; channel++) {
uint16_t phase_begin = (channel - this->min_channel_) * phase_delta_begin;
uint16_t phase_begin;
switch (this->balancer_) {
case PhaseBalancer::NONE:
phase_begin = 0;
break;
case PhaseBalancer::LINEAR:
phase_begin = (channel - this->min_channel_) * phase_delta_begin;
break;
default:
ESP_LOGE(TAG, "Unknown phase balancer %d", static_cast<int>(this->balancer_));
return;
}
uint16_t phase_end;
uint16_t amount = this->pwm_amounts_[channel];
if (amount == 0) {

View File

@@ -7,6 +7,11 @@
namespace esphome {
namespace pca9685 {
enum class PhaseBalancer {
NONE = 0x00,
LINEAR = 0x01,
};
/// Inverts polarity of channel output signal
extern const uint8_t PCA9685_MODE_INVERTED;
/// Channel update happens upon ACK (post-set) rather than on STOP (endTransmission)
@@ -47,6 +52,7 @@ class PCA9685Output : public Component, public i2c::I2CDevice {
void loop() override;
void set_extclk(bool extclk) { this->extclk_ = extclk; }
void set_frequency(float frequency) { this->frequency_ = frequency; }
void set_phase_balancer(PhaseBalancer balancer) { this->balancer_ = balancer; }
protected:
friend PCA9685Channel;
@@ -60,6 +66,7 @@ class PCA9685Output : public Component, public i2c::I2CDevice {
float frequency_;
uint8_t mode_;
bool extclk_ = false;
PhaseBalancer balancer_ = PhaseBalancer::LINEAR;
uint8_t min_channel_{0xFF};
uint8_t max_channel_{0x00};

View File

@@ -2,6 +2,7 @@ pca9685:
i2c_id: i2c_bus
frequency: 500
address: 0x0
phase_balancer: linear
output:
- platform: pca9685