Add support for HMC5883L

Add support for HMC5883L 3-Axis Digital Compass sensor by Andreas Achtzehn (#17069)
This commit is contained in:
Theo Arends 2022-11-15 11:11:32 +01:00
parent 5e61ee6086
commit 5f3d504c30
7 changed files with 58 additions and 50 deletions

View File

@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- New ``FUNC_NETWORK_UP`` and ``FUNC_NETWORK_DOWN`` events - New ``FUNC_NETWORK_UP`` and ``FUNC_NETWORK_DOWN`` events
- WS2812 and Light Art-Net DMX control over UDP port 6454 (#17059) - WS2812 and Light Art-Net DMX control over UDP port 6454 (#17059)
- Command ``SwitchMode 16`` sending only MQTT message on inverted switch change (#17028) - Command ``SwitchMode 16`` sending only MQTT message on inverted switch change (#17028)
- Support for HMC5883L 3-Axis Digital Compass sensor by Andreas Achtzehn (#17069)
### Breaking Changed ### Breaking Changed

View File

@ -120,6 +120,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
- Support for Plantower PMSx003T AQI models with temperature and humidity [#16971](https://github.com/arendst/Tasmota/issues/16971) - Support for Plantower PMSx003T AQI models with temperature and humidity [#16971](https://github.com/arendst/Tasmota/issues/16971)
- Support for BP1658CJ RGBCW led bulbs like Orein OS0100411267 by Cossid [#17011](https://github.com/arendst/Tasmota/issues/17011) - Support for BP1658CJ RGBCW led bulbs like Orein OS0100411267 by Cossid [#17011](https://github.com/arendst/Tasmota/issues/17011)
- Support for Dingtian x595 shift register based relay boards by Barbudor [#17032](https://github.com/arendst/Tasmota/issues/17032) - Support for Dingtian x595 shift register based relay boards by Barbudor [#17032](https://github.com/arendst/Tasmota/issues/17032)
- Support for HMC5883L 3-Axis Digital Compass sensor by Andreas Achtzehn [#17069](https://github.com/arendst/Tasmota/issues/17069)
- WS2812 and Light Art-Net DMX control over UDP port 6454 [#17059](https://github.com/arendst/Tasmota/issues/17059) - WS2812 and Light Art-Net DMX control over UDP port 6454 [#17059](https://github.com/arendst/Tasmota/issues/17059)
- Berry ``bytes().setbytes()`` method [#16892](https://github.com/arendst/Tasmota/issues/16892) - Berry ``bytes().setbytes()`` method [#16892](https://github.com/arendst/Tasmota/issues/16892)
- Berry ``bytes().reverse()`` method [#16977](https://github.com/arendst/Tasmota/issues/16977) - Berry ``bytes().reverse()`` method [#16977](https://github.com/arendst/Tasmota/issues/16977)

View File

@ -322,16 +322,16 @@ enum WifiConfigOptions {WIFI_RESTART, EX_WIFI_SMARTCONFIG, WIFI_MANAGER, EX_WIFI
enum WifiTestOptions {WIFI_NOT_TESTING, WIFI_TESTING, WIFI_TEST_FINISHED, WIFI_TEST_FINISHED_BAD}; enum WifiTestOptions {WIFI_NOT_TESTING, WIFI_TESTING, WIFI_TEST_FINISHED, WIFI_TEST_FINISHED_BAD};
enum SwitchModeOptions {TOGGLE, enum SwitchModeOptions {TOGGLE, // 0
FOLLOW, FOLLOW_INV, FOLLOW, FOLLOW_INV, // 1, 2 - Follow switch state
PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTON, PUSHBUTTON_INV, // 3, 4 - Pushbutton (default 1, 0 = toggle)
PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, // 5, 6 - Pushbutton with hold (default 1, 0 = toggle, Hold = hold)
PUSHBUTTON_TOGGLE, PUSHBUTTON_TOGGLE, // 7 - = 0
TOGGLEMULTI, TOGGLEMULTI, // 8 - = 0 with multi toggle
FOLLOWMULTI, FOLLOWMULTI_INV, FOLLOWMULTI, FOLLOWMULTI_INV, // 9, 10 - Multi change follow (0 = off, 1 = on, 2x change = hold)
PUSHHOLDMULTI, PUSHHOLDMULTI_INV, PUSHHOLDMULTI, PUSHHOLDMULTI_INV, // 11, 12 - Pushbutton with dimmer mode
PUSHON, PUSHON_INV, PUSHON, PUSHON_INV, // 13, 14 - Pushon mode (1 = on, switch off using PulseTime)
PUSH_IGNORE, PUSH_IGNORE_INV, // 15, 16 PUSH_IGNORE, PUSH_IGNORE_INV, // 15, 16 - Send only MQTT message on switch change
MAX_SWITCH_OPTION}; MAX_SWITCH_OPTION};
enum LedStateOptions {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; enum LedStateOptions {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION};

View File

@ -691,7 +691,7 @@
// #define USE_HYT // [I2CDriver68] Enable HYTxxx temperature and humidity sensor (I2C address 0x28) (+0k5 code) // #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_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_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 USE_HMC5883L // [I2CDriver73] Enable HMC5883L magnetic induction sensor (I2C address 0x1E) (+1k3 code)
// #define QMC5883L_TEMP_SHIFT 23 // sensor temperature are not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet) // #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 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 // #define INA3221_ADDRESS1 // allow to change the 1st address to search for INA3221 to 0x41..0x43

View File

@ -852,7 +852,9 @@ void ResponseAppendFeatures(void)
#ifdef USE_DINGTIAN_RELAY #ifdef USE_DINGTIAN_RELAY
feature9 |= 0x00000100; // xdrv_90_dingtian_relay.ino feature9 |= 0x00000100; // xdrv_90_dingtian_relay.ino
#endif #endif
// feature9 |= 0x00000200; #if defined(USE_I2C) && defined(USE_HMC5883L)
feature9 |= 0x00000200; // xsns_101_hmc5883l.ino
#endif
// feature9 |= 0x00000400; // feature9 |= 0x00000400;
// feature9 |= 0x00000800; // feature9 |= 0x00000800;

View File

@ -1,7 +1,7 @@
/* /*
xsns_101_hmc5883l.ino - HMC5883L 3-Axis Digital Compass sensor support for Tasmota xsns_101_hmc5883l.ino - HMC5883L 3-Axis Digital Compass sensor support for Tasmota
(inspired by Helge Scheunemann)
Copyright (C) 2022 Andreas Achtzehn Copyright (C) 2022 Andreas Achtzehn (inspired by Helge Scheunemann)
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -27,8 +27,8 @@
\*********************************************************************************************/ \*********************************************************************************************/
// Define driver ID // Define driver ID
#define XSNS_101 101 #define XSNS_101 101
#define XI2C_73 73 // See I2CDEVICES.md #define XI2C_73 73 // See I2CDEVICES.md
/* The default I2C address of this chip */ /* The default I2C address of this chip */
#define HMC5883L_ADDR 0x1E #define HMC5883L_ADDR 0x1E
@ -45,8 +45,8 @@
#define HMC5883L_CONFIG_B 0x01 #define HMC5883L_CONFIG_B 0x01
#define HMC5883L_MODE 0x02 #define HMC5883L_MODE 0x02
#define HMC5883L_CHIP_ID_A 0x0A #define HMC5883L_CHIP_ID_A 0x0A
#define HMC5883L_CHIP_ID_B 0x0B #define HMC5883L_CHIP_ID_B 0x0B
#define HMC5883L_CHIP_ID_C 0x0C #define HMC5883L_CHIP_ID_C 0x0C
/* Bit values for the STATUS register */ /* Bit values for the STATUS register */
const uint8_t HMC5883L_STATUS_RDY = 0b00000001; const uint8_t HMC5883L_STATUS_RDY = 0b00000001;
@ -104,20 +104,21 @@ bool HMC5883L_SetConfig() {
uint8_t cfgB = (( (HMC5883L->gain ) << HMC5883L_CONFIG_B_GAIN_SHIFT ) & HMC5883L_CONFIG_B_GAIN_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); AddLog(LOG_LEVEL_INFO,"HMC: CONFIG A: %#X CONFIG B: %#X MODE: %#X", cfgA, cfgB, HMC5883L->mode);
if (I2cWrite8(HMC5883L_ADDR, HMC5883L_CONFIG_A, cfgA ) == false) { if (I2cWrite8(HMC5883L_ADDR, HMC5883L_CONFIG_A, cfgA ) == false) {
AddLog(LOG_LEVEL_INFO,"HMC5883L: Setting CONFIG A failed."); AddLog(LOG_LEVEL_INFO,"HMC: Setting CONFIG A failed");
return false; return false;
} }
if (I2cWrite8(HMC5883L_ADDR, HMC5883L_CONFIG_B, cfgB ) == false) { if (I2cWrite8(HMC5883L_ADDR, HMC5883L_CONFIG_B, cfgB ) == false) {
AddLog(LOG_LEVEL_INFO,"HMC5883L: Setting CONFIG B failed."); AddLog(LOG_LEVEL_INFO,"HMC: Setting CONFIG B failed");
return false; return false;
} }
if (HMC5883L->mode == HMC5883L_MODE_CONT) { if (HMC5883L->mode == HMC5883L_MODE_CONT) {
if (I2cWrite8(HMC5883L_ADDR, HMC5883L_MODE, HMC5883L_MODE_CONT ) == false) if (I2cWrite8(HMC5883L_ADDR, HMC5883L_MODE, HMC5883L_MODE_CONT ) == false) {
{ AddLog(LOG_LEVEL_INFO,"HMC5883L: Setting continuous mode failed."); AddLog(LOG_LEVEL_INFO,"HMC: Setting continuous mode failed");
return false; } return false;
}
} }
return true; return true;
} }
@ -142,11 +143,13 @@ void HMC5883L_Init() {
//Read the magnetic data //Read the magnetic data
void HMC5883L_ReadData(void) { void HMC5883L_ReadData(void) {
if (HMC5883L->mode == HMC5883L_MODE_SINGLE) { if (HMC5883L->mode == HMC5883L_MODE_SINGLE) {
if (I2cWrite8(HMC5883L_ADDR, HMC5883L_MODE, HMC5883L_MODE_SINGLE ) == false) if (I2cWrite8(HMC5883L_ADDR, HMC5883L_MODE, HMC5883L_MODE_SINGLE ) == false) { return; }
{ return; }
} }
while (!(I2cRead8(HMC5883L_ADDR, HMC5883L_STATUS) & HMC5883L_STATUS_RDY)) { } // Chip not yet ready, next round try again uint32_t timeout = millis() + 20;
while (!(I2cRead8(HMC5883L_ADDR, HMC5883L_STATUS) & HMC5883L_STATUS_RDY)) {
if (millis() > timeout) { return; } // Chip not yet ready, next round try again
}
HMC5883L->MX = I2cReadS16(HMC5883L_ADDR, HMC5883L_X_MSB); // Select starting with MSB register HMC5883L->MX = I2cReadS16(HMC5883L_ADDR, HMC5883L_X_MSB); // Select starting with MSB register
HMC5883L->MY = I2cReadS16(HMC5883L_ADDR, HMC5883L_Y_MSB); HMC5883L->MY = I2cReadS16(HMC5883L_ADDR, HMC5883L_Y_MSB);
@ -205,11 +208,11 @@ bool HMC5883L_Command() {
commandKnown = true; commandKnown = true;
} }
//AddLog(LOG_LEVEL_INFO,PSTR(D_LOG_I2C "HMC5883L: cmd: (%s) value: %d cmdKnown: %d"), cmd, value,commandKnown); //AddLog(LOG_LEVEL_INFO,PSTR(D_LOG_I2C "HMC: cmd: (%s) value: %d cmdKnown: %d"), cmd, value,commandKnown);
if (commandKnown == false) { return false; } if (commandKnown == false) { return false; }
AddLog(LOG_LEVEL_INFO,PSTR(D_LOG_I2C "HMC5883L: Reconfiguring.")); AddLog(LOG_LEVEL_INFO,PSTR(D_LOG_I2C "HMC: Reconfiguring."));
return HMC5883L_SetConfig(); return HMC5883L_SetConfig();
} }
@ -227,8 +230,9 @@ bool Xsns101(uint32_t function) {
else if (HMC5883L != nullptr) { else if (HMC5883L != nullptr) {
switch (function) { switch (function) {
case FUNC_COMMAND_SENSOR: case FUNC_COMMAND_SENSOR:
if (XSNS_101 == XdrvMailbox.index) if (XSNS_101 == XdrvMailbox.index) {
return HMC5883L_Command(); // Return true on success return HMC5883L_Command(); // Return true on success
}
break; break;
case FUNC_JSON_APPEND: case FUNC_JSON_APPEND:
HMC5883L_Show(1); HMC5883L_Show(1);

View File

@ -288,7 +288,7 @@ a_features = [[
],[ ],[
"USE_SGP40","USE_LUXV30B","USE_CANSNIFFER","USE_QMC5883L", "USE_SGP40","USE_LUXV30B","USE_CANSNIFFER","USE_QMC5883L",
"USE_MODBUS_ENERGY","USE_SHELLY_PRO","USE_DALI","USE_BP1658CJ", "USE_MODBUS_ENERGY","USE_SHELLY_PRO","USE_DALI","USE_BP1658CJ",
"USE_DINGTIAN_RELAY","","","", "USE_DINGTIAN_RELAY","USE_HMC5883L","","",
"","","","", "","","","",
"","","","", "","","","",
"","","","", "","","","",