9 static const char *
const TAG =
"pca9685";
17 static const uint8_t PCA9685_REGISTER_SOFTWARE_RESET = 0x06;
18 static const uint8_t PCA9685_REGISTER_MODE1 = 0x00;
19 static const uint8_t PCA9685_REGISTER_MODE2 = 0x01;
20 static const uint8_t PCA9685_REGISTER_LED0 = 0x06;
21 static const uint8_t PCA9685_REGISTER_PRE_SCALE = 0xFE;
23 static const uint8_t PCA9685_MODE1_RESTART = 0b10000000;
24 static const uint8_t PCA9685_MODE1_EXTCLK = 0b01000000;
25 static const uint8_t PCA9685_MODE1_AUTOINC = 0b00100000;
26 static const uint8_t PCA9685_MODE1_SLEEP = 0b00010000;
29 ESP_LOGCONFIG(TAG,
"Setting up PCA9685OutputComponent...");
31 ESP_LOGV(TAG,
" Resetting devices...");
32 uint8_t address_tmp = this->
address_;
34 if (!this->
write_bytes(PCA9685_REGISTER_SOFTWARE_RESET,
nullptr, 0)) {
40 if (!this->
write_byte(PCA9685_REGISTER_MODE1, PCA9685_MODE1_RESTART | PCA9685_MODE1_AUTOINC)) {
50 if (!this->
read_byte(PCA9685_REGISTER_MODE1, &mode1)) {
54 mode1 = (mode1 & ~PCA9685_MODE1_RESTART) | PCA9685_MODE1_SLEEP;
55 if (!this->
write_byte(PCA9685_REGISTER_MODE1, mode1)) {
62 mode1 = mode1 | PCA9685_MODE1_EXTCLK;
63 if (!this->
write_byte(PCA9685_REGISTER_MODE1, mode1)) {
68 pre_scaler =
static_cast<int>((25000000 / (4096 * this->
frequency_)) - 1);
69 pre_scaler =
clamp(pre_scaler, 3, 255);
71 ESP_LOGV(TAG,
" -> Prescaler: %d", pre_scaler);
73 if (!this->
write_byte(PCA9685_REGISTER_PRE_SCALE, pre_scaler)) {
78 mode1 = (mode1 & ~PCA9685_MODE1_SLEEP) | PCA9685_MODE1_RESTART;
79 if (!this->
write_byte(PCA9685_REGISTER_MODE1, mode1)) {
89 ESP_LOGCONFIG(TAG,
"PCA9685:");
90 ESP_LOGCONFIG(TAG,
" Mode: 0x%02X", this->
mode_);
92 ESP_LOGCONFIG(TAG,
" EXTCLK: enabled");
94 ESP_LOGCONFIG(TAG,
" EXTCLK: disabled");
95 ESP_LOGCONFIG(TAG,
" Frequency: %.0f Hz", this->
frequency_);
98 ESP_LOGE(TAG,
"Setting up PCA9685 failed!");
107 for (uint8_t channel = this->min_channel_; channel <= this->
max_channel_; channel++) {
108 uint16_t phase_begin = uint16_t(channel - this->min_channel_) / num_channels * 4096;
113 }
else if (amount >= 4096) {
117 phase_end = phase_begin + amount;
118 if (phase_end >= 4096)
122 ESP_LOGVV(TAG,
"Channel %02u: amount=%04u phase_begin=%04u phase_end=%04u", channel, amount, phase_begin,
126 data[0] = phase_begin & 0xFF;
127 data[1] = (phase_begin >> 8) & 0xFF;
128 data[2] = phase_end & 0xFF;
129 data[3] = (phase_end >> 8) & 0xFF;
131 uint8_t
reg = PCA9685_REGISTER_LED0 + 4 * channel;
150 const uint16_t max_duty = 4096;
151 const float duty_rounded = roundf(state * max_duty);
152 auto duty =
static_cast<uint16_t
>(duty_rounded);
153 this->parent_->set_channel_value_(this->channel_, duty);
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
const uint8_t PCA9685_MODE_OUTPUT_ONACK
Channel update happens upon ACK (post-set) rather than on STOP (endTransmission)
I2CRegister reg(uint8_t a_register)
const uint8_t PCA9685_MODE_INVERTED
Inverts polarity of channel output signal.
void set_parent(PCA9685Output *parent)
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
void dump_config() override
void register_channel(PCA9685Channel *channel)
void status_clear_warning()
void status_set_warning()
void write_state(float state) override
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
virtual void mark_failed()
Mark this component as failed.
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
const uint8_t PCA9685_MODE_OUTPUT_TOTEM_POLE
Use a totem-pole (push-pull) style output rather than an open-drain structure.
const uint8_t PCA9685_MODE_OUTNE_HIGHZ
For active low output enable, sets channel output to high-impedance state.
uint16_t pwm_amounts_[16]
void set_i2c_address(uint8_t address)
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len, bool stop=true)
const uint8_t PCA9685_MODE_OUTNE_LOW
Similarly, sets channel output to high if in totem-pole mode, otherwise.