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/mitsubishi/* @RubyBailey | ||||
| esphome/components/mlx90393/* @functionpointer | ||||
| esphome/components/mmc5603/* @benhoff | ||||
| esphome/components/modbus_controller/* @martgras | ||||
| esphome/components/modbus_controller/binary_sensor/* @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: | ||||
|       name: MPU6886 Temperature | ||||
|     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 | ||||
|     temperature: | ||||
|       name: DPS310 Temperature | ||||
|   | ||||
		Reference in New Issue
	
	Block a user