mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Added in mmc5603 code (#4175)
* added in mmc5603 code * added in codeowner * fix linter errors * whitespace linter errors * added codeowner * clang format * remove clang format from python code * fix whitespace * add tests * fix test * make requested edits * remove status manipulation --------- Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -159,6 +159,7 @@ esphome/components/midea/* @dudanov | |||||||
| esphome/components/midea_ir/* @dudanov | esphome/components/midea_ir/* @dudanov | ||||||
| esphome/components/mitsubishi/* @RubyBailey | esphome/components/mitsubishi/* @RubyBailey | ||||||
| esphome/components/mlx90393/* @functionpointer | esphome/components/mlx90393/* @functionpointer | ||||||
|  | esphome/components/mmc5603/* @benhoff | ||||||
| esphome/components/modbus_controller/* @martgras | esphome/components/modbus_controller/* @martgras | ||||||
| esphome/components/modbus_controller/binary_sensor/* @martgras | esphome/components/modbus_controller/binary_sensor/* @martgras | ||||||
| esphome/components/modbus_controller/number/* @martgras | esphome/components/modbus_controller/number/* @martgras | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								esphome/components/mmc5603/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								esphome/components/mmc5603/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | CODEOWNERS = ["@benhoff"] | ||||||
							
								
								
									
										162
									
								
								esphome/components/mmc5603/mmc5603.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								esphome/components/mmc5603/mmc5603.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | |||||||
|  | #include "mmc5603.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace mmc5603 { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "mmc5603"; | ||||||
|  | static const uint8_t MMC5603_ADDRESS = 0x30; | ||||||
|  | static const uint8_t MMC56X3_PRODUCT_ID = 0x39; | ||||||
|  |  | ||||||
|  | static const uint8_t MMC56X3_DEFAULT_ADDRESS = 0x30; | ||||||
|  | static const uint8_t MMC56X3_CHIP_ID = 0x10; | ||||||
|  |  | ||||||
|  | static const uint8_t MMC56X3_ADDR_XOUT0 = 0x00; | ||||||
|  | static const uint8_t MMC56X3_ADDR_XOUT1 = 0x01; | ||||||
|  | static const uint8_t MMC56X3_ADDR_XOUT2 = 0x06; | ||||||
|  |  | ||||||
|  | static const uint8_t MMC56X3_ADDR_YOUT0 = 0x02; | ||||||
|  | static const uint8_t MMC56X3_ADDR_YOUT1 = 0x03; | ||||||
|  | static const uint8_t MMC56X3_ADDR_YOUT2 = 0x07; | ||||||
|  |  | ||||||
|  | static const uint8_t MMC56X3_ADDR_ZOUT0 = 0x04; | ||||||
|  | static const uint8_t MMC56X3_ADDR_ZOUT1 = 0x05; | ||||||
|  | static const uint8_t MMC56X3_ADDR_ZOUT2 = 0x08; | ||||||
|  |  | ||||||
|  | static const uint8_t MMC56X3_OUT_TEMP = 0x09; | ||||||
|  | static const uint8_t MMC56X3_STATUS_REG = 0x18; | ||||||
|  | static const uint8_t MMC56X3_CTRL0_REG = 0x1B; | ||||||
|  | static const uint8_t MMC56X3_CTRL1_REG = 0x1C; | ||||||
|  | static const uint8_t MMC56X3_CTRL2_REG = 0x1D; | ||||||
|  | static const uint8_t MMC5603_ODR_REG = 0x1A; | ||||||
|  |  | ||||||
|  | void MMC5603Component::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up MMC5603..."); | ||||||
|  |   uint8_t id = 0; | ||||||
|  |   if (!this->read_byte(MMC56X3_PRODUCT_ID, &id)) { | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (id != MMC56X3_CHIP_ID) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "Chip Wrong"); | ||||||
|  |     this->error_code_ = ID_REGISTERS; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!this->write_byte(MMC56X3_CTRL1_REG, 0x80)) {  // turn on set bit | ||||||
|  |     ESP_LOGCONFIG(TAG, "Control 1 Failed for set bit"); | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!this->write_byte(MMC56X3_CTRL0_REG, 0x08)) {  // turn on set bit | ||||||
|  |     ESP_LOGCONFIG(TAG, "Control 0 Failed for set bit"); | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!this->write_byte(MMC56X3_CTRL0_REG, 0x10)) { | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   uint8_t ctrl_2 = 0; | ||||||
|  |  | ||||||
|  |   ctrl_2 &= ~0x10;  // turn off cmm_en bit | ||||||
|  |   if (!this->write_byte(MMC56X3_CTRL2_REG, ctrl_2)) { | ||||||
|  |     this->error_code_ = COMMUNICATION_FAILED; | ||||||
|  |     this->mark_failed(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | void MMC5603Component::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "MMC5603:"); | ||||||
|  |   LOG_I2C_DEVICE(this); | ||||||
|  |   if (this->error_code_ == COMMUNICATION_FAILED) { | ||||||
|  |     ESP_LOGE(TAG, "Communication with MMC5603 failed!"); | ||||||
|  |   } else if (this->error_code_ == ID_REGISTERS) { | ||||||
|  |     ESP_LOGE(TAG, "The ID registers don't match - Is this really an MMC5603?"); | ||||||
|  |   } | ||||||
|  |   LOG_UPDATE_INTERVAL(this); | ||||||
|  |  | ||||||
|  |   LOG_SENSOR("  ", "X Axis", this->x_sensor_); | ||||||
|  |   LOG_SENSOR("  ", "Y Axis", this->y_sensor_); | ||||||
|  |   LOG_SENSOR("  ", "Z Axis", this->z_sensor_); | ||||||
|  |   LOG_SENSOR("  ", "Heading", this->heading_sensor_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float MMC5603Component::get_setup_priority() const { return setup_priority::DATA; } | ||||||
|  |  | ||||||
|  | void MMC5603Component::update() { | ||||||
|  |   if (!this->write_byte(MMC56X3_CTRL0_REG, 0x01)) { | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   uint8_t status = 0; | ||||||
|  |   if (!this->read_byte(MMC56X3_STATUS_REG, &status)) { | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   uint8_t buffer[9] = {0}; | ||||||
|  |  | ||||||
|  |   if (!this->read_byte(MMC56X3_ADDR_XOUT0, &buffer[0]) || !this->read_byte(MMC56X3_ADDR_XOUT1, &buffer[1]) || | ||||||
|  |       !this->read_byte(MMC56X3_ADDR_XOUT2, &buffer[2])) { | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!this->read_byte(MMC56X3_ADDR_YOUT0, &buffer[3]) || !this->read_byte(MMC56X3_ADDR_YOUT1, &buffer[4]) || | ||||||
|  |       !this->read_byte(MMC56X3_ADDR_YOUT2, &buffer[5])) { | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!this->read_byte(MMC56X3_ADDR_ZOUT0, &buffer[6]) || !this->read_byte(MMC56X3_ADDR_ZOUT1, &buffer[7]) || | ||||||
|  |       !this->read_byte(MMC56X3_ADDR_ZOUT2, &buffer[8])) { | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int32_t raw_x = 0; | ||||||
|  |   raw_x |= buffer[0] << 12; | ||||||
|  |   raw_x |= buffer[1] << 4; | ||||||
|  |   raw_x |= buffer[2] << 0; | ||||||
|  |  | ||||||
|  |   const float x = 0.0625 * (raw_x - 524288); | ||||||
|  |  | ||||||
|  |   int32_t raw_y = 0; | ||||||
|  |   raw_y |= buffer[3] << 12; | ||||||
|  |   raw_y |= buffer[4] << 4; | ||||||
|  |   raw_y |= buffer[5] << 0; | ||||||
|  |  | ||||||
|  |   const float y = 0.0625 * (raw_y - 524288); | ||||||
|  |  | ||||||
|  |   int32_t raw_z = 0; | ||||||
|  |   raw_z |= buffer[6] << 12; | ||||||
|  |   raw_z |= buffer[7] << 4; | ||||||
|  |   raw_z |= buffer[8] << 0; | ||||||
|  |  | ||||||
|  |   const float z = 0.0625 * (raw_z - 524288); | ||||||
|  |  | ||||||
|  |   const float heading = atan2f(0.0f - x, y) * 180.0f / M_PI; | ||||||
|  |   ESP_LOGD(TAG, "Got x=%0.02fµT y=%0.02fµT z=%0.02fµT heading=%0.01f°", x, y, z, heading); | ||||||
|  |  | ||||||
|  |   if (this->x_sensor_ != nullptr) | ||||||
|  |     this->x_sensor_->publish_state(x); | ||||||
|  |   if (this->y_sensor_ != nullptr) | ||||||
|  |     this->y_sensor_->publish_state(y); | ||||||
|  |   if (this->z_sensor_ != nullptr) | ||||||
|  |     this->z_sensor_->publish_state(z); | ||||||
|  |   if (this->heading_sensor_ != nullptr) | ||||||
|  |     this->heading_sensor_->publish_state(heading); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace mmc5603 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										43
									
								
								esphome/components/mmc5603/mmc5603.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								esphome/components/mmc5603/mmc5603.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/components/sensor/sensor.h" | ||||||
|  | #include "esphome/components/i2c/i2c.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace mmc5603 { | ||||||
|  |  | ||||||
|  | enum MMC5603Datarate { | ||||||
|  |   MMC5603_DATARATE_75_0_HZ, | ||||||
|  |   MMC5603_DATARATE_150_0_HZ, | ||||||
|  |   MMC5603_DATARATE_255_0_HZ, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class MMC5603Component : public PollingComponent, public i2c::I2CDevice { | ||||||
|  |  public: | ||||||
|  |   void setup() override; | ||||||
|  |   void dump_config() override; | ||||||
|  |   float get_setup_priority() const override; | ||||||
|  |   void update() override; | ||||||
|  |  | ||||||
|  |   void set_datarate(MMC5603Datarate datarate) { datarate_ = datarate; } | ||||||
|  |   void set_x_sensor(sensor::Sensor *x_sensor) { x_sensor_ = x_sensor; } | ||||||
|  |   void set_y_sensor(sensor::Sensor *y_sensor) { y_sensor_ = y_sensor; } | ||||||
|  |   void set_z_sensor(sensor::Sensor *z_sensor) { z_sensor_ = z_sensor; } | ||||||
|  |   void set_heading_sensor(sensor::Sensor *heading_sensor) { heading_sensor_ = heading_sensor; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   MMC5603Datarate datarate_; | ||||||
|  |   sensor::Sensor *x_sensor_{nullptr}; | ||||||
|  |   sensor::Sensor *y_sensor_{nullptr}; | ||||||
|  |   sensor::Sensor *z_sensor_{nullptr}; | ||||||
|  |   sensor::Sensor *heading_sensor_{nullptr}; | ||||||
|  |   enum ErrorCode { | ||||||
|  |     NONE = 0, | ||||||
|  |     COMMUNICATION_FAILED, | ||||||
|  |     ID_REGISTERS, | ||||||
|  |   } error_code_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace mmc5603 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										91
									
								
								esphome/components/mmc5603/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								esphome/components/mmc5603/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.components import i2c, sensor | ||||||
|  | from esphome.const import ( | ||||||
|  |     CONF_ADDRESS, | ||||||
|  |     CONF_ID, | ||||||
|  |     ICON_MAGNET, | ||||||
|  |     STATE_CLASS_MEASUREMENT, | ||||||
|  |     UNIT_MICROTESLA, | ||||||
|  |     UNIT_DEGREES, | ||||||
|  |     ICON_SCREEN_ROTATION, | ||||||
|  |     CONF_UPDATE_INTERVAL, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | DEPENDENCIES = ["i2c"] | ||||||
|  |  | ||||||
|  | mmc5603_ns = cg.esphome_ns.namespace("mmc5603") | ||||||
|  |  | ||||||
|  | CONF_FIELD_STRENGTH_X = "field_strength_x" | ||||||
|  | CONF_FIELD_STRENGTH_Y = "field_strength_y" | ||||||
|  | CONF_FIELD_STRENGTH_Z = "field_strength_z" | ||||||
|  | CONF_HEADING = "heading" | ||||||
|  |  | ||||||
|  | MMC5603Component = mmc5603_ns.class_( | ||||||
|  |     "MMC5603Component", cg.PollingComponent, i2c.I2CDevice | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | MMC5603Datarate = mmc5603_ns.enum("MMC5603Datarate") | ||||||
|  | MMC5603Datarates = { | ||||||
|  |     75: MMC5603Datarate.MMC5603_DATARATE_75_0_HZ, | ||||||
|  |     150: MMC5603Datarate.MMC5603_DATARATE_150_0_HZ, | ||||||
|  |     255: MMC5603Datarate.MMC5603_DATARATE_255_0_HZ, | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | field_strength_schema = sensor.sensor_schema( | ||||||
|  |     unit_of_measurement=UNIT_MICROTESLA, | ||||||
|  |     icon=ICON_MAGNET, | ||||||
|  |     accuracy_decimals=1, | ||||||
|  |     state_class=STATE_CLASS_MEASUREMENT, | ||||||
|  | ) | ||||||
|  | heading_schema = sensor.sensor_schema( | ||||||
|  |     unit_of_measurement=UNIT_DEGREES, | ||||||
|  |     icon=ICON_SCREEN_ROTATION, | ||||||
|  |     accuracy_decimals=1, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = ( | ||||||
|  |     cv.Schema( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(): cv.declare_id(MMC5603Component), | ||||||
|  |             cv.Optional(CONF_ADDRESS): cv.i2c_address, | ||||||
|  |             cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema, | ||||||
|  |             cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, | ||||||
|  |             cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, | ||||||
|  |             cv.Optional(CONF_HEADING): heading_schema, | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  |     .extend(cv.polling_component_schema("60s")) | ||||||
|  |     .extend(i2c.i2c_device_schema(0x1E)) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def auto_data_rate(config): | ||||||
|  |     interval_msec = config[CONF_UPDATE_INTERVAL].total_milliseconds | ||||||
|  |     interval_hz = 1000.0 / interval_msec | ||||||
|  |     for datarate in sorted(MMC5603Datarates.keys()): | ||||||
|  |         if float(datarate) >= interval_hz: | ||||||
|  |             return MMC5603Datarates[datarate] | ||||||
|  |     return MMC5603Datarates[75] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     await i2c.register_i2c_device(var, config) | ||||||
|  |  | ||||||
|  |     cg.add(var.set_datarate(auto_data_rate(config))) | ||||||
|  |     if CONF_FIELD_STRENGTH_X in config: | ||||||
|  |         sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_X]) | ||||||
|  |         cg.add(var.set_x_sensor(sens)) | ||||||
|  |     if CONF_FIELD_STRENGTH_Y in config: | ||||||
|  |         sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_Y]) | ||||||
|  |         cg.add(var.set_y_sensor(sens)) | ||||||
|  |     if CONF_FIELD_STRENGTH_Z in config: | ||||||
|  |         sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_Z]) | ||||||
|  |         cg.add(var.set_z_sensor(sens)) | ||||||
|  |     if CONF_HEADING in config: | ||||||
|  |         sens = await sensor.new_sensor(config[CONF_HEADING]) | ||||||
|  |         cg.add(var.set_heading_sensor(sens)) | ||||||
| @@ -831,6 +831,15 @@ sensor: | |||||||
|     temperature: |     temperature: | ||||||
|       name: MPU6886 Temperature |       name: MPU6886 Temperature | ||||||
|     i2c_id: i2c_bus |     i2c_id: i2c_bus | ||||||
|  |   - platform: mmc5603 | ||||||
|  |     address: 0x30 | ||||||
|  |     field_strength_x: | ||||||
|  |       name: HMC5883L Field Strength X | ||||||
|  |     field_strength_y: | ||||||
|  |       name: HMC5883L Field Strength Y | ||||||
|  |     field_strength_z: | ||||||
|  |       name: HMC5883L Field Strength Z | ||||||
|  |     i2c_id: i2c_bus | ||||||
|   - platform: dps310 |   - platform: dps310 | ||||||
|     temperature: |     temperature: | ||||||
|       name: DPS310 Temperature |       name: DPS310 Temperature | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user