diff --git a/CHANGELOG.md b/CHANGELOG.md index 156ca4f94..a7652faac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Support for Shelly Plus 2PM using template ``{"NAME":"Shelly Plus 2PM PCB v0.1.9","GPIO":[320,0,0,0,32,192,0,0,225,224,0,0,0,0,193,0,0,0,0,0,0,608,640,3458,0,0,0,0,0,9472,0,4736,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"}`` - Zigbee Alexa/Hue emulation, support multiple switches on separate endpoints +- Support for QMC5883L magnetic induction sensor by Helge Scheunemann (#16714) ### Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9da6261d7..24224aa94 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,9 +116,11 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Command ``UrlFetch `` to download a file to filesystem - Command ``DspSpeed 2..127`` to control message rotation speed on display of POWR3xxD and THR3xxD - Command ``DspLine<1|2> ,,,,...`` to select message(s) on display of POWR3xxD and THR3xxD +- Support for Shelly Plus 2PM - Support for SGP40 gas and air quality sensor [#16341](https://github.com/arendst/Tasmota/issues/16341) - Support for Modbus writing using ModbusBridge by JeroenSt [#16351](https://github.com/arendst/Tasmota/issues/16351) - Support for DFRobot SEN0390 V30B ambient light sensor [#16105](https://github.com/arendst/Tasmota/issues/16105) +- Support for QMC5883L magnetic induction sensor by Helge Scheunemann [#16714](https://github.com/arendst/Tasmota/issues/16714) - Zigbee device plugin mechanism with commands ``ZbLoad``, ``ZbUnload`` and ``ZbLoadDump`` [#16252](https://github.com/arendst/Tasmota/issues/16252) - Zigbee basic support for Green Power [#16407](https://github.com/arendst/Tasmota/issues/16407) - Zigbee friendly names per endpoint diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 77e301cd6..a32ced52e 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -685,6 +685,8 @@ // #define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 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_QMC5883L // [I2CDriver71] Enable QMC5883L magnetic induction sensor (I2C address 0x0D) (+0k8 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 USE_RTC_CHIPS // Enable RTC chip support and NTP server - Select only one // #define USE_DS3231 // [I2cDriver26] Enable DS3231 RTC (I2C address 0x68) (+1k2 code) @@ -715,8 +717,6 @@ // Reference: https://cdn-learn.adafruit.com/downloads/pdf/adafruit-led-backpack.pdf // #define SEVENSEG_ADDRESS1 0x70 // No longer used. Use MTX_ADDRESS1 - MTX_ADDRESS8 instead to specify I2C address of sevenseg displays // #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) -// #define USE_QMC5883L // USE_QMC5883L magnetic induction sensor, (I2C address 0x0D) -// #define QMC5883L_TEMP_SHIFT 23 // sensor temperature are not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet) #endif // USE_I2C diff --git a/tasmota/tasmota_support/support_features.ino b/tasmota/tasmota_support/support_features.ino index ca0cc27c9..54fe47a23 100644 --- a/tasmota/tasmota_support/support_features.ino +++ b/tasmota/tasmota_support/support_features.ino @@ -834,8 +834,9 @@ void ResponseAppendFeatures(void) #if defined(USE_SPI) && defined(USE_CANSNIFFER) feature9 |= 0x00000004; // xsns_87_can_sniffer.ino #endif -// feature9 |= 0x00000008; - +#if defined(USE_I2C) && defined(USE_QMC5883L) + feature9 |= 0x00000008; // xsns_33_qmc5882l.ino +#endif // feature9 |= 0x00000010; // feature9 |= 0x00000020; // feature9 |= 0x00000040; diff --git a/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino b/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino index 1122a389f..7c640a737 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino @@ -1,5 +1,5 @@ /* - xsns_99_qmc5883l.ino - QMC5883L 3-Axis Digital Compass sensor support for Tasmota + xsns_33_qmc5883l.ino - QMC5883L 3-Axis Digital Compass sensor support for Tasmota Copyright (C) 2022 Helge Scheunemann @@ -15,7 +15,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . +*/ +#ifdef USE_I2C +#ifdef USE_QMC5883L +/*********************************************************************************************\ + * QMC5883L is 3-Axis Digital Compass sensor + * + * I2C Address: 0x0D +\*********************************************************************************************/ +/* DATASHEET The QMC5883L is a multi-chip three-axis magnetic sensor. This @@ -152,21 +161,14 @@ */ -#ifdef USE_I2C -#ifdef USE_QMC5883L - -/*********************************************************************************************\ - * QMC5883L is 3-Axis Digital Compass sensor - * - * Source: Helge Scheunemann - * - * I2C Address: 0x0D -\*********************************************************************************************/ - // Define driver ID #define XSNS_33 33 #define XI2C_71 71 // See I2CDEVICES.md +#ifndef QMC5883L_TEMP_SHIFT +#define QMC5883L_TEMP_SHIFT 23 // sensor temperature are not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet) +#endif + /* The default I2C address of this chip */ #define QMC5883L_ADDR 0x0D @@ -215,49 +217,42 @@ #define QMC5883L_CONFIG2_RESET 0b10000000 // data field -struct QMC5883L_s -{ +struct QMC5883L_s { int16_t MX, MY, MZ; - int16_t temp; + float temp; uint16_t scalar; } *QMC5883L = nullptr; // Initialise the device -void QMC5883L_Init() -{ - if (!I2cSetDevice(QMC5883L_ADDR)) - { - return; - } - I2cSetActiveFound(QMC5883L_ADDR, "QMC5883L"); +void QMC5883L_Init() { + if (!I2cSetDevice(QMC5883L_ADDR)) { return; } // reset QMC5883L - if (I2cWrite8(QMC5883L_ADDR, QMC5883L_CONFIG2, QMC5883L_CONFIG2_RESET) == false) - return; // Software Reset - if (I2cWrite8(QMC5883L_ADDR, QMC5883L_RESET, 0x01) == false) - return; + if (I2cWrite8(QMC5883L_ADDR, QMC5883L_CONFIG2, QMC5883L_CONFIG2_RESET) == false) { return; } + // Software Reset + if (I2cWrite8(QMC5883L_ADDR, QMC5883L_RESET, 0x01) == false) { return; } // write config - if (I2cWrite8(QMC5883L_ADDR, QMC5883L_CONFIG, QMC5883L_CONFIG_OS256 | QMC5883L_CONFIG_8GAUSS | QMC5883L_CONFIG_100HZ | QMC5883L_CONFIG_CONT) == false) - return; + if (I2cWrite8(QMC5883L_ADDR, QMC5883L_CONFIG, QMC5883L_CONFIG_OS256 | QMC5883L_CONFIG_8GAUSS | QMC5883L_CONFIG_100HZ | QMC5883L_CONFIG_CONT) == false) { return; } + + I2cSetActiveFound(QMC5883L_ADDR, "QMC5883L"); QMC5883L = (QMC5883L_s *)calloc(1, sizeof(struct QMC5883L_s)); } //Read the magnetic data -void QMC5883L_read_data(void) -{ +void QMC5883L_read_data(void) { // check if chip is ready to provice data - if (!(I2cRead8(QMC5883L_ADDR, QMC5883L_STATUS) & QMC5883L_STATUS_DRDY)) - return; // chip not yet ready, next round try again + if (!(I2cRead8(QMC5883L_ADDR, QMC5883L_STATUS) & QMC5883L_STATUS_DRDY)) { return; } // Chip not yet ready, next round try again - QMC5883L->MX = I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_X_LSB); // select LSB register + QMC5883L->MX = I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_X_LSB); // Select LSB register QMC5883L->MY = I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_Y_LSB); QMC5883L->MZ = I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_Z_LSB); // calculate scalar magnetic induction - QMC5883L->scalar = sqrt((QMC5883L->MX * QMC5883L->MX) + (QMC5883L->MY * QMC5883L->MY) + (QMC5883L->MZ * QMC5883L->MZ)); +// QMC5883L->scalar = sqrt((QMC5883L->MX * QMC5883L->MX) + (QMC5883L->MY * QMC5883L->MY) + (QMC5883L->MZ * QMC5883L->MZ)); // 650 bytes larger + QMC5883L->scalar = SqrtInt((QMC5883L->MX * QMC5883L->MX) + (QMC5883L->MY * QMC5883L->MY) + (QMC5883L->MZ * QMC5883L->MZ)); // get temperature - QMC5883L->temp = (I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_TEMP_LSB) / 100) + QMC5883L_TEMP_SHIFT; + QMC5883L->temp = ConvertTemp((I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_TEMP_LSB) / 100) + QMC5883L_TEMP_SHIFT); // Temp in celsius } /*********************************************************************************************\ @@ -266,49 +261,36 @@ void QMC5883L_read_data(void) #ifdef USE_WEBSERVER const char HTTP_SNS_QMC5883L[] PROGMEM = - "{s}QMC5883L " D_MX "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_MY "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_MZ "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_MAGNETICFLD "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_TEMPERATURE "{m}%d " D_UNIT_DEGREE D_UNIT_CELSIUS "{e}"; // {s} = , {m} = , {e} = - -const char HTTP_SNS_QMC5883L_ERROR[] PROGMEM = - "{s}QMC5883L {m} %s {e}"; + "{s}QMC5883L " D_MX "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = + "{s}QMC5883L " D_MY "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = + "{s}QMC5883L " D_MZ "{m}%d " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = + "{s}QMC5883L " D_MAGNETICFLD "{m}%d " D_UNIT_MICROTESLA "{e}"; // {s} = , {m} = , {e} = #endif - -void QMC5883L_Show(uint8_t json) -{ - if (json) - { - ResponseAppend_P(PSTR(",\"QMC5883L\":{\"" D_JSON_MX "\":%d,\"" D_JSON_MY "\":%d,\"" D_JSON_MZ "\":%d,\"" D_JSON_MAGNETICFLD "\":%u,\"" D_JSON_TEMPERATURE "\":%d}"), QMC5883L->MX, QMC5883L->MY, QMC5883L->MZ, QMC5883L->scalar, QMC5883L->temp); - } +void QMC5883L_Show(uint8_t json) { + if (json) { + ResponseAppend_P(PSTR(",\"QMC5883L\":{\"" D_JSON_MX "\":%d,\"" D_JSON_MY "\":%d,\"" D_JSON_MZ "\":%d,\"" D_JSON_MAGNETICFLD "\":%u,\"" D_JSON_TEMPERATURE "\":%*_f}"), + QMC5883L->MX, QMC5883L->MY, QMC5883L->MZ, QMC5883L->scalar, Settings->flag2.temperature_resolution, &QMC5883L->temp); #ifdef USE_WEBSERVER - else - { - WSContentSend_PD(HTTP_SNS_QMC5883L, QMC5883L->MX, QMC5883L->MY, QMC5883L->MZ, QMC5883L->scalar, QMC5883L->temp); - } + } else { + WSContentSend_PD(HTTP_SNS_QMC5883L, QMC5883L->MX, QMC5883L->MY, QMC5883L->MZ, QMC5883L->scalar); + WSContentSend_Temp("QMC5883L", QMC5883L->temp); #endif + } } /*********************************************************************************************\ * Interface \*********************************************************************************************/ - -bool Xsns33(byte function) -{ - if (!I2cEnabled(XI2C_71)) - { - return false; - } - if (FUNC_INIT == function) - { + +bool Xsns33(byte function) { + if (!I2cEnabled(XI2C_71)) { return false; } + + if (FUNC_INIT == function) { QMC5883L_Init(); } - else if (QMC5883L != nullptr) - { - switch (function) - { + else if (QMC5883L != nullptr) { + switch (function) { case FUNC_JSON_APPEND: QMC5883L_Show(1); break; @@ -324,5 +306,5 @@ bool Xsns33(byte function) } return true; } -#endif // USE_QMC5883L -#endif // USE_I2C \ No newline at end of file +#endif // USE_QMC5883L +#endif // USE_I2C \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index 2d2ce4fa0..32afcd966 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -286,7 +286,7 @@ a_features = [[ "USE_PCF85363","USE_DS3502","USE_IMPROV","USE_FLOWRATEMETER", "USE_BP5758D","USE_HYT","USE_SM2335","USE_DISPLAY_TM1621_SONOFF" ],[ - "USE_SGP40","USE_LUXV30B","USE_CANSNIFFER","", + "USE_SGP40","USE_LUXV30B","USE_CANSNIFFER","USE_QMC5883L", "","","","", "","","","", "","","","", @@ -321,7 +321,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v12.1.1.2 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v12.1.1.4 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj))