diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index f3e9b0ea4..532682faf 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -728,9 +728,9 @@ https://rya.nc/tasmota-fingerprint.html" // #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) (+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_OVERSAMPLE 1 // 0 .. 3 => 512, 256(default), 128, 64 -// #define QMC5883L_GAUSS 0 // 0,1(default) => 2GAUSS, 8GAUSS(default) -// #define QMC5883L_FILTER 2 // 0 .. 3 => 10HZ, 50HZ, 109HZ(default), 200HZ +// #define QMC5883L_OVERSAMPLE 0 // 0 .. 3 => 512(default), 256, 128, 64 +// #define QMC5883L_GAUSS 1 // 0,1(default) => 2GAUSS, 8GAUSS(default) +// #define QMC5883L_FILTER 0 // 0 .. 3 => 10HZ(default), 50HZ, 100HZ, 200HZ // #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_MAX_COUNT // change the number of devices to search for (default 4). diff --git a/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino b/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino index f5c674d71..2dd2cca02 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_33_qmc5883l.ino @@ -1,7 +1,7 @@ /* xsns_33_qmc5883l.ino - QMC5883L 3-Axis Digital Compass sensor support for Tasmota - Copyright (C) 2022 Helge Scheunemann and Friedbert Bader + Copyright (C) 2022 Helge Scheunemann + fb-pilot 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 @@ -24,19 +24,20 @@ * * I2C Address: 0x0D * - * #define QMC5883L_OVERSAMPLE 1 // 0 .. 3 => 512, 256, 128, 64 - * #define QMC5883L_GAUSS 1 // 0,1 => 2GAUSS, 8GAUSS - * #define QMC5883L_FILTER 2 // 0 .. 3 => 10HZ, 50HZ, 109HZ, 200HZ - * #define QMC5883L_TEMP_SHIFT 23 // sensor temperature are not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet) - * - * Calibration : - * valid relations : 1 T = 10000 G ... 1G = 0.1mT = 100µT - * Dynamic Output Field Range ±2 or ±8 Gauss ==> ±200µT or ±800µT - * Sensitivity [1] - * Field Range = ±2G 12000 LSB/G --> factor = 120 - * Field Range = ±8G 3000 LSB/G --> factor = 30 + * #define QMC5883L_OVERSAMPLE 0 // 0 .. 3 => over Sample Ratio : 512, 256, 128, 64 + * #define QMC5883L_GAUSS 1 // 0 .. 1 => full Scale : 2GAUSS, 8GAUSS + * #define QMC5883L_FILTER 0 // 0 .. 3 => Output Data Rate : 10HZ, 50HZ, 109HZ, 200HZ + * #define QMC5883L_TEMP_SHIFT 23.0f // sensor temperature are not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet) + * #define QMC5883L_DECIMAL 4 // Decimals for display \*********************************************************************************************/ +#ifndef QMC5883L_TEMP_SHIFT +#define QMC5883L_TEMP_SHIFT 23.0f // sensor temperature is not calibrated (only relativ measurement) and need an absolute ground value in °C (see datasheet) +#endif +#ifndef QMC5883L_DECIMAL + #define QMC5883L_DECIMAL 4 +#endif + /* DATASHEET @@ -72,7 +73,21 @@ 0BH SET/RESET Period FBR [7:0] Read/Write 0CH Reserved Read only 0DH Reserved Read only - +/* Register numbers */ +#define QMC5883L_X_LSB 0x00 +#define QMC5883L_X_MSB 0x01 +#define QMC5883L_Y_LSB 0x02 +#define QMC5883L_Y_MSB 0x03 +#define QMC5883L_Z_LSB 0x04 +#define QMC5883L_Z_MSB 0x05 +#define QMC5883L_STATUS 0x06 +#define QMC5883L_TEMP_LSB 0x07 +#define QMC5883L_TEMP_MSB 0x08 +#define QMC5883L_CONFIG 0x09 +#define QMC5883L_CONFIG2 0x0a +#define QMC5883L_RESET 0x0b // SET/RESET Period it is recommended that the register 0BH is written by 0x01. +// #define QMC5883L_RESERVED 0x0c +/* 9.2 Register Definition 9.2.1 Output Data Register Registers 00H ~ 05H store the measurement data from each axis magnetic sensor in continuous-measurement. @@ -80,7 +95,20 @@ ODR setup in control registers 1. The data stays the same, regardless of reading status through I2C, until new data replaces them. Each axis has 16 bit data width in 2’s complement, i.e., MSB of 01H/03H/05H indicates the sign of each axis. The output data of each channel saturates at -32768 and 32767. + * Calibration : + * valid relations : 1 T = 10000 G ... 1G = 0.1mT = 100µT + * Dynamic Output Field Range ±2 or ±8 Gauss ==> ±200µT or ±800µT + * Sensitivity [1] + * Field Range = ±2G 12000 LSB/G --> factor = 120 + * Field Range = ±8G 3000 LSB/G --> factor = 30 +*/ +#if QMC5883L_GAUSS == 0 + #define QMC5883L_FACTOR 120.0f +#else + #define QMC5883L_FACTOR 30.0f +#endif +/* Table 14. Output Data Register Addr. 7 6 5 4 3 2 1 0 00H Data Output X LSB Register XOUT[7:0] @@ -97,8 +125,12 @@ Table 15. Status Register 1 Addr. 7 6 5 4 3 2 1 0 - 06H DOR OVL DRDY - + 06H DOR OVL DRDY +*/ +#define QMC5883L_STATUS_DRDY 1 +#define QMC5883L_STATUS_OVL 2 +// #define QMC5883L_STATUS_DOR 4 +/* Data Ready Register (DRDY), it is set when all three axis data is ready, and loaded to the output data registers in the continuous measurement mode. It is reset to “0” by reading any data register (00H~05H) through I2C commends @@ -143,14 +175,20 @@ Table 18. Control Register 1 Addr 7 6 5 4 3 2 1 0 - 09H OSR[1:0] RNG[1:0] ODR[1:0] MODE[1:0] - + 09H OSR[1:0] RNG[1:0] ODR[1:0] MODE[1:0] + Reg. Definition 00 01 10 11 Mode Mode Control Standby Continuous Reserve Reserve ODR Output Data Rate 10Hz 50Hz 100Hz 200Hz RNG Full Scale 2G 8G Reserve Reserve OSR Over Sample Ratio 512 256 128 64 - +*/ +// #define QMC5883L_CONFIG_STANDBY 0b00000000 + #define QMC5883L_CONFIG_CONT 0b00000001 + #define QMC5883L_SHIFT_ODR 2 // for QMC5883L_FILTER + #define QMC5883L_SHIFT_RNG 4 // for QMC5883L_GAUSS + #define QMC5883L_SHIFT_OSR 6 // for QMC5883L_OVERSAMPLE +/* Interrupt enabling is controlled by register INT_ENB in control register 2. Once the interrupt is enabled, it will flag when new data is in Data Output Registers. INT_ENB: “0”: enable interrupt PIN, “1”: disable interrupt PIN @@ -164,111 +202,50 @@ Table 19. Control Register 2 Addr. 7 6 5 4 3 2 1 0 0AH SOFT_RST ROL_PNT INT_ENB - +*/ +#define QMC5883L_CONFIG2_RESET 0b10000000 +/* 9.2.5 SET/RESET Period Register SET/RESET Period is controlled by FBR [7:0], it is recommended that the register 0BH is written by 0x01. Table 20. SET/RESET Period Register Addr. 7 6 5 4 3 2 1 0 0BH SET/RESET Perio [7:0] - */ // 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 -/* Register numbers */ -#define QMC5883L_X_LSB 0x00 -#define QMC5883L_X_MSB 0x01 -#define QMC5883L_Y_LSB 0x02 -#define QMC5883L_Y_MSB 0x03 -#define QMC5883L_Z_LSB 0x04 -#define QMC5883L_Z_MSB 0x05 -#define QMC5883L_STATUS 0x06 -#define QMC5883L_TEMP_LSB 0x07 -#define QMC5883L_TEMP_MSB 0x08 -#define QMC5883L_CONFIG 0x09 -#define QMC5883L_CONFIG2 0x0a -#define QMC5883L_RESET 0x0b // SET/RESET Period it is recommended that the register 0BH is written by 0x01. -// #define QMC5883L_RESERVED 0x0c #define QMC5883L_CHIP_ID 0x0d -/* Bit values for the STATUS register ... #define QMC5883L_STATUS 0x06 -*/ -#define QMC5883L_STATUS_DRDY 1 -#define QMC5883L_STATUS_OVL 2 -// #define QMC5883L_STATUS_DOR 4 - -/* set QMC5883L_STATUS_REG ... #define QMC5883L_CONFIG 0x09 - Addr 7 6 5 4 3 2 1 0 - 09H OSR[1:0] RNG[1:0] ODR[1:0] MODE[1:0] - Oversampling values for the CONFIG register - Reg. Definition 00 01 10 11 - OSR Over Sample Ratio 512 256 128 64 - - #define QMC5883L_OVERSAMPLE 1 // 0 .. 3 => 512, 256, 128, 64 -*/ #ifndef QMC5883L_OVERSAMPLE #define QMC5883L_OVERSAMPLE 1 #elif (QMC5883L_OVERSAMPLE>3) #undef QMC5883L_OVERSAMPLE #define QMC5883L_OVERSAMPLE 3 #endif - -/* Reg. Definition 00 01 10 11 - RNG Full Scale 2G 8G Reserve Reserve - #define QMC5883L_GAUSS 1 // 0,1 => 2GAUSS, 8GAUSS -*/ #ifndef QMC5883L_GAUSS #define QMC5883L_GAUSS 1 #elif (QMC5883L_GAUSS>1) #undef QMC5883L_GAUSS #define QMC5883L_GAUSS 1 #endif -#if QMC5883L_GAUSS == 0 - #define FACTOR 120 -#else - #define FACTOR 30 -#endif - - -/* Reg. Definition 00 01 10 11 - ODR Output Data Rate 10Hz 50Hz 100Hz 200Hz - #define QMC5883L_FILTER 2 // 0 .. 3 => 10HZ, 50HZ, 109HZ, 200HZ -*/ #ifndef QMC5883L_FILTER - #define QMC5883L_FILTER 2 + #define QMC5883L_FILTER 0 #elif (QMC5883L_FILTER>3) #undef QMC5883L_FILTER #define QMC5883L_FILTER 3 #endif - -/* Reg. Definition 00 01 10 11 - Mode Mode Control Standby Continuous Reserve Reserve */ -// #define QMC5883L_CONFIG_STANDBY 0b00000000 -#define QMC5883L_CONFIG_CONT 0b00000001 - -/* Mode values for the CONFIG2 register = Software Reset */ -#define QMC5883L_CONFIG2_RESET 0b10000000 - -#define REG_OVL 0x7fff -// #define OVL "overflow" -#define OVL INFINITY +#define QMC5883L_OVL INFINITY // data field struct QMC5883L_s { - int16_t MX, MY, MZ; -// uint16_t scalar; + float MX, MY, MZ; float temp; -// float MX, MY, MZ, scalar; bool ovl; } *QMC5883L = nullptr; @@ -284,8 +261,8 @@ void QMC5883L_Init() { Addr 7 6 5 4 3 2 1 0 09H OSR[1:0] RNG[1:0] ODR[1:0] MODE[1:0] */ AddLog(LOG_LEVEL_DEBUG,PSTR("QMC: QMC5883L_STATUS_REG 0x%X, size of buffer %d" ), - ((QMC5883L_OVERSAMPLE<<6) | (QMC5883L_GAUSS<<4) | (QMC5883L_FILTER<<2) | QMC5883L_CONFIG_CONT), sizeof(struct QMC5883L_s)); - if (I2cWrite8(QMC5883L_ADDR, QMC5883L_CONFIG, ((QMC5883L_OVERSAMPLE<<6) | (QMC5883L_GAUSS<<4) | (QMC5883L_FILTER<<2) | QMC5883L_CONFIG_CONT)) == false) { return; } + ((QMC5883L_OVERSAMPLE<ovl = false; - 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)); // 650 bytes larger - // QMC5883L->scalar = SqrtInt((QMC5883L->MX * QMC5883L->MX) + (QMC5883L->MY * QMC5883L->MY) + (QMC5883L->MZ * QMC5883L->MZ)); + QMC5883L->MX = (float) I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_X_LSB) / QMC5883L_FACTOR; // Select LSB register + QMC5883L->MY = (float) I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_Y_LSB) / QMC5883L_FACTOR; + QMC5883L->MZ = (float) I2cReadS16_LE(QMC5883L_ADDR, QMC5883L_Z_LSB) / QMC5883L_FACTOR; break; case 3: QMC5883L->ovl = true; AddLog(LOG_LEVEL_DEBUG,PSTR("QMC: QMC5883L_STATUS_Overflow")); - - QMC5883L->MX = REG_OVL; - QMC5883L->MY = REG_OVL; - QMC5883L->MZ = REG_OVL; - + QMC5883L->MX = \ + QMC5883L->MY = \ + QMC5883L->MZ = QMC5883L_OVL; break; default: return; @@ -326,36 +302,32 @@ void QMC5883L_read_data(void) { \*********************************************************************************************/ #ifdef USE_WEBSERVER +// {s} = , {m} = , {e} = const char HTTP_SNS_QMC5883L[] PROGMEM = - "{s}QMC5883L " D_MX "{m}%s " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_MY "{m}%s " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_MZ "{m}%s " D_UNIT_MICROTESLA "{e}" // {s} = , {m} = , {e} = - "{s}QMC5883L " D_MAGNETICFLD "{m}%s " D_UNIT_MICROTESLA "{e}"; // {s} = , {m} = , {e} = + "{s}QMC5883L " D_MX "{m}%*_f " D_UNIT_MICROTESLA "{e}" + "{s}QMC5883L " D_MY "{m}%*_f " D_UNIT_MICROTESLA "{e}" + "{s}QMC5883L " D_MZ "{m}%*_f " D_UNIT_MICROTESLA "{e}" + "{s}QMC5883L " D_MAGNETICFLD "{m}%*_f " D_UNIT_MICROTESLA "{e}"; #endif -void QMC5883L_Show(uint8_t json) { - char s_mx[12] ; - char s_my[12] ; - char s_mz[12] ; - char s_scalar[12] ; - if (!QMC5883L->ovl) { - dtostrfd((float)QMC5883L->MX / FACTOR, 3, s_mx); - dtostrfd((float)QMC5883L->MY / FACTOR, 3, s_my); - dtostrfd((float)QMC5883L->MZ / FACTOR, 3, s_mz); - dtostrfd((float)(SqrtInt((QMC5883L->MX * QMC5883L->MX) + (QMC5883L->MY * QMC5883L->MY) + (QMC5883L->MZ * QMC5883L->MZ))) / FACTOR, 3, s_scalar); - }else{ - dtostrfd(OVL, 3, s_mx); - dtostrfd(OVL, 3, s_my); - dtostrfd(OVL, 3, s_mz); - dtostrfd(OVL, 3, s_scalar); -// s_my = s_mz = s_scalar = s_mx; - } +void QMC5883L_Show(uint8_t json) +{ + float QMC5883L_MF = (float) sqrt((QMC5883L->MX * QMC5883L->MX) + (QMC5883L->MY * QMC5883L->MY) + (QMC5883L->MZ * QMC5883L->MZ)); if (json) { - ResponseAppend_P(PSTR(",\"QMC5883L\":{\"" D_JSON_MX "\":%s,\"" D_JSON_MY "\":%s,\"" D_JSON_MZ "\":%s,\"" D_JSON_MAGNETICFLD "\":%s,\"" D_JSON_TEMPERATURE "\":%*_f}"), - s_mx, s_my, s_mz, s_scalar, Settings->flag2.temperature_resolution, &QMC5883L->temp); + ResponseAppend_P(PSTR(",\"QMC5883L\":{\"" \ + D_JSON_MX "\":%*_f,\"" D_JSON_MY "\":%*_f,\"" D_JSON_MZ "\":%*_f,\"" \ + D_JSON_MAGNETICFLD "\":%*_f,\"" D_JSON_TEMPERATURE "\":%*_f}"),\ + QMC5883L_DECIMAL, &QMC5883L->MX, \ + QMC5883L_DECIMAL, &QMC5883L->MY, \ + QMC5883L_DECIMAL, &QMC5883L->MZ, \ + QMC5883L_DECIMAL, &QMC5883L_MF, \ + Settings->flag2.temperature_resolution, &QMC5883L->temp); #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_QMC5883L, s_mx, s_my, s_mz, s_scalar); + WSContentSend_PD(HTTP_SNS_QMC5883L, QMC5883L_DECIMAL, &QMC5883L->MX, \ + QMC5883L_DECIMAL, &QMC5883L->MY, \ + QMC5883L_DECIMAL, &QMC5883L->MZ, \ + QMC5883L_DECIMAL, &QMC5883L_MF); WSContentSend_Temp("QMC5883L", QMC5883L->temp); #endif } @@ -396,4 +368,4 @@ bool Xsns33(uint32_t function) { return result; } #endif // USE_QMC5883L -#endif // USE_I2C \ No newline at end of file +#endif // USE_I2C