mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	DAC7678 support (#3441)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -52,6 +52,7 @@ esphome/components/cs5460a/* @balrog-kun | ||||
| esphome/components/cse7761/* @berfenger | ||||
| esphome/components/ct_clamp/* @jesserockz | ||||
| esphome/components/current_based/* @djwmarcx | ||||
| esphome/components/dac7678/* @NickB1 | ||||
| esphome/components/daly_bms/* @s1lvi0 | ||||
| esphome/components/dashboard_import/* @esphome/core | ||||
| esphome/components/debug/* @OttoWinter | ||||
|   | ||||
							
								
								
									
										32
									
								
								esphome/components/dac7678/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								esphome/components/dac7678/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ["output"] | ||||
| CODEOWNERS = ["@NickB1"] | ||||
| DEPENDENCIES = ["i2c"] | ||||
| MULTI_CONF = True | ||||
|  | ||||
| dac7678_ns = cg.esphome_ns.namespace("dac7678") | ||||
| DAC7678Output = dac7678_ns.class_("DAC7678Output", cg.Component, i2c.I2CDevice) | ||||
| CONF_INTERNAL_REFERENCE = "internal_reference" | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(DAC7678Output), | ||||
|             cv.Optional(CONF_INTERNAL_REFERENCE, default=False): cv.boolean, | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
|     .extend(i2c.i2c_device_schema(0x48)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     await cg.register_component(var, config) | ||||
|     cg.add(var.set_internal_reference(config[CONF_INTERNAL_REFERENCE])) | ||||
|     await i2c.register_i2c_device(var, config) | ||||
|     return var | ||||
							
								
								
									
										83
									
								
								esphome/components/dac7678/dac7678_output.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								esphome/components/dac7678/dac7678_output.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #include "dac7678_output.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/hal.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace dac7678 { | ||||
|  | ||||
| static const char *const TAG = "dac7678"; | ||||
|  | ||||
| static const uint8_t DAC7678_REG_INPUT_N = 0x00; | ||||
| static const uint8_t DAC7678_REG_SELECT_UPDATE_N = 0x10; | ||||
| static const uint8_t DAC7678_REG_WRITE_N_UPDATE_ALL = 0x20; | ||||
| static const uint8_t DAC7678_REG_WRITE_N_UPDATE_N = 0x30; | ||||
| static const uint8_t DAC7678_REG_POWER = 0x40; | ||||
| static const uint8_t DAC7678_REG_CLEAR_CODE = 0x50; | ||||
| static const uint8_t DAC7678_REG_LDAC = 0x60; | ||||
| static const uint8_t DAC7678_REG_SOFTWARE_RESET = 0x70; | ||||
| static const uint8_t DAC7678_REG_INTERNAL_REF_0 = 0x80; | ||||
| static const uint8_t DAC7678_REG_INTERNAL_REF_1 = 0x90; | ||||
|  | ||||
| void DAC7678Output::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up DAC7678OutputComponent..."); | ||||
|  | ||||
|   ESP_LOGV(TAG, "Resetting device..."); | ||||
|  | ||||
|   // Reset device | ||||
|   if (!this->write_byte_16(DAC7678_REG_SOFTWARE_RESET, 0x0000)) { | ||||
|     ESP_LOGE(TAG, "Reset failed"); | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   } else | ||||
|     ESP_LOGV(TAG, "Reset succeeded"); | ||||
|  | ||||
|   delayMicroseconds(1000); | ||||
|  | ||||
|   // Set internal reference | ||||
|   if (this->internal_reference_) { | ||||
|     if (!this->write_byte_16(DAC7678_REG_INTERNAL_REF_0, 1 << 4)) { | ||||
|       ESP_LOGE(TAG, "Set internal reference failed"); | ||||
|       this->mark_failed(); | ||||
|       return; | ||||
|     } else | ||||
|       ESP_LOGV(TAG, "Internal reference enabled"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void DAC7678Output::dump_config() { | ||||
|   if (this->is_failed()) { | ||||
|     ESP_LOGE(TAG, "Setting up DAC7678 failed!"); | ||||
|   } else | ||||
|     ESP_LOGCONFIG(TAG, "DAC7678 initialised"); | ||||
| } | ||||
|  | ||||
| void DAC7678Output::register_channel(DAC7678Channel *channel) { | ||||
|   auto c = channel->channel_; | ||||
|   this->min_channel_ = std::min(this->min_channel_, c); | ||||
|   this->max_channel_ = std::max(this->max_channel_, c); | ||||
|   channel->set_parent(this); | ||||
|   ESP_LOGV(TAG, "Registered channel: %01u", channel->channel_); | ||||
| } | ||||
|  | ||||
| void DAC7678Output::set_channel_value_(uint8_t channel, uint16_t value) { | ||||
|   if (this->dac_input_reg_[channel] != value) { | ||||
|     ESP_LOGV(TAG, "Channel %01u: input_reg=%04u ", channel, value); | ||||
|  | ||||
|     if (!this->write_byte_16(DAC7678_REG_WRITE_N_UPDATE_N | channel, value << 4)) { | ||||
|       this->status_set_warning(); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
|   this->dac_input_reg_[channel] = value; | ||||
|   this->status_clear_warning(); | ||||
| } | ||||
|  | ||||
| void DAC7678Channel::write_state(float state) { | ||||
|   const float input_rounded = roundf(state * this->full_scale_); | ||||
|   auto input = static_cast<uint16_t>(input_rounded); | ||||
|   this->parent_->set_channel_value_(this->channel_, input); | ||||
| } | ||||
|  | ||||
| }  // namespace dac7678 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										55
									
								
								esphome/components/dac7678/dac7678_output.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								esphome/components/dac7678/dac7678_output.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/components/output/float_output.h" | ||||
| #include "esphome/components/i2c/i2c.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace dac7678 { | ||||
|  | ||||
| class DAC7678Output; | ||||
|  | ||||
| class DAC7678Channel : public output::FloatOutput, public Parented<DAC7678Output> { | ||||
|  public: | ||||
|   void set_channel(uint8_t channel) { channel_ = channel; } | ||||
|  | ||||
|  protected: | ||||
|   friend class DAC7678Output; | ||||
|  | ||||
|   const uint16_t full_scale_ = 0xFFF; | ||||
|  | ||||
|   void write_state(float state) override; | ||||
|  | ||||
|   uint8_t channel_; | ||||
| }; | ||||
|  | ||||
| /// DAC7678 float output component. | ||||
| class DAC7678Output : public Component, public i2c::I2CDevice { | ||||
|  public: | ||||
|   DAC7678Output() {} | ||||
|  | ||||
|   void register_channel(DAC7678Channel *channel); | ||||
|  | ||||
|   void set_internal_reference(const bool value) { this->internal_reference_ = value; } | ||||
|  | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override { return setup_priority::HARDWARE; } | ||||
|  | ||||
|  protected: | ||||
|   friend DAC7678Channel; | ||||
|  | ||||
|   bool internal_reference_; | ||||
|  | ||||
|   void set_channel_value_(uint8_t channel, uint16_t value); | ||||
|  | ||||
|   uint8_t min_channel_{0xFF}; | ||||
|   uint8_t max_channel_{0x00}; | ||||
|   uint16_t dac_input_reg_[8] = { | ||||
|       0, | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| }  // namespace dac7678 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										27
									
								
								esphome/components/dac7678/output.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								esphome/components/dac7678/output.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import output | ||||
| from esphome.const import CONF_CHANNEL, CONF_ID | ||||
| from . import DAC7678Output, dac7678_ns | ||||
|  | ||||
| DEPENDENCIES = ["dac7678"] | ||||
|  | ||||
| DAC7678Channel = dac7678_ns.class_("DAC7678Channel", output.FloatOutput) | ||||
| CONF_DAC7678_ID = "dac7678_id" | ||||
|  | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(DAC7678Channel), | ||||
|         cv.GenerateID(CONF_DAC7678_ID): cv.use_id(DAC7678Output), | ||||
|         cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     paren = await cg.get_variable(config[CONF_DAC7678_ID]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     cg.add(var.set_channel(config[CONF_CHANNEL])) | ||||
|     cg.add(paren.register_channel(var)) | ||||
|     await output.register_output(var, config) | ||||
|     return var | ||||
| @@ -80,6 +80,11 @@ sx1509: | ||||
| mcp3204: | ||||
|   cs_pin: GPIO23 | ||||
|  | ||||
| dac7678: | ||||
|     address: 0x4A | ||||
|     id: dac7678_hub1 | ||||
|     internal_reference: true | ||||
|  | ||||
| sensor: | ||||
|   - platform: homeassistant | ||||
|     entity_id: sensor.hello_world | ||||
| @@ -518,6 +523,38 @@ output: | ||||
|     pipsolar_id: inverter0 | ||||
|     battery_recharge_voltage: | ||||
|       id: inverter0_battery_recharge_voltage_out | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 0 | ||||
|     id: 'dac7678_1_ch0' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 1 | ||||
|     id: 'dac7678_1_ch1' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 2 | ||||
|     id: 'dac7678_1_ch2' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 3 | ||||
|     id: 'dac7678_1_ch3' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 4 | ||||
|     id: 'dac7678_1_ch4' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 5 | ||||
|     id: 'dac7678_1_ch5' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 6 | ||||
|     id: 'dac7678_1_ch6' | ||||
|   - platform: dac7678 | ||||
|     dac7678_id: 'dac7678_hub1' | ||||
|     channel: 7 | ||||
|     id: 'dac7678_1_ch7' | ||||
| esp32_camera: | ||||
|   name: ESP-32 Camera | ||||
|   data_pins: [GPIO17, GPIO35, GPIO34, GPIO5, GPIO39, GPIO18, GPIO36, GPIO19] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user