From ad7c929d9be19a93b073357e203cb6e2144d3e5a Mon Sep 17 00:00:00 2001 From: Justifiably Date: Wed, 17 Jun 2020 14:53:38 +0100 Subject: [PATCH] Add support for LMT01 temperature sensor --- tasmota/language/en_GB.h | 1 + tasmota/my_user_config.h | 1 + tasmota/tasmota_configurations.h | 1 + tasmota/tasmota_template.h | 7 +- tasmota/tasmota_template_ESP32.h | 1 + tasmota/xsns_74_lmt01.ino | 146 +++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 tasmota/xsns_74_lmt01.ino diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 3011c2aa1..aade08f71 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -681,6 +681,7 @@ #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN" +#define D_SENSOR_LMT01_PULSE "LMT01 Pulse" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 689a440b5..42cf596bd 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -635,6 +635,7 @@ #define MAX31865_PTD_RES 100 // Nominal PTD resistance at 0°C (100Ω for a PT100, 1000Ω for a PT1000, YMMV!) #define MAX31865_REF_RES 430 // Reference resistor (Usually 430Ω for a PT100, 4300Ω for a PT1000) #define MAX31865_PTD_BIAS 0 // To calibrate your not-so-good PTD +//#define USE_LMT01 // Add support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code) // -- IR Remote features - all protocols from IRremoteESP8266 -------------------------- // IR Full Protocols mode is activated through platform.io only. diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index eb58d30e5..fa49ce2c4 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -176,6 +176,7 @@ #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) +#define USE_LMT01 // Add support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code) #define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) #define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) #define USE_HX711 // Add support for HX711 load cell (+1k5 code) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index afd707a80..30a3d9d90 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -238,6 +238,7 @@ enum UserSelectablePins { GPIO_TCP_RX, // TCP Serial bridge GPIO_TELEINFO_RX, // TELEINFO serial interface GPIO_TELEINFO_ENABLE,// TELEINFO Enable PIN + GPIO_LMT01, // LMT01 input counting pin GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -330,7 +331,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_WINDMETER_SPEED "|" D_SENSOR_BL0940_RX "|" D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD "|" - D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE + D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|" + D_SENSOR_LMT01_PULSE ; const char kSensorNamesFixed[] PROGMEM = @@ -696,6 +698,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_TELEINFO_RX, GPIO_TELEINFO_ENABLE, #endif +#ifdef USE_LMT01 // LMT01, count pulses on GPIO + GPIO_LMT01, +#endif }; /********************************************************************************************/ diff --git a/tasmota/tasmota_template_ESP32.h b/tasmota/tasmota_template_ESP32.h index 93e58b932..9a67d6d02 100644 --- a/tasmota/tasmota_template_ESP32.h +++ b/tasmota/tasmota_template_ESP32.h @@ -133,6 +133,7 @@ enum UserSelectablePins { GPIO_ETH_PHY_POWER, GPIO_ETH_PHY_MDC, GPIO_ETH_PHY_MDIO, // Ethernet GPIO_TELEINFO_RX, // Teleinfo telemetry data receive pin GPIO_TELEINFO_ENABLE, // Teleinfo Enable Receive Pin + GPIO_LMT01, // LMT01 input counting pin GPIO_SENSOR_END }; enum ProgramSelectablePins { diff --git a/tasmota/xsns_74_lmt01.ino b/tasmota/xsns_74_lmt01.ino new file mode 100644 index 000000000..1b3f363c9 --- /dev/null +++ b/tasmota/xsns_74_lmt01.ino @@ -0,0 +1,146 @@ +/* + xns_74_lmt01.ino + + Copyright (C) 2020 Theo Arends, Justifiably + + 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_LMT01 +/*********************************************************************************************\ + * LMT01 - 0.5°C Accurate 2-Pin Digital Output Temperature Sensor With Pulse Count Interface + * + * Uses fragments of public domain code LMT01_Example.ino released by Texas Instruments, July 10th 2017. + * See https://training.ti.com/how-interface-lmt01-temperature-sensor-arduino + * +\*********************************************************************************************/ + +#define XSNS_74 74 + +#define LMT01_TIMEOUT 200 // ms timeout for a reading cycle + +bool lmt01_initialized = false; +float lmt01_temperature = NAN; + +void LMT01_Init(void) { + if (PinUsed(GPIO_LMT01)) { + pinMode(Pin(GPIO_LMT01), INPUT); + attachInterrupt(Pin(GPIO_LMT01), LMT01_countPulse, FALLING); + lmt01_initialized = true; + } +} + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception +void LMT01_countPulse(void) ICACHE_RAM_ATTR; +#endif // ARDUINO_ESP8266_RELEASE_2_3_0 + +volatile int lmt01_pulseCount = 0; + +void LMT01_countPulse(void) { + lmt01_pulseCount++; +} + +void LMT01_GetTemperature(void) { + int pulses = 0; + pulses = LMT01_getPulses(); + if (pulses >= 0) { + // simple linear conversion, datasheet has a look-up table alternative + // which is accurate over a wider temperature range + lmt01_temperature = ConvertTemp(0.0625 * pulses - 50); + } else { + lmt01_temperature = NAN; // Timeout + } +} + +int LMT01_getPulses(void) { + int timeout = LMT01_TIMEOUT; + int hold = -1; + // complete current pulse cycle (50ms max) + while(lmt01_pulseCount != hold && --timeout > 0) { + hold = lmt01_pulseCount; + delay(1); + } + lmt01_pulseCount = 0; + // wait for start of next (54ms max) + while(lmt01_pulseCount == 0 && --timeout > 0) { + delay(1); + } + hold = -1; + // take this count (up to 50ms) + while(lmt01_pulseCount != hold && --timeout > 0) { + hold = lmt01_pulseCount; + delay(1); + } + if (timeout > 0) { + return hold; + } + return -1; +} + + +void LMT01_Show(bool Json) { + char temp[33]; + dtostrfd(lmt01_temperature, Settings.flag2.temperature_resolution, temp); + + if (Json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), \ + "LMT01", temp); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temp); + } +#endif // USE_DOMOTICZ +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, lmt01_temperature); + } +#endif // USE_KNX +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "LMT01", temp, TempUnit()); +#endif // USE_WEBSERVER + } +} + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns74(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + LMT01_Init(); + } + else if (lmt01_initialized) { + switch (function) { + case FUNC_EVERY_SECOND: + LMT01_GetTemperature(); + break; + case FUNC_JSON_APPEND: + LMT01_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + LMT01_Show(false); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_LMT01