diff --git a/I2CDEVICES.md b/I2CDEVICES.md
index d3b2cd418..3ef236eeb 100644
--- a/I2CDEVICES.md
+++ b/I2CDEVICES.md
@@ -107,3 +107,4 @@ Index | Define | Driver | Device | Address(es) | Description
70 | USE_LUXV30B | xsns_99 | LUXV30B | 0x4A | DFRobot SEN0390 V30B lux sensor
71 | USE_QMC5883L | xsns_33 | QMC5883L | 0x0D | Magnetic Field Sensor
72 | USE_INA3221 | xsns_100 | INA3221 | 0x40-0x43 | 3-channels Voltage and Current sensor
+ 73 | USE_HMC5883L | xsns_101 | HMC5883L | 0x1E | 3-channels Magnetic Field Sensor
diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h
index e2803f8d4..23415f8fd 100644
--- a/tasmota/my_user_config.h
+++ b/tasmota/my_user_config.h
@@ -691,6 +691,7 @@
// #define USE_HYT // [I2CDriver68] Enable HYTxxx temperature and humidity sensor (I2C address 0x28) (+0k5 code)
// #define USE_LUXV30B // [I2CDriver70] Enable RFRobot SEN0390 LuxV30b ambient light sensor (I2C address 0x4A) (+0k5 code)
// #define USE_QMC5883L // [I2CDriver71] Enable QMC5883L magnetic induction sensor (I2C address 0x0D) (+0k8 code)
+// #define USE_HMC5883L // [I2CDriver73] Enable HMC5883L magnetic induction sensor (I2C address 0x1E)
// #define QMC5883L_TEMP_SHIFT 23 // sensor temperature are not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet)
// #define USE_INA3221 // [I2CDriver72] Enable INA3221 3-channel DC voltage and current sensor (I2C address 0x40-0x44) (+3.2k code)
// #define INA3221_ADDRESS1 // allow to change the 1st address to search for INA3221 to 0x41..0x43
diff --git a/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino b/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino
new file mode 100644
index 000000000..56a311354
--- /dev/null
+++ b/tasmota/tasmota_xsns_sensor/xsns_101_hmc5883l.ino
@@ -0,0 +1,249 @@
+/*
+ xsns_101_hmc5883l.ino - HMC5883L 3-Axis Digital Compass sensor support for Tasmota
+ (inspired by Helge Scheunemann)
+ Copyright (C) 2022 Andreas Achtzehn
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef USE_I2C
+#ifdef USE_HMC5883L
+/*********************************************************************************************\
+ * HMC5883L is 3-Axis Digital Compass sensor
+ *
+ * Datasheet: https://cdn-shop.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf
+ * I2C Address: 0x1E
+\*********************************************************************************************/
+
+// Define driver ID
+#define XSNS_101 101
+#define XI2C_73 73 // See I2CDEVICES.md
+
+/* The default I2C address of this chip */
+#define HMC5883L_ADDR 0x1E
+
+/* Register locations */
+#define HMC5883L_X_LSB 0x04
+#define HMC5883L_X_MSB 0x03
+#define HMC5883L_Y_LSB 0x08
+#define HMC5883L_Y_MSB 0x07
+#define HMC5883L_Z_LSB 0x06
+#define HMC5883L_Z_MSB 0x05
+#define HMC5883L_STATUS 0x09
+#define HMC5883L_CONFIG_A 0x00
+#define HMC5883L_CONFIG_B 0x01
+#define HMC5883L_MODE 0x02
+#define HMC5883L_CHIP_ID_A 0x0A
+#define HMC5883L_CHIP_ID_B 0x0B
+#define HMC5883L_CHIP_ID_C 0x0C
+
+/* Bit values for the STATUS register */
+const uint8_t HMC5883L_STATUS_RDY = 0b00000001;
+const uint8_t HMC5883L_STATUS_LOCK = 0b00000010;
+
+/* Modes for the sampling in the MODE register */
+const uint8_t HMC5883L_MODE_CONT = 0b00000000;
+const uint8_t HMC5883L_MODE_SINGLE = 0b00000001;
+const uint8_t HMC5883L_MODE_IDLE = 0b00000010;
+
+/* Gain value mask for CONFIG B register */
+const uint8_t HMC5883L_CONFIG_B_GAIN_MASK = 0b11100000; // shift operation, values 0-7
+const uint8_t HMC5883L_CONFIG_B_GAIN_SHIFT = 5;
+
+/* Averaging value for CONFIG A register: pow(2,N) */
+const uint8_t HMC5883L_CONFIG_A_AVG_MASK = 0b01100000;
+const uint8_t HMC5883L_CONFIG_A_AVG_SHIFT = 5;
+
+/* Data output rate */
+const uint8_t HMC5883L_CONFIG_A_RATE_MASK = 0b00011100;
+const uint8_t HMC5883L_CONFIG_A_RATE_SHIFT = 2;
+
+/* Data measurement mode */
+const uint8_t HMC5883L_CONFIG_A_MMODE_NORM = 0;
+const uint8_t HMC5883L_CONFIG_A_MMODE_POSBIAS = 1;
+const uint8_t HMC5883L_CONFIG_A_MMODE_NEGBIAS = 2;
+const uint8_t HMC5883L_CONFIG_A_MMODE_MASK = 0b00000011;
+const uint8_t HMC5883L_CONFIG_A_MMODE_SHIFT = 0;
+
+/* Data output X register A contains the MSB from the measurement result,
+and data output X register B contains the LSB from the measurement result. The value stored in these two registers is a
+16-bit value in 2’s complement form, whose range is 0xF800 to 0x07FF. */
+
+
+
+ // data field
+struct HMC5883L_s {
+ int16_t MX, MY, MZ;
+ uint16_t magnitude;
+ int8_t measurement_mode;
+ int8_t data_rate;
+ int8_t average_mode;
+ int8_t gain;
+ int8_t mode;
+} *HMC5883L = nullptr;
+
+
+// Change configuration registers of the device
+bool HMC5883L_SetConfig() {
+ if ( HMC5883L == nullptr ) { return false; }
+
+ uint8_t cfgA = (( (HMC5883L->measurement_mode) << HMC5883L_CONFIG_A_MMODE_SHIFT ) & HMC5883L_CONFIG_A_MMODE_MASK ) |
+ (( (HMC5883L->data_rate ) << HMC5883L_CONFIG_A_RATE_SHIFT ) & HMC5883L_CONFIG_A_RATE_MASK ) |
+ (( (HMC5883L->average_mode ) << HMC5883L_CONFIG_A_AVG_SHIFT ) & HMC5883L_CONFIG_A_AVG_MASK );
+
+ uint8_t cfgB = (( (HMC5883L->gain ) << HMC5883L_CONFIG_B_GAIN_SHIFT ) & HMC5883L_CONFIG_B_GAIN_MASK );
+
+ AddLog(LOG_LEVEL_INFO,"HMC5883L: CONFIG A: %#X CONFIG B: %#X MODE: %#X",cfgA, cfgB, HMC5883L->mode);
+
+ if (I2cWrite8(HMC5883L_ADDR, HMC5883L_CONFIG_A, cfgA ) == false) {
+ AddLog(LOG_LEVEL_INFO,"HMC5883L: Setting CONFIG A failed.");
+ return false;
+ }
+ if (I2cWrite8(HMC5883L_ADDR, HMC5883L_CONFIG_B, cfgB ) == false) {
+ AddLog(LOG_LEVEL_INFO,"HMC5883L: Setting CONFIG B failed.");
+ return false;
+ }
+ if (HMC5883L->mode == HMC5883L_MODE_CONT) {
+ if (I2cWrite8(HMC5883L_ADDR, HMC5883L_MODE, HMC5883L_MODE_CONT ) == false)
+ { AddLog(LOG_LEVEL_INFO,"HMC5883L: Setting continuous mode failed.");
+ return false; }
+ }
+ return true;
+}
+
+// Initialize the device
+void HMC5883L_Init() {
+ if (!I2cSetDevice(HMC5883L_ADDR)) { return; }
+
+ HMC5883L = (HMC5883L_s *)calloc(1, sizeof(struct HMC5883L_s));
+ // standard configuration
+ HMC5883L->gain = 5;
+ HMC5883L->average_mode = 3;
+ HMC5883L->data_rate = 2;
+ HMC5883L->measurement_mode = HMC5883L_CONFIG_A_MMODE_NORM;
+ HMC5883L->mode = HMC5883L_MODE_SINGLE;
+
+ HMC5883L_SetConfig();
+
+ I2cSetActiveFound(HMC5883L_ADDR, "HMC5883L");
+}
+
+//Read the magnetic data
+void HMC5883L_ReadData(void) {
+ if (HMC5883L->mode == HMC5883L_MODE_SINGLE) {
+ if (I2cWrite8(HMC5883L_ADDR, HMC5883L_MODE, HMC5883L_MODE_SINGLE ) == false)
+ { return; }
+ }
+
+ while (!(I2cRead8(HMC5883L_ADDR, HMC5883L_STATUS) & HMC5883L_STATUS_RDY)) { } // Chip not yet ready, next round try again
+
+ HMC5883L->MX = I2cReadS16(HMC5883L_ADDR, HMC5883L_X_MSB); // Select starting with MSB register
+ HMC5883L->MY = I2cReadS16(HMC5883L_ADDR, HMC5883L_Y_MSB);
+ HMC5883L->MZ = I2cReadS16(HMC5883L_ADDR, HMC5883L_Z_MSB);
+
+ // calculate magnetic induction magnitude
+ HMC5883L->magnitude = SqrtInt((HMC5883L->MX * HMC5883L->MX) + (HMC5883L->MY * HMC5883L->MY) + (HMC5883L->MZ * HMC5883L->MZ));
+}
+
+/*********************************************************************************************\
+ * Presentation
+\*********************************************************************************************/
+
+#ifdef USE_WEBSERVER
+const char HTTP_SNS_HMC5883L[] PROGMEM =
+ "{s}HMC5883L " D_MX "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} =
, {m} = | , {e} = |
+ "{s}HMC5883L " D_MY "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = | , {e} = |
+ "{s}HMC5883L " D_MZ "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = | , {e} = |
+ "{s}HMC5883L " D_MAGNETICFLD "{m}%d " D_UNIT_MICROTESLA "{e}"; // {s} = , {m} = | , {e} = |
+#endif
+
+void HMC5883L_Show(uint8_t json) {
+ if (json) {
+ ResponseAppend_P(PSTR(",\"HMC5883L\":{\"" D_JSON_MX "\":%d,\"" D_JSON_MY "\":%d,\"" D_JSON_MZ "\":%d,\"" D_JSON_MAGNETICFLD "\":%u,\""),
+ HMC5883L->MX, HMC5883L->MY, HMC5883L->MZ, HMC5883L->magnitude);
+#ifdef USE_WEBSERVER
+ } else {
+ WSContentSend_PD(HTTP_SNS_HMC5883L, HMC5883L->MX, HMC5883L->MY, HMC5883L->MZ, HMC5883L->magnitude);
+#endif
+ }
+}
+
+// Process configuration commands
+bool HMC5883L_Command() {
+ bool commandKnown = false;
+ char cmd[20];
+ char ss2[20];
+
+ subStr(cmd, XdrvMailbox.data, ",", 1);
+ int8_t value = atoi(subStr(ss2, XdrvMailbox.data, ",", 2));
+
+ if (strcmp(cmd,"GAIN")) {
+ HMC5883L->gain = value;
+ commandKnown = true;
+ }
+ if (strcmp(cmd,"AVG")) {
+ HMC5883L->average_mode = value;
+ commandKnown = true;
+ }
+ if (strcmp(cmd,"RATE")) {
+ HMC5883L->data_rate = value;
+ commandKnown = true;
+ }
+ if (strcmp(cmd,"MMODE")) {
+ HMC5883L->measurement_mode = value;
+ commandKnown = true;
+ }
+
+ //AddLog(LOG_LEVEL_INFO,PSTR(D_LOG_I2C "HMC5883L: cmd: (%s) value: %d cmdKnown: %d"), cmd, value,commandKnown);
+
+ if (commandKnown == false) { return false; }
+
+ AddLog(LOG_LEVEL_INFO,PSTR(D_LOG_I2C "HMC5883L: Reconfiguring."));
+
+ return HMC5883L_SetConfig();
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xsns101(uint32_t function) {
+ if (!I2cEnabled(XI2C_73)) { return false; }
+
+ if (FUNC_INIT == function) {
+ HMC5883L_Init();
+ }
+ else if (HMC5883L != nullptr) {
+ switch (function) {
+ case FUNC_COMMAND_SENSOR:
+ if (XSNS_101 == XdrvMailbox.index)
+ return HMC5883L_Command(); // Return true on success
+ break;
+ case FUNC_JSON_APPEND:
+ HMC5883L_Show(1);
+ break;
+ case FUNC_EVERY_SECOND:
+ HMC5883L_ReadData();
+ break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_SENSOR:
+ HMC5883L_Show(0);
+ break;
+#endif // USE_WEBSERVER
+ }
+ }
+ return true;
+}
+#endif // USE_HMC5883L
+#endif // USE_I2C