1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-16 07:38:17 +00:00

Correction to make DS2406 functional with or without crc

This commit is contained in:
Thierry DUVERNOY 2025-01-25 14:14:49 +01:00
parent d935b4066c
commit 93efb803fb
5 changed files with 68 additions and 33 deletions

View File

@ -62,11 +62,9 @@ void DallasPioBinarySensor::update() {
} }
this->status_clear_warning(); this->status_clear_warning();
if (this->reference_ == "DS2413") {
if (!this->dallas_pio_->read_state(state, this->pin_)) { if (!this->dallas_pio_->read_state(state, this->pin_)) {
return; return;
} }
}
if (this->pin_inverted_) { if (this->pin_inverted_) {
state = !state; state = !state;

View File

@ -67,28 +67,32 @@ void DallasPio::dump_config() {
bool DallasPio::read_state(uint8_t &state, uint8_t pin) { bool DallasPio::read_state(uint8_t &state, uint8_t pin) {
this->pin_ = pin; this->pin_ = pin;
if (this->reference_ == "DS2413") { if (this->reference_ == "DS2413") {
// ESP_LOGD(TAG, "DallasPio read_state %u pin %u", state, this->pin_); // ESP_LOGD(TAG, "DallasPio DS2413 read_state %u pin %u", state, this->pin_);
return this->ds2413_get_state_(state); return this->ds2413_get_state_(state);
} else if (this->reference_ == "DS2406") { } else if (this->reference_ == "DS2406") {
// ESP_LOGD(TAG, "DallasPio DS2406 read_state %u pin %u", state, this->pin_);
return this->ds2406_get_state_(state, this->crc_enabled_); return this->ds2406_get_state_(state, this->crc_enabled_);
// ESP_LOGD(TAG, "DallasPio DS2408 read_state %u pin %u", state, this->pin_);
} else if (this->reference_ == "DS2408") { } else if (this->reference_ == "DS2408") {
return this->ds2408_get_state_(state, this->crc_enabled_); return this->ds2408_get_state_(state, this->crc_enabled_);
} }
return true; return false;
} }
bool DallasPio::write_state(bool state, uint8_t pin, bool pin_inverted) { bool DallasPio::write_state(bool state, uint8_t pin, bool pin_inverted) {
this->pin_ = pin; this->pin_ = pin;
this->pin_inverted_ = pin_inverted; this->pin_inverted_ = pin_inverted;
// ESP_LOGW(TAG, "DallasPio write_state %u pin %u pin_ %u", state, pin, this->pin_);
if (this->reference_ == "DS2413") { if (this->reference_ == "DS2413") {
// ESP_LOGD(TAG, "DallasPio DS2413 write_state %u pin %u pin_ %u", state, pin, this->pin_);
this->ds2413_write_state_(state); this->ds2413_write_state_(state);
} else if (this->reference_ == "DS2406") { } else if (this->reference_ == "DS2406") {
ESP_LOGD(TAG, "DallasPio DS2406 write_state %u pin %u pin_ %u", state, pin, this->pin_);
this->ds2406_write_state_(state, this->crc_enabled_); this->ds2406_write_state_(state, this->crc_enabled_);
} else if (this->reference_ == "DS2408") { } else if (this->reference_ == "DS2408") {
// ESP_LOGD(TAG, "DallasPio DS2408 write_state %u pin %u pin_ %u", state, pin, this->pin_);
this->ds2408_write_state_(state, this->crc_enabled_); this->ds2408_write_state_(state, this->crc_enabled_);
} }
return true; return false;
} }
/************/ /************/
@ -115,7 +119,7 @@ bool DallasPio::ds2413_get_state_(uint8_t &state) {
} }
{ {
InterruptLock lock; InterruptLock lock;
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_READ); this->send_command_(DALLAS_DS2413_COMMAND_PIO_ACCESS_READ);
results = this->bus_->read8(); results = this->bus_->read8();
} }
ok = (~results & 0x0F) == (results >> 4); ok = (~results & 0x0F) == (results >> 4);
@ -174,12 +178,12 @@ void DallasPio::ds2413_write_state_(bool state) {
} }
{ {
InterruptLock lock; InterruptLock lock;
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_WRITE); this->send_command_(DALLAS_DS2413_COMMAND_PIO_ACCESS_WRITE);
this->bus_->write8(this->pio_output_register_); // Send data this->bus_->write8(this->pio_output_register_); // Send data
this->bus_->write8(~this->pio_output_register_); // Invert data and resend this->bus_->write8(~this->pio_output_register_); // Invert data and resend
ack = this->bus_->read8(); // 0xAA=success, 0xFF=failure ack = this->bus_->read8(); // 0xAA=success, 0xFF=failure
} }
if (ack == DALLAS_COMMAND_PIO_ACK_SUCCESS) { if (ack == DALLAS_DS2413_COMMAND_PIO_ACK_SUCCESS) {
this->bus_->read8(); // Read the PIOA PIOB status byte this->bus_->read8(); // Read the PIOA PIOB status byte
} else { } else {
return; return;
@ -218,7 +222,8 @@ bool DallasPio::ds2406_get_state_(uint8_t &state, bool use_crc = false) {
uint8_t channel_control_byte_1; uint8_t channel_control_byte_1;
uint8_t channel_control_byte_2 = 0xFF; uint8_t channel_control_byte_2 = 0xFF;
uint8_t channel_info_byte; uint8_t channel_info_byte;
uint8_t received_crc = 0; uint8_t pio_input_state;
uint16_t received_crc = 0;
const char *str_pio = nullptr; const char *str_pio = nullptr;
// Initialize One-Wire bus for this device // Initialize One-Wire bus for this device
if (!this->check_address_()) { if (!this->check_address_()) {
@ -243,21 +248,29 @@ bool DallasPio::ds2406_get_state_(uint8_t &state, bool use_crc = false) {
} }
{ {
InterruptLock lock; InterruptLock lock;
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_READ); this->send_command_(DALLAS_DS2406_COMMAND_CHANNEL_ACCESS);
// write CHANNEL CONTROL BYTE 1 // write CHANNEL CONTROL BYTE 1
this->bus_->write8(channel_control_byte_1); this->bus_->write8(channel_control_byte_1);
// write CHANNEL CONTROL BYTE 2 // write CHANNEL CONTROL BYTE 2
this->bus_->write8(channel_control_byte_2); this->bus_->write8(channel_control_byte_2);
// read CHANNEL INFO BYTE // read CHANNEL INFO BYTE
channel_info_byte = this->bus_->read8(); channel_info_byte = this->bus_->read8();
// Read Bits from PioA and PioB
pio_input_state = this->bus_->read8();
if (use_crc) { if (use_crc) {
received_crc = this->bus_->read8(); received_crc = this->bus_->read8();
received_crc |= ((unsigned int) (this->bus_->read8())) << 8;
} }
} }
if (use_crc) { if (use_crc) {
ESP_LOGD(TAG, "CRC for Channel Info Byte: 0x%04X", use_crc); if (!this->ds2406_verify_crc_(channel_control_byte_1, channel_control_byte_2, channel_info_byte, pio_input_state,
if (!this->ds2406_verify_crc_(channel_control_byte_1, channel_control_byte_2, channel_info_byte, received_crc)) { received_crc)) {
ESP_LOGW(TAG, "CRC verification failed!"); ESP_LOGD(TAG, "channel_control_byte_1: 0x%04X", channel_control_byte_1);
ESP_LOGD(TAG, "channel_control_byte_2: 0x%04X", channel_control_byte_2);
ESP_LOGD(TAG, "channel_info_byte: 0x%04X", channel_info_byte);
ESP_LOGD(TAG, "pio_input_state: 0x%04X", pio_input_state);
ESP_LOGD(TAG, "Received CRC: 0x%04X", received_crc);
ESP_LOGW(TAG, "Read CRC verification failed!");
this->status_set_warning(); this->status_set_warning();
return false; return false;
} }
@ -357,15 +370,34 @@ void DallasPio::ds2406_write_state_(bool state, bool use_crc = false) {
} }
uint8_t channel_control_byte_2 = 0xFF; uint8_t channel_control_byte_2 = 0xFF;
uint8_t channel_info_byte; uint8_t channel_info_byte;
uint16_t received_crc = 0;
uint8_t ds2406_write_state = state ? 0xFF : 0x00;
{ {
InterruptLock lock; InterruptLock lock;
this->send_command_(DALLAS_COMMAND_PIO_ACCESS_READ); this->send_command_(DALLAS_DS2406_COMMAND_CHANNEL_ACCESS);
// write CHANNEL CONTROL BYTE 1 // write CHANNEL CONTROL BYTE 1
this->bus_->write8(channel_control_byte_1); this->bus_->write8(channel_control_byte_1);
// write CHANNEL CONTROL BYTE 2 // write CHANNEL CONTROL BYTE 2
this->bus_->write8(channel_control_byte_2); this->bus_->write8(channel_control_byte_2);
channel_info_byte = this->bus_->read8(); channel_info_byte = this->bus_->read8();
this->bus_->write8(state ? 0xFF : 0x00); this->bus_->write8(ds2406_write_state);
if (use_crc) {
received_crc = this->bus_->read8();
received_crc |= ((unsigned int) (this->bus_->read8())) << 8;
}
}
if (use_crc) {
if (!this->ds2406_verify_crc_(channel_control_byte_1, channel_control_byte_2, channel_info_byte, ds2406_write_state,
received_crc)) {
ESP_LOGD(TAG, "channel_control_byte_1: 0x%04X", channel_control_byte_1);
ESP_LOGD(TAG, "channel_control_byte_2: 0x%04X", channel_control_byte_2);
ESP_LOGD(TAG, "channel_info_byte: 0x%04X", channel_info_byte);
ESP_LOGD(TAG, "ds2406_write_state: 0x%04X", ds2406_write_state);
ESP_LOGD(TAG, "Received CRC: 0x%04X", received_crc);
ESP_LOGW(TAG, "Write CRC verification failed!");
this->status_set_warning();
return;
}
} }
ESP_LOGD(TAG, "channel_info_byte=%d", channel_info_byte); ESP_LOGD(TAG, "channel_info_byte=%d", channel_info_byte);
if (!this->bus_->reset()) { if (!this->bus_->reset()) {
@ -375,16 +407,20 @@ void DallasPio::ds2406_write_state_(bool state, bool use_crc = false) {
} }
} // ds2406_write_state_ } // ds2406_write_state_
bool DallasPio::ds2406_verify_crc_(uint8_t control1, uint8_t control2, uint8_t info, uint16_t received_crc) { bool DallasPio::ds2406_verify_crc_(uint8_t control1, uint8_t control2, uint8_t channel_info_byte, uint8_t io_state,
uint16_t received_crc) {
uint16_t computed_crc = 0; uint16_t computed_crc = 0;
this->crc_reset_(); this->crc_reset_();
this->crc_shift_byte_(DALLAS_COMMAND_PIO_ACCESS_READ); this->crc_shift_byte_(DALLAS_DS2406_COMMAND_CHANNEL_ACCESS);
this->crc_shift_byte_(control1); this->crc_shift_byte_(control1);
this->crc_shift_byte_(control2); this->crc_shift_byte_(control2);
this->crc_shift_byte_(info); this->crc_shift_byte_(channel_info_byte);
this->crc_shift_byte_(io_state);
computed_crc = this->crc_read_(); computed_crc = this->crc_read_();
computed_crc = ~computed_crc;
if (computed_crc != received_crc) {
ESP_LOGD(TAG, "Computed CRC: 0x%04X", computed_crc); ESP_LOGD(TAG, "Computed CRC: 0x%04X", computed_crc);
}
return computed_crc == received_crc; return computed_crc == received_crc;
} }
@ -498,7 +534,7 @@ void DallasPio::ds2408_write_state_(bool state, bool use_crc = false) {
this->bus_->write8(~new_state); this->bus_->write8(~new_state);
ack = this->bus_->read8(); // 0xAA=success, 0xFF=failure ack = this->bus_->read8(); // 0xAA=success, 0xFF=failure
} }
if (ack != DALLAS_COMMAND_PIO_ACK_SUCCESS) { if (ack != DALLAS_DS2413_COMMAND_PIO_ACK_SUCCESS) {
ESP_LOGW(TAG, "Failed to write One-Wire bus."); ESP_LOGW(TAG, "Failed to write One-Wire bus.");
this->status_set_warning(); this->status_set_warning();
return; return;

View File

@ -77,7 +77,7 @@ class DallasPio : public Component, public one_wire::OneWireDevice {
void ds2408_write_state_(bool state, bool use_crc); void ds2408_write_state_(bool state, bool use_crc);
uint16_t crc_; uint16_t crc_;
bool crc_enabled_ = false; bool crc_enabled_ = false;
bool ds2406_verify_crc_(uint8_t control1, uint8_t control2, uint8_t info, uint16_t received_crc); bool ds2406_verify_crc_(uint8_t control1, uint8_t control2, uint8_t info, uint8_t io_state, uint16_t received_crc);
void crc_reset_(); void crc_reset_();
void crc_shift_byte_(uint8_t byte); void crc_shift_byte_(uint8_t byte);
uint16_t crc_read_() const; uint16_t crc_read_() const;

View File

@ -8,10 +8,13 @@ static const char *const TAG = "dallas_pio";
static const uint8_t DALLAS_MODEL_DS2413 = 0xBA; static const uint8_t DALLAS_MODEL_DS2413 = 0xBA;
static const uint8_t DALLAS_MODEL_DS2406 = 0x12; static const uint8_t DALLAS_MODEL_DS2406 = 0x12;
static const uint8_t DALLAS_MODEL_DS2408 = 0x29; static const uint8_t DALLAS_MODEL_DS2408 = 0x29;
static const uint8_t DALLAS_COMMAND_PIO_ACCESS_READ = 0xF5; static const uint8_t DALLAS_DS2413_COMMAND_PIO_ACCESS_READ = 0xF5;
static const uint8_t DALLAS_COMMAND_PIO_ACCESS_WRITE = 0x5A; static const uint8_t DALLAS_DS2413_COMMAND_PIO_ACCESS_WRITE = 0x5A;
static const uint8_t DALLAS_COMMAND_PIO_ACK_SUCCESS = 0xAA; static const uint8_t DALLAS_DS2413_COMMAND_PIO_ACK_SUCCESS = 0xAA;
static const uint8_t DALLAS_COMMAND_PIO_ACK_ERROR = 0xFF; static const uint8_t DALLAS_DS2413_COMMAND_PIO_ACK_ERROR = 0xFF;
static const uint8_t DALLAS_DS2406_COMMAND_CHANNEL_ACCESS = 0xF5;
static const uint8_t DALLAS_DS2406_COMMAND_READ_STATUS = 0xAA;
static const uint8_t DALLAS_DS2406_COMMAND_WRITE_STATUS = 0x55;
static const uint8_t DALLAS_DS2408_COMMAND_READ_PIO_REGISTERS = 0xF0; static const uint8_t DALLAS_DS2408_COMMAND_READ_PIO_REGISTERS = 0xF0;
static const uint8_t DALLAS_DS2408_COMMAND_WRITE_PIO_REGISTERS = 0x5A; static const uint8_t DALLAS_DS2408_COMMAND_WRITE_PIO_REGISTERS = 0x5A;

View File

@ -63,11 +63,9 @@ void DallasPioSwitch::write_state(bool state) {
} }
this->status_clear_warning(); this->status_clear_warning();
if (this->reference_ == "DS2413") {
if (!this->dallas_pio_->write_state(state, this->pin_, this->pin_inverted_)) { if (!this->dallas_pio_->write_state(state, this->pin_, this->pin_inverted_)) {
return; return;
} }
}
this->publish_state(state); // Set state in ESPHome this->publish_state(state); // Set state in ESPHome
} }