From f81e0eb2e468caffabd9a54d77c2ad642ae04f23 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 9 Jul 2018 12:24:24 +0200 Subject: [PATCH 01/14] Change SHT1x sensor detection Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference --- sonoff/_releasenotes.ino | 1 + sonoff/xsns_07_sht1x.ino | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 4ce79838b..4595b8ab3 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) * Add experimental (untested) TM1638 switch support (#2226) * Add support for APDS9960 proximity sensor (#3051) diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 98837471b..be86b3c21 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -231,7 +231,8 @@ boolean Xsns07(byte function) if (i2c_flg) { switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: +// case FUNC_PREP_BEFORE_TELEPERIOD: // As this is not a real I2C device it may interfere with other sensors + case FUNC_INIT: // Move detection to restart only removing interference ShtDetect(); break; case FUNC_JSON_APPEND: From cc24dd11ce3e68a0dcac2564e5c7317602306ecd Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 9 Jul 2018 12:41:17 +0200 Subject: [PATCH 02/14] Update TSL2561 library Remove TSL2561 debug message and update library (#2415) --- .../COPYING | 0 .../COPYING.LESSER | 0 .../README | 0 .../examples/Autogain/Autogain.ino | 32 ++++++---- .../examples/Simple/Simple.ino | 13 +++- .../examples/Testing/Testing.ino | 25 +++++--- .../examples/Utility/Utility.ino | 21 +++++-- .../examples/platformio.ini | 61 +++++++++++++++++++ lib/Joba_Tsl2561-2.0.7/examples/platformio.sh | 12 ++++ lib/Joba_Tsl2561-2.0.7/lib/readme.txt | 36 +++++++++++ .../library.json | 2 +- .../library.properties | 2 +- lib/Joba_Tsl2561-2.0.7/platformio.ini | 58 ++++++++++++++++++ .../src/Tsl2561.cpp | 24 +++++--- .../src/Tsl2561.h | 0 .../src/Tsl2561Util.cpp | 56 +++++++++++------ .../src/Tsl2561Util.h | 14 ++++- sonoff/_releasenotes.ino | 1 + sonoff/xsns_16_tsl2561.ino | 6 +- 19 files changed, 306 insertions(+), 57 deletions(-) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/COPYING (100%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/COPYING.LESSER (100%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/README (100%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/examples/Autogain/Autogain.ino (54%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/examples/Simple/Simple.ino (76%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/examples/Testing/Testing.ino (82%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/examples/Utility/Utility.ino (70%) create mode 100644 lib/Joba_Tsl2561-2.0.7/examples/platformio.ini create mode 100644 lib/Joba_Tsl2561-2.0.7/examples/platformio.sh create mode 100644 lib/Joba_Tsl2561-2.0.7/lib/readme.txt rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/library.json (93%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/library.properties (95%) create mode 100644 lib/Joba_Tsl2561-2.0.7/platformio.ini rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/src/Tsl2561.cpp (85%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/src/Tsl2561.h (100%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/src/Tsl2561Util.cpp (78%) rename lib/{Joba_Tsl2561 => Joba_Tsl2561-2.0.7}/src/Tsl2561Util.h (79%) diff --git a/lib/Joba_Tsl2561/COPYING b/lib/Joba_Tsl2561-2.0.7/COPYING similarity index 100% rename from lib/Joba_Tsl2561/COPYING rename to lib/Joba_Tsl2561-2.0.7/COPYING diff --git a/lib/Joba_Tsl2561/COPYING.LESSER b/lib/Joba_Tsl2561-2.0.7/COPYING.LESSER similarity index 100% rename from lib/Joba_Tsl2561/COPYING.LESSER rename to lib/Joba_Tsl2561-2.0.7/COPYING.LESSER diff --git a/lib/Joba_Tsl2561/README b/lib/Joba_Tsl2561-2.0.7/README similarity index 100% rename from lib/Joba_Tsl2561/README rename to lib/Joba_Tsl2561-2.0.7/README diff --git a/lib/Joba_Tsl2561/examples/Autogain/Autogain.ino b/lib/Joba_Tsl2561-2.0.7/examples/Autogain/Autogain.ino similarity index 54% rename from lib/Joba_Tsl2561/examples/Autogain/Autogain.ino rename to lib/Joba_Tsl2561-2.0.7/examples/Autogain/Autogain.ino index 03da78d46..169d2b6e3 100644 --- a/lib/Joba_Tsl2561/examples/Autogain/Autogain.ino +++ b/lib/Joba_Tsl2561-2.0.7/examples/Autogain/Autogain.ino @@ -21,6 +21,17 @@ This file is part of the Joba_Tsl2561 Library. #include +// to mimic Serial.printf() of esp8266 core for other platforms +char *format( const char *fmt, ... ) { + static char buf[128]; + va_list arg; + va_start(arg, fmt); + vsnprintf(buf, sizeof(buf), fmt, arg); + buf[sizeof(buf)-1] = '\0'; + va_end(arg); + return buf; +} + Tsl2561 Tsl(Wire); uint8_t id; @@ -35,31 +46,30 @@ void setup() { } void loop() { - uint16_t scaledFull = ~0, scaledIr = ~0; - uint32_t full = ~0, ir = ~0, milliLux = ~0; + uint16_t scaledFull = 0xffff, scaledIr = 0xffff; + uint32_t full = 0xffffffff, ir = 0xffffffff, milliLux = 0xffffffff; bool gain = false; Tsl2561::exposure_t exposure = Tsl2561::EXP_OFF; if( Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) ) { if( Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) ) { - if( Tsl2561Util::milliLux(full, ir, milliLux, Tsl2561::packageCS(id)) ) { - Serial.printf("Tsl2561 addr: 0x%02x, id: 0x%02x, sfull: %5u, sir: %5u, full: %5u, ir: %5u, gain: %d, exp: %d, lux: %5u.%03u\n", - Tsl.address(), id, scaledFull, scaledIr, full, ir, gain, exposure, milliLux/1000, milliLux%1000); + if( Tsl2561Util::milliLux(full, ir, milliLux, Tsl2561::packageCS(id), 5) ) { + Serial.print(format("Tsl2561 addr: 0x%02x, id: 0x%02x, sfull: %5u, sir: %5u, full: %7lu, ir: %7lu, gain: %d, exp: %d, lux: %5lu.%03lu\n", + Tsl.address(), id, scaledFull, scaledIr, (unsigned long)full, (unsigned long)ir, gain, exposure, (unsigned long)milliLux/1000, (unsigned long)milliLux%1000)); } else { - Serial.printf("Tsl2561Util::milliLux(full=%u, ir=%u) error\n", full, ir); + Serial.print(format("Tsl2561Util::milliLux(full=%lu, ir=%lu) error\n", (unsigned long)full, (unsigned long)ir)); } } else { - Serial.printf("Tsl2561Util::normalizedLuminosity(gain=%u, exposure=%u, sfull=%u, sir=%u, full=%u, ir=%u) error\n", - gain, exposure, scaledFull, scaledIr, full, ir); + Serial.print(format("Tsl2561Util::normalizedLuminosity(gain=%u, exposure=%u, sfull=%u, sir=%u, full=%lu, ir=%lu) error\n", + gain, exposure, scaledFull, scaledIr, (unsigned long)full, (unsigned long)ir)); } } else { - Serial.printf("Tsl2561Util::autoGain(gain=%u, exposure=%u, sfull=%u, sir=%u) error\n", - gain, exposure, scaledFull, scaledIr); + Serial.print(format("Tsl2561Util::autoGain(gain=%u, exposure=%u, sfull=%u, sir=%u) error\n", + gain, exposure, scaledFull, scaledIr)); } delay(1000); } - diff --git a/lib/Joba_Tsl2561/examples/Simple/Simple.ino b/lib/Joba_Tsl2561-2.0.7/examples/Simple/Simple.ino similarity index 76% rename from lib/Joba_Tsl2561/examples/Simple/Simple.ino rename to lib/Joba_Tsl2561-2.0.7/examples/Simple/Simple.ino index f1c2d88d9..5bebb7e50 100644 --- a/lib/Joba_Tsl2561/examples/Simple/Simple.ino +++ b/lib/Joba_Tsl2561-2.0.7/examples/Simple/Simple.ino @@ -21,6 +21,17 @@ This file is part of the Joba_Tsl2561 Library. #include +// to mimic Serial.printf() of esp8266 core for other platforms +char *format( const char *fmt, ... ) { + static char buf[128]; + va_list arg; + va_start(arg, fmt); + vsnprintf(buf, sizeof(buf), fmt, arg); + buf[sizeof(buf)-1] = '\0'; + va_end(arg); + return buf; +} + Tsl2561 Tsl(Wire); void setup() { @@ -44,7 +55,7 @@ void loop() { Tsl.fullLuminosity(full); Tsl.irLuminosity(ir); - Serial.printf("Tsl2561 at 0x%02x(id=0x%02x) luminosity is %5u (full) and %5u (ir)\n", Tsl.address(), id, full, ir); + Serial.print(format("Tsl2561 at 0x%02x(id=0x%02x) luminosity is %5u (full) and %5u (ir)\n", Tsl.address(), id, full, ir)); Tsl.off(); } diff --git a/lib/Joba_Tsl2561/examples/Testing/Testing.ino b/lib/Joba_Tsl2561-2.0.7/examples/Testing/Testing.ino similarity index 82% rename from lib/Joba_Tsl2561/examples/Testing/Testing.ino rename to lib/Joba_Tsl2561-2.0.7/examples/Testing/Testing.ino index 8fc6d121a..0dbeb09be 100644 --- a/lib/Joba_Tsl2561/examples/Testing/Testing.ino +++ b/lib/Joba_Tsl2561-2.0.7/examples/Testing/Testing.ino @@ -22,11 +22,22 @@ This file is part of the Joba_Tsl2561 Library. #include +// to mimic Serial.printf() of esp8266 core for other platforms +char *format( const char *fmt, ... ) { + static char buf[128]; + va_list arg; + va_start(arg, fmt); + vsnprintf(buf, sizeof(buf), fmt, arg); + buf[sizeof(buf)-1] = '\0'; + va_end(arg); + return buf; +} + Tsl2561 Tsl(Wire); void showError( Tsl2561 &tsl ) { Tsl2561::status_t status = tsl.status(); - Serial.printf("Error was %u: ", status); + Serial.print(format("Error was %u: ", status)); switch( status ) { case Tsl2561::ERR_OK: Serial.println("None"); break; case Tsl2561::ERR_RW: Serial.println("Read/Write"); break; @@ -40,7 +51,7 @@ void showError( Tsl2561 &tsl ) { void testSensitivity( Tsl2561 &tsl, bool newGain, Tsl2561::exposure_t newExp ) { if( tsl.on() ) { uint32_t start = millis(); - Serial.printf("Chip powered on at %u\n", start); + Serial.print(format("Chip powered on at %lu\n", (unsigned long)start)); bool chipGain; Tsl2561::exposure_t chipExp; @@ -58,7 +69,7 @@ void testSensitivity( Tsl2561 &tsl, bool newGain, Tsl2561::exposure_t newExp ) { bool check = true; if( change ) { if( tsl.setSensitivity(newGain, newExp) ) { - Serial.printf("New gain = %d, exposure = 0x%02x\n", newGain, newExp); + Serial.print(format("New gain = %d, exposure = 0x%02x\n", newGain, newExp)); } else { check = false; @@ -69,6 +80,7 @@ void testSensitivity( Tsl2561 &tsl, bool newGain, Tsl2561::exposure_t newExp ) { if( check ) { uint16_t ir, full = 0; + while( !full && millis() - start < 1000 ) { if( !tsl.fullLuminosity(full) ) { Serial.print("Check full luminosity failed. "); @@ -89,7 +101,7 @@ void testSensitivity( Tsl2561 &tsl, bool newGain, Tsl2561::exposure_t newExp ) { Serial.println("No luminosity reading after 1s. Too dark?"); } else { - Serial.printf("Got luminosity after %d ms. Full spectrum is %d and IR only is %d\n", millis() - start, full, ir); + Serial.print(format("Got luminosity after %lu ms. Full spectrum is %u and IR only is %u\n", (unsigned long)millis() - start, full, ir)); } } @@ -107,7 +119,7 @@ void testSensitivity( Tsl2561 &tsl, bool newGain, Tsl2561::exposure_t newExp ) { bool testPackage( Tsl2561 &tsl ) { uint8_t id; if( tsl.id(id) ) { - Serial.printf("Chip has type %02x and revision %x\n", Tsl2561::type(id), Tsl2561::revision(id) ); + Serial.print(format("Chip has type %02x and revision %x\n", Tsl2561::type(id), Tsl2561::revision(id))); if( Tsl2561::packageT_FN_CL(id) ) { Serial.println("Chip is a T, FN or CL type package"); } @@ -128,7 +140,7 @@ bool testPackage( Tsl2561 &tsl ) { void test( Tsl2561 &tsl ) { bool ok = tsl.available(); - Serial.printf("\nTesting Tsl2561 at address %02x: %sfound\n", tsl.address(), ok ? "" : "NOT "); + Serial.print(format("\nTesting Tsl2561 at address %02x: %sfound\n", tsl.address(), ok ? "" : "NOT ")); if( ok ) { if( testPackage(tsl) ) { testSensitivity(tsl, Tsl2561::GAIN_OFF, Tsl2561::EXP_402); @@ -160,4 +172,3 @@ void loop() { Serial.println("\nNext test in 5s\n"); delay(5000); } - diff --git a/lib/Joba_Tsl2561/examples/Utility/Utility.ino b/lib/Joba_Tsl2561-2.0.7/examples/Utility/Utility.ino similarity index 70% rename from lib/Joba_Tsl2561/examples/Utility/Utility.ino rename to lib/Joba_Tsl2561-2.0.7/examples/Utility/Utility.ino index 58e03ca14..d05549616 100644 --- a/lib/Joba_Tsl2561/examples/Utility/Utility.ino +++ b/lib/Joba_Tsl2561-2.0.7/examples/Utility/Utility.ino @@ -21,6 +21,17 @@ This file is part of the Joba_Tsl2561 Library. #include +// to mimic Serial.printf() of esp8266 core for other platforms +char *format( const char *fmt, ... ) { + static char buf[128]; + va_list arg; + va_start(arg, fmt); + vsnprintf(buf, sizeof(buf), fmt, arg); + buf[sizeof(buf)-1] = '\0'; + va_end(arg); + return buf; +} + Tsl2561::address_t addr[] = { Tsl2561::ADDR_GND, Tsl2561::ADDR_FLOAT, Tsl2561::ADDR_VDD }; Tsl2561 Tsl(Wire); @@ -58,18 +69,19 @@ void loop() { Tsl.fullLuminosity(scaledFull); Tsl.irLuminosity(scaledIr); - Serial.printf("Tsl2561 addr: 0x%02x, id: 0x%02x, sfull: %5u, sir: %5u, gain: %d, exp: %d", addr[i], id, scaledFull, scaledIr, gain, exposure); + Serial.print(format("Tsl2561 addr: 0x%02x, id: 0x%02x, sfull: %5u, sir: %5u, gain: %d, exp: %d", + addr[i], id, scaledFull, scaledIr, gain, exposure)); if( Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) ) { if( Tsl2561Util::milliLux(full, ir, milliLux, Tsl2561::packageCS(id)) ) { - Serial.printf(", full: %5u, ir: %5u, lux: %5u.%03u\n", full, ir, milliLux/1000, milliLux%1000); + Serial.print(format(", full: %5lu, ir: %5lu, lux: %5lu.%03lu\n", (unsigned long)full, (unsigned long)ir, (unsigned long)milliLux/1000, (unsigned long)milliLux%1000)); } else { - Serial.printf(", full: %5u, ir: %5u: Tsl2561Util::milliLux() error\n", full, ir); + Serial.print(format(", full: %5lu, ir: %5lu: Tsl2561Util::milliLux() error\n", (unsigned long)full, (unsigned long)ir)); } } else { - Serial.printf(", full: %5u, ir: %5u: Tsl2561Util::normalizedLuminosity() error\n", full, ir); + Serial.print(format(", full: %5lu, ir: %5lu: Tsl2561Util::normalizedLuminosity() error\n", (unsigned long)full, (unsigned long)ir)); } Tsl.off(); @@ -84,4 +96,3 @@ void loop() { delay(5000); } - diff --git a/lib/Joba_Tsl2561-2.0.7/examples/platformio.ini b/lib/Joba_Tsl2561-2.0.7/examples/platformio.ini new file mode 100644 index 000000000..ef71e03ae --- /dev/null +++ b/lib/Joba_Tsl2561-2.0.7/examples/platformio.ini @@ -0,0 +1,61 @@ +; PlatformIO Project Configuration File +; +; Example config for flashing nodemcuv2 boards via linux serial port +; +; Adapt (e.g. platform, board, port) to your environment as needed. +; Then call platformio.sh to copy the file to all examples. +; Now cd to the example directory (e.g. Autogain/) and do "pio run" +; to build it or directly upload with "pio run --target upload". +; Watch the serial output of your sketch with "pio device monitor". +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +[platformio] +src_dir = . +lib_dir = ../.. + +; uncomment one, if you want to build only one +; env_default = nodemcuv2 +; env_default = nano328 + +[env:nodemcuv2] +; TSL <-> ESP8266 +; ------------ +; GND <-> GND +; VCC <-> 3V +; SCL <-> D1 +; SDA <-> D2 +platform = espressif8266 +board = nodemcuv2 +framework = arduino +build_flags = -Wall + +monitor_speed = 115200 + +upload_speed = 230400 +upload_resetmethod = nodemcu +;usually upload port is autodetected +;upload_port = /dev/ttyUSB[1-9] + + +[env:nano328] +; TSL <-> NANO +; ------------ +; GND <-> GND +; VCC <-> 3V3 +; SCL <-> A5 +; SDA <-> A4 +platform = atmelavr +board = nanoatmega328 +framework = arduino +build_flags = -Wall + +monitor_speed = 115200 +;upload_port = /dev/ttyUSB[1-9] diff --git a/lib/Joba_Tsl2561-2.0.7/examples/platformio.sh b/lib/Joba_Tsl2561-2.0.7/examples/platformio.sh new file mode 100644 index 000000000..e5f0d3f76 --- /dev/null +++ b/lib/Joba_Tsl2561-2.0.7/examples/platformio.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Create platformio.ini templates for all examples, if missing. +# Start this script from within the examples directory. + +for d in *; do + if [ -d "$d" -a -f "$d/$d.ino" -a ! -e "$d/platformio.ini" ] + then + cp -av platformio.ini "$d/" + fi +done + diff --git a/lib/Joba_Tsl2561-2.0.7/lib/readme.txt b/lib/Joba_Tsl2561-2.0.7/lib/readme.txt new file mode 100644 index 000000000..dbadc3d63 --- /dev/null +++ b/lib/Joba_Tsl2561-2.0.7/lib/readme.txt @@ -0,0 +1,36 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +More information about PlatformIO Library Dependency Finder +- http://docs.platformio.org/page/librarymanager/ldf.html diff --git a/lib/Joba_Tsl2561/library.json b/lib/Joba_Tsl2561-2.0.7/library.json similarity index 93% rename from lib/Joba_Tsl2561/library.json rename to lib/Joba_Tsl2561-2.0.7/library.json index cacc33d5a..94585c488 100644 --- a/lib/Joba_Tsl2561/library.json +++ b/lib/Joba_Tsl2561-2.0.7/library.json @@ -1,6 +1,6 @@ { "name": "Joba_Tsl2561", - "version": "2.0.1", + "version": "2.0.7", "keywords": "twowire, i2c, bus, sensor, luminosity, illuminance, lux", "description": "Arduino Library for ams (taos) luminance chip Tsl2561 with autogain", "repository": diff --git a/lib/Joba_Tsl2561/library.properties b/lib/Joba_Tsl2561-2.0.7/library.properties similarity index 95% rename from lib/Joba_Tsl2561/library.properties rename to lib/Joba_Tsl2561-2.0.7/library.properties index 148736de6..ba1840764 100644 --- a/lib/Joba_Tsl2561/library.properties +++ b/lib/Joba_Tsl2561-2.0.7/library.properties @@ -1,5 +1,5 @@ name=Joba Tsl2561 Library -version=2.0.1 +version=2.0.7 author=joba-1 maintainer=joba-1 sentence=IoT library for using the Tsl2561 luminosity sensor diff --git a/lib/Joba_Tsl2561-2.0.7/platformio.ini b/lib/Joba_Tsl2561-2.0.7/platformio.ini new file mode 100644 index 000000000..ea6847aaa --- /dev/null +++ b/lib/Joba_Tsl2561-2.0.7/platformio.ini @@ -0,0 +1,58 @@ +; PlatformIO Project Configuration File +; +; Example config for flashing nodemcuv2 boards via linux serial port +; +; Adapt (e.g. platform, board, port) to your environment as needed. +; Then call platformio.sh to copy the file to all examples. +; Now cd to the example directory (e.g. Autogain/) and do "pio run" +; to build it or directly upload with "pio run --target upload". +; Watch the serial output of your sketch with "pio device monitor". +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +[platformio] +; uncomment one, if you want to build only one +; env_default = nodemcuv2 +; env_default = nano328 + + +[env:nodemcuv2] +; TSL <-> ESP8266 +; ------------ +; GND <-> GND +; VCC <-> 3V +; SCL <-> D1 +; SDA <-> D2 +platform = espressif8266 +board = nodemcuv2 +framework = arduino +build_flags = -Wall + +monitor_speed = 115200 + +upload_speed = 230400 +upload_resetmethod = nodemcu +;usually upload port is autodetected +;upload_port = /dev/ttyUSB[1-9] + + +[env:nano328] +; TSL <-> NANO +; ------------ +; GND <-> GND +; VCC <-> 3V3 +; SCL <-> A5 +; SDA <-> A4 +platform = atmelavr +board = nanoatmega328 +framework = arduino +build_flags = -Wall + +monitor_speed = 115200 diff --git a/lib/Joba_Tsl2561/src/Tsl2561.cpp b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561.cpp similarity index 85% rename from lib/Joba_Tsl2561/src/Tsl2561.cpp rename to lib/Joba_Tsl2561-2.0.7/src/Tsl2561.cpp index ad347f071..f0e324eb8 100644 --- a/lib/Joba_Tsl2561/src/Tsl2561.cpp +++ b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561.cpp @@ -29,7 +29,7 @@ bool Tsl2561::available() { bool Tsl2561::begin( address_t addr ) { _addr = addr; - return available(); + return available(); } bool Tsl2561::begin() { @@ -48,24 +48,30 @@ bool Tsl2561::begin() { bool Tsl2561::readByte( register_t reg, uint8_t &val ) { _wire.beginTransmission(_addr); _wire.write(reg | CONTROL_CMD); - if( _wire.endTransmission(false) == ERR_OK ) { - if( _wire.requestFrom(_addr, 1) ) { + if( (_status = static_cast(_wire.endTransmission(false))) == ERR_OK ) { + if( _wire.requestFrom(_addr, 1) == 1 ) { val = static_cast(_wire.read()); } + else { + _status = ERR_RW; + } } - return (_status = static_cast(_wire.endTransmission())) == ERR_OK; + return _status == ERR_OK; } bool Tsl2561::readWord( register_t reg, uint16_t &val ) { _wire.beginTransmission(_addr); _wire.write(reg | CONTROL_CMD); - if( _wire.endTransmission(false) == ERR_OK ) { - if( _wire.requestFrom(_addr, 2) ) { - val = (uint16_t)_wire.read() & 0xff; - val |= ((uint16_t)_wire.read() & 0xff) << 8; + if( (_status = static_cast(_wire.endTransmission(false))) == ERR_OK ) { + if( _wire.requestFrom(_addr, 2) == 2 ) { + val = static_cast(_wire.read()) & 0xff; + val |= (static_cast(_wire.read()) & 0xff) << 8; + } + else { + _status = ERR_RW; } } - return (_status = static_cast(_wire.endTransmission())) == ERR_OK; + return _status == ERR_OK; } bool Tsl2561::writeByte( register_t reg, uint8_t val ) { diff --git a/lib/Joba_Tsl2561/src/Tsl2561.h b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561.h similarity index 100% rename from lib/Joba_Tsl2561/src/Tsl2561.h rename to lib/Joba_Tsl2561-2.0.7/src/Tsl2561.h diff --git a/lib/Joba_Tsl2561/src/Tsl2561Util.cpp b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561Util.cpp similarity index 78% rename from lib/Joba_Tsl2561/src/Tsl2561Util.cpp rename to lib/Joba_Tsl2561-2.0.7/src/Tsl2561Util.cpp index 92997b60b..ae811f743 100644 --- a/lib/Joba_Tsl2561/src/Tsl2561Util.cpp +++ b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561Util.cpp @@ -39,22 +39,22 @@ bool normalizedLuminosity( bool gain, Tsl2561::exposure_t exposure, uint32_t &fu switch( exposure ) { case Tsl2561::EXP_14: - full = (scaledFull >= 5047/4*3) ? ~0 : ((full + 5) * 322) / 11; - ir = (scaledIr >= 5047/4*3) ? ~0 : ((ir + 5) * 322) / 11; + full = (scaledFull >= 5047/4*3) ? 0xffffffff : ((full + 5) * 322) / 11; + ir = (scaledIr >= 5047/4*3) ? 0xffffffff : ((ir + 5) * 322) / 11; break; case Tsl2561::EXP_101: - full = (scaledFull >= 37177/4*3) ? ~0 : ((full + 40) * 322) / 81; - ir = (scaledIr >= 37177/4*3) ? ~0 : ((ir + 40) * 322) / 81; + full = (scaledFull >= 37177/4*3) ? 0xffffffff : ((full + 40) * 322) / 81; + ir = (scaledIr >= 37177/4*3) ? 0xffffffff : ((ir + 40) * 322) / 81; break; case Tsl2561::EXP_402: - if( scaledFull >= 65535/4*3 ) full = ~0; - if( scaledIr >= 65535/4*3 ) ir = ~0; + if( scaledFull >= 65535/4*3 ) full = 0xffffffff; + if( scaledIr >= 65535/4*3 ) ir = 0xffffffff; break; default: return false; } - return full != ~0U && ir != ~0U; + return full != 0xffffffff && ir != 0xffffffff; } return false; @@ -72,9 +72,9 @@ uint16_t getLimit( Tsl2561::exposure_t exposure ) { // Wait for one measurement interval plus some empirically tested extra millis void waitNext( Tsl2561::exposure_t exposure ) { switch( exposure ) { - case Tsl2561::EXP_14: delay(16); break; - case Tsl2561::EXP_101: delay(103); break; - default: delay(408); break; + case Tsl2561::EXP_14: delay(Tsl2561Util::DELAY_EXP_14); break; + case Tsl2561::EXP_101: delay(Tsl2561Util::DELAY_EXP_101); break; + default: delay(Tsl2561Util::DELAY_EXP_402); break; } } @@ -95,7 +95,7 @@ bool autoGain( Tsl2561 &tsl, bool &gain, Tsl2561::exposure_t &exposure, uint16_t // get current sensitivity if( !tsl.getSensitivity(gain, exposure) ) { - return false; + return false; // I2C error } // find index of current sensitivity @@ -111,11 +111,13 @@ bool autoGain( Tsl2561 &tsl, bool &gain, Tsl2561::exposure_t &exposure, uint16_t } // in a loop wait for next sample, get values and adjust sensitivity if needed + uint8_t retryOnSaturated = 10; + while( true ) { waitNext(exposure); if( !tsl.fullLuminosity(full) || !tsl.irLuminosity(ir) ) { - return false; + return false; // I2C error } uint16_t limit = getLimit(exposure); @@ -126,13 +128,15 @@ bool autoGain( Tsl2561 &tsl, bool &gain, Tsl2561::exposure_t &exposure, uint16_t if( (full < 1000 && ++curr < sizeof(sensitivity)/sizeof(sensitivity[0])) || (full > limit && curr-- > 0) ) { if( !tsl.setSensitivity(sensitivity[curr].gain, sensitivity[curr].exposure) ) { - return false; + return false; // I2C error } gain = sensitivity[curr].gain; exposure = sensitivity[curr].exposure; } else { - return true; // saturated, but best we can do + if( ++curr > 0 && retryOnSaturated-- == 0 ) { + return true; // saturated, but best we can do + } } } } @@ -141,16 +145,32 @@ bool autoGain( Tsl2561 &tsl, bool &gain, Tsl2561::exposure_t &exposure, uint16_t bool compensateTemperature( int16_t centiCelsius, uint32_t &full, uint32_t &ir ) { // assume linear gradient 0% at 25°C to +20% at 70°C if( centiCelsius >= -3000 && centiCelsius <= 7000 ) { - full -= (full * (centiCelsius - 2500) * 20) / (100 * (7000 - 2500)); - ir -= (ir * (centiCelsius - 2500) * 20) / (100 * (7000 - 2500)); + full -= (full * (centiCelsius - 2500)) / (5 * (7000 - 2500)); + ir -= (ir * (centiCelsius - 2500)) / (5 * (7000 - 2500)); return true; } return false; } +// Round num after valid digits +uint32_t significance( uint32_t num, uint8_t digits ) { + uint8_t len = 1; + uint32_t n = num; + while( n /= 10 ) { + len++; + } + + uint32_t e10 = 1; + while( len-- > digits ) { + e10 *= 10; + } + + return ((num + e10 / 2) / e10) * e10; +} + // Calculate lux from raw luminosity values -bool milliLux( uint32_t full, uint32_t ir, uint32_t &mLux, bool csType ) { +bool milliLux( uint32_t full, uint32_t ir, uint32_t &mLux, bool csType, uint8_t digits ) { if( !full ) { mLux = 0; return true; @@ -187,6 +207,8 @@ bool milliLux( uint32_t full, uint32_t ir, uint32_t &mLux, bool csType ) { mLux /= 400 * 16 / 193; // 33 = counts/lux (cpl) } + mLux = significance(mLux, digits); // only the first 4 digits seem to make sense. + return true; } diff --git a/lib/Joba_Tsl2561/src/Tsl2561Util.h b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561Util.h similarity index 79% rename from lib/Joba_Tsl2561/src/Tsl2561Util.h rename to lib/Joba_Tsl2561-2.0.7/src/Tsl2561Util.h index 58c5d4bbf..5b831183d 100644 --- a/lib/Joba_Tsl2561/src/Tsl2561Util.h +++ b/lib/Joba_Tsl2561-2.0.7/src/Tsl2561Util.h @@ -24,6 +24,14 @@ This file is part of the Joba_Tsl2561 Library. namespace Tsl2561Util { + // Some chips may need higher values. + // Tweak here if autogain does not return valid results. + typedef enum { + DELAY_EXP_14 = 20, // Max. delay in ms after + DELAY_EXP_101 = 110, // starting a measurement until + DELAY_EXP_402 = 430 // the first values arrive. + } delay_t; + // delay until next sample is available void waitNext( Tsl2561::exposure_t exposure ); @@ -40,9 +48,11 @@ namespace Tsl2561Util { // adjust luminosity according to sensor temperature (max +/-20% from 25°C) bool compensateTemperature( int16_t centiCelsius, uint32_t &full, uint32_t &ir ); - // calculate lux from normalized (and optionally temperature adjusted) luminosity - bool milliLux( uint32_t full, uint32_t ir, uint32_t &milliLux, bool csType = false ); + // helper function to round after significant digits (~4 digits for Tsl2561) + uint32_t significance( uint32_t value, uint8_t digits ); + // calculate lux from normalized (and optionally temperature adjusted) luminosity + bool milliLux( uint32_t full, uint32_t ir, uint32_t &milliLux, bool csType = false, uint8_t digits = 4 ); }; #endif diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 4595b8ab3..6fd301922 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Remove TSL2561 debug message and update library (#2415) * Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) * Add experimental (untested) TM1638 switch support (#2226) diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 63abbc4a1..ac0536c6a 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -63,9 +63,9 @@ void Tsl2561Show(boolean json) && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) && Tsl2561Util::milliLux(full, ir, milliLux, Tsl2561::packageCS(id))) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_ILLUMINANCE " g:%d, e:%d, f:%u, i:%u -> %u.%03u " D_UNIT_LUX), - gain, exposure, full, ir, milliLux/1000, milliLux%1000); - AddLog(LOG_LEVEL_DEBUG); +// snprintf_P(log_data, sizeof(log_data), PSTR(D_ILLUMINANCE " g:%d, e:%d, f:%u, i:%u -> %u.%03u " D_UNIT_LUX), +// gain, exposure, full, ir, milliLux/1000, milliLux%1000); +// AddLog(LOG_LEVEL_DEBUG); if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), From fb41466cb7b6341930b7bbeac375a09f4308430d Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 9 Jul 2018 14:18:26 +0200 Subject: [PATCH 03/14] Change DS18B20 driver Change DS18B20 driver to provide better instant results --- sonoff/_releasenotes.ino | 1 + sonoff/xsns_05_ds18b20.ino | 73 ++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 6fd301922..65bde0745 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Change DS18B20 driver to provide instant results * Remove TSL2561 debug message and update library (#2415) * Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index dabaf25d4..12ebe3be2 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -26,9 +26,12 @@ #define W1_CONVERT_TEMP 0x44 #define W1_READ_SCRATCHPAD 0xBE -float ds18b20_last_temperature = 0; +#define DS18B20_MAX_MISS 5 + +float ds18b20_temperature = 0; uint16_t ds18b20_last_result = 0; uint8_t ds18x20_pin = 0; +uint8_t ds18b20_second = 0; /*********************************************************************************************\ * Embedded stripped and tuned OneWire library @@ -126,12 +129,7 @@ boolean OneWireCrc8(uint8_t *addr) /********************************************************************************************/ -void Ds18x20Init() -{ - ds18x20_pin = pin[GPIO_DSB]; -} - -void Ds18x20Convert() +void Ds18b20Convert() { OneWireReset(); OneWireWrite(W1_SKIP_ROM); // Address all Sensors on Bus @@ -139,25 +137,16 @@ void Ds18x20Convert() // delay(750); // 750ms should be enough for 12bit conv } -boolean Ds18b20Read(float &t) +void Ds18b20Read() { uint8_t data[9]; int8_t sign = 1; - if (!ds18b20_last_temperature) { - t = NAN; - } else { - ds18b20_last_result++; - if (ds18b20_last_result > 4) { // Reset after 4 misses - ds18b20_last_temperature = NAN; - } - t = ds18b20_last_temperature; - } - + if (ds18b20_last_result) { ds18b20_last_result--; } /* - if (!OneWireReadBit()) { //check measurement end + if (!OneWireReadBit()) { // Check end of measurement AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_BUSY)); - return !isnan(t); + return; } */ for (uint8_t retry = 0; retry < 3; retry++) { @@ -173,36 +162,40 @@ boolean Ds18b20Read(float &t) temp12 = (~temp12) +1; sign = -1; } - t = ConvertTemp(sign * temp12 * 0.0625); - ds18b20_last_result = 0; - } - if (!isnan(t)) { - ds18b20_last_temperature = t; - return true; + ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625); + ds18b20_last_result = DS18B20_MAX_MISS; + return; } } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return !isnan(t); +} + +/********************************************************************************************/ + +void Ds18b20EverySecond() +{ + ds18x20_pin = pin[GPIO_DSB]; + ds18b20_second++; + if (ds18b20_second &1) { + Ds18b20Convert(); // Start conversion, takes up to one second + } else { + Ds18b20Read(); // Read temperature + } } void Ds18b20Show(boolean json) { - float t; - - if (Ds18b20Read(t)) { // Check if read failed + if (ds18b20_last_result) { // Check for valid temperature char temperature[10]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - + dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); if(json) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"DS18B20\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, temperature); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); + if (0 == tele_period) { DomoticzSensor(DZ_TEMP, temperature); } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - } + if (0 == tele_period) { KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); } #endif // USE_KNX #ifdef USE_WEBSERVER } else { @@ -210,7 +203,6 @@ void Ds18b20Show(boolean json) #endif // USE_WEBSERVER } } - Ds18x20Convert(); // Start conversion, takes up to one second } /*********************************************************************************************\ @@ -225,11 +217,8 @@ boolean Xsns05(byte function) if (pin[GPIO_DSB] < 99) { switch (function) { - case FUNC_INIT: - Ds18x20Init(); - break; - case FUNC_PREP_BEFORE_TELEPERIOD: - Ds18x20Convert(); // Start conversion, takes up to one second + case FUNC_EVERY_SECOND: + Ds18b20EverySecond(); break; case FUNC_JSON_APPEND: Ds18b20Show(1); From d875b0b1adc18cea65dad2368bb89159a058947b Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 9 Jul 2018 15:50:52 +0200 Subject: [PATCH 04/14] Change DS18x20 driver Change DS18x20 driver to provide better instant results (#3169) --- sonoff/_releasenotes.ino | 3 +- sonoff/xsns_05_ds18x20.ino | 108 ++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 65bde0745..f18c25b6b 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,5 +1,6 @@ /* 6.1.0a - * Change DS18B20 driver to provide instant results + * Change DS18x20 driver to provide better instant results (#3169) + * Change DS18B20 driver to provide better instant results * Remove TSL2561 debug message and update library (#2415) * Change SHT1x sensor initialization from pre-teleperiod to once during restart to fix I2C interference * Add wifi and mqtt status led blinkyblinky to be disabled by SetOption31 1. Does not work when LedPower is On (deliberate) (#871, #2230, #3114, #3155) diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 292191b18..96c6ef335 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -33,15 +33,24 @@ #define W1_WRITE_SCRATCHPAD 0x4E #define W1_READ_SCRATCHPAD 0xBE +#define DS18X20_MAX_MISS 5 #define DS18X20_MAX_SENSORS 8 +typedef struct DS18X20SENSORS { + uint8_t address[8]; + uint8_t index; + uint8_t result; + float temperature; +} Ds18x20Sensor; + const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; -uint8_t ds18x20_address[DS18X20_MAX_SENSORS][8]; -uint8_t ds18x20_index[DS18X20_MAX_SENSORS] = { 0 }; + +Ds18x20Sensor ds18x20_sensor[DS18X20_MAX_SENSORS]; uint8_t ds18x20_sensors = 0; uint8_t ds18x20_pin = 0; +uint8_t ds18x20_second = 0; char ds18x20_types[9]; /*********************************************************************************************\ @@ -248,26 +257,26 @@ void Ds18x20Init() ds18x20_pin = pin[GPIO_DSB]; OneWireResetSearch(); for (ds18x20_sensors = 0; ds18x20_sensors < DS18X20_MAX_SENSORS; ds18x20_sensors) { - if (!OneWireSearch(ds18x20_address[ds18x20_sensors])) { + if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { break; } - if (OneWireCrc8(ds18x20_address[ds18x20_sensors]) && - ((ds18x20_address[ds18x20_sensors][0] == DS18S20_CHIPID) || - (ds18x20_address[ds18x20_sensors][0] == DS1822_CHIPID) || - (ds18x20_address[ds18x20_sensors][0] == DS18B20_CHIPID) || - (ds18x20_address[ds18x20_sensors][0] == MAX31850_CHIPID))) { - ds18x20_index[ds18x20_sensors] = ds18x20_sensors; - ids[ds18x20_sensors] = ds18x20_address[ds18x20_sensors][0]; // Chip id + if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && + ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { + ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; + ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; // Chip id for (uint8_t j = 6; j > 0; j--) { - ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_address[ds18x20_sensors][j]; + ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; } ds18x20_sensors++; } } for (uint8_t i = 0; i < ds18x20_sensors; i++) { for (uint8_t j = i + 1; j < ds18x20_sensors; j++) { - if (ids[ds18x20_index[i]] > ids[ds18x20_index[j]]) { // Sort ascending - std::swap(ds18x20_index[i], ds18x20_index[j]); + if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { // Sort ascending + std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); } } } @@ -283,7 +292,7 @@ void Ds18x20Convert() // delay(750); // 750ms should be enough for 12bit conv } -boolean Ds18x20Read(uint8_t sensor, float &t) +void Ds18x20Read(uint8_t sensor) { uint8_t data[9]; int8_t sign = 1; @@ -291,17 +300,17 @@ boolean Ds18x20Read(uint8_t sensor, float &t) int16_t temp14 = 0; float temp9 = 0.0; - t = NAN; - + uint8_t index = ds18x20_sensor[sensor].index; + if (ds18x20_sensor[index].result) { ds18x20_sensor[index].result--; } for (uint8_t retry = 0; retry < 3; retry++) { OneWireReset(); - OneWireSelect(ds18x20_address[ds18x20_index[sensor]]); + OneWireSelect(ds18x20_sensor[index].address); OneWireWrite(W1_READ_SCRATCHPAD); for (uint8_t i = 0; i < 9; i++) { data[i] = OneWireRead(); } if (OneWireCrc8(data)) { - switch(ds18x20_address[ds18x20_index[sensor]][0]) { + switch(ds18x20_sensor[index].address[0]) { case DS18S20_CHIPID: if (data[1] > 0x80) { data[0] = (~data[0]) +1; @@ -312,19 +321,20 @@ boolean Ds18x20Read(uint8_t sensor, float &t) } else { temp9 = (data[0] >> 1) * sign; } - t = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - break; + ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + ds18x20_sensor[index].result = DS18X20_MAX_MISS; + return; case DS1822_CHIPID: case DS18B20_CHIPID: if (data[4] != 0x7F) { data[4] = 0x7F; // Set resolution to 12-bit OneWireReset(); - OneWireSelect(ds18x20_address[ds18x20_index[sensor]]); + OneWireSelect(ds18x20_sensor[index].address); OneWireWrite(W1_WRITE_SCRATCHPAD); OneWireWrite(data[2]); // Th Register OneWireWrite(data[3]); // Tl Register OneWireWrite(data[4]); // Configuration Register - OneWireSelect(ds18x20_address[ds18x20_index[sensor]]); + OneWireSelect(ds18x20_sensor[index].address); OneWireWrite(W1_WRITE_EEPROM); // Save scratchpad to EEPROM } temp12 = (data[1] << 8) + data[0]; @@ -332,41 +342,54 @@ boolean Ds18x20Read(uint8_t sensor, float &t) temp12 = (~temp12) +1; sign = -1; } - t = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 - break; + ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 + ds18x20_sensor[index].result = DS18X20_MAX_MISS; + return; case MAX31850_CHIPID: temp14 = (data[1] << 8) + (data[0] & 0xFC); - t = ConvertTemp(temp14 * 0.0625); // Divide by 16 - break; + ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); // Divide by 16 + ds18x20_sensor[index].result = DS18X20_MAX_MISS; + return; } } - if (!isnan(t)) { - return true; - } } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return false; +} + +/********************************************************************************************/ + +void Ds18x20EverySecond() +{ + ds18x20_second++; + if (ds18x20_second &1) { + Ds18x20Convert(); // Start conversion, takes up to one second + } else { + for (uint8_t i = 0; i < ds18x20_sensors; i++) { + Ds18x20Read(i); // Read temperature + } + } } void Ds18x20Show(boolean json) { char temperature[10]; char stemp[12]; - float t; bool domoticz_flag = true; for (uint8_t i = 0; i < ds18x20_sensors; i++) { - if (Ds18x20Read(i, t)) { // Check if read failed - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + uint8_t index = ds18x20_sensor[i].index; - uint8_t index = sizeof(ds18x20_chipids); - while (index) { - if (ds18x20_address[ds18x20_index[i]][0] == ds18x20_chipids[index]) { + if (ds18x20_sensor[index].result) { // Check for valid temperature + dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); + + uint8_t idx = sizeof(ds18x20_chipids); + while (idx) { + if (ds18x20_sensor[ds18x20_sensor[idx].index].address[0] == ds18x20_chipids[idx]) { break; } - index--; + idx--; } - GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); + GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), idx, kDs18x20Types); snprintf_P(stemp, sizeof(stemp), PSTR("%s-%d"), ds18x20_types, i +1); if (json) { @@ -375,7 +398,7 @@ void Ds18x20Show(boolean json) } else { char address[17]; for (byte j = 0; j < 6; j++) { - sprintf(address+2*j, "%02X", ds18x20_address[ds18x20_index[i]][6-j]); // Skip sensor type and crc + sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, stemp, address, temperature); } @@ -387,7 +410,7 @@ void Ds18x20Show(boolean json) #endif // USE_DOMOTICZ #ifdef USE_KNX if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); } #endif // USE_KNX #ifdef USE_WEBSERVER @@ -397,7 +420,6 @@ void Ds18x20Show(boolean json) } } } - Ds18x20Convert(); // Start conversion, takes up to one second } /*********************************************************************************************\ @@ -415,8 +437,8 @@ boolean Xsns05(byte function) case FUNC_INIT: Ds18x20Init(); break; - case FUNC_PREP_BEFORE_TELEPERIOD: - Ds18x20Convert(); // Start conversion, takes up to one second + case FUNC_EVERY_SECOND: + Ds18x20EverySecond(); break; case FUNC_JSON_APPEND: Ds18x20Show(1); From 0c902b7d642739c2e7a253eaa0b086cfbdafa58b Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 9 Jul 2018 16:39:24 +0200 Subject: [PATCH 05/14] Change DHT driver Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) --- sonoff/_releasenotes.ino | 1 + sonoff/xsns_05_ds18b20.ino | 6 +-- sonoff/xsns_05_ds18x20.ino | 18 ++++---- sonoff/xsns_06_dht.ino | 84 +++++++++++++++++--------------------- 4 files changed, 48 insertions(+), 61 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index f18c25b6b..0bb9f9aec 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) * Change DS18x20 driver to provide better instant results (#3169) * Change DS18B20 driver to provide better instant results * Remove TSL2561 debug message and update library (#2415) diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 12ebe3be2..505f75a76 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -29,9 +29,8 @@ #define DS18B20_MAX_MISS 5 float ds18b20_temperature = 0; -uint16_t ds18b20_last_result = 0; +uint8_t ds18b20_last_result = 0; uint8_t ds18x20_pin = 0; -uint8_t ds18b20_second = 0; /*********************************************************************************************\ * Embedded stripped and tuned OneWire library @@ -175,8 +174,7 @@ void Ds18b20Read() void Ds18b20EverySecond() { ds18x20_pin = pin[GPIO_DSB]; - ds18b20_second++; - if (ds18b20_second &1) { + if (uptime &1) { Ds18b20Convert(); // Start conversion, takes up to one second } else { Ds18b20Read(); // Read temperature diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 96c6ef335..5a64ddc29 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -36,21 +36,18 @@ #define DS18X20_MAX_MISS 5 #define DS18X20_MAX_SENSORS 8 -typedef struct DS18X20SENSORS { - uint8_t address[8]; - uint8_t index; - uint8_t result; - float temperature; -} Ds18x20Sensor; - const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; -Ds18x20Sensor ds18x20_sensor[DS18X20_MAX_SENSORS]; +struct DS18X20STRUCT { + uint8_t address[8]; + uint8_t index; + uint8_t result; + float temperature; +} ds18x20_sensor[DS18X20_MAX_SENSORS]; uint8_t ds18x20_sensors = 0; uint8_t ds18x20_pin = 0; -uint8_t ds18x20_second = 0; char ds18x20_types[9]; /*********************************************************************************************\ @@ -360,8 +357,7 @@ void Ds18x20Read(uint8_t sensor) void Ds18x20EverySecond() { - ds18x20_second++; - if (ds18x20_second &1) { + if (uptime &1) { Ds18x20Convert(); // Start conversion, takes up to one second } else { for (uint8_t i = 0; i < ds18x20_sensors; i++) { diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 91a154169..855248a71 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -139,45 +139,30 @@ void DhtRead(byte sensor) } } -boolean DhtReadTempHum(byte sensor, float &t, float &h) +void DhtReadTempHum(byte sensor) { - if (NAN == Dht[sensor].h) { - t = NAN; - h = NAN; - } else { - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { // Reset after 8 misses - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - t = Dht[sensor].t; - h = Dht[sensor].h; + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { // Reset after 8 misses + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; } - DhtRead(sensor); if (!Dht[sensor].lastresult) { switch (Dht[sensor].type) { case GPIO_DHT11: - h = dht_data[0]; - t = dht_data[2]; + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); // Issue #3164 break; case GPIO_DHT22: case GPIO_SI7021: - h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; if (dht_data[2] & 0x80) { - t *= -1; + Dht[sensor].t *= -1; } break; } - t = ConvertTemp(t); - if (!isnan(t)) { - Dht[sensor].t = t; - } - if (!isnan(h)) { - Dht[sensor].h = h; - } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); } - return (!isnan(t) && !isnan(h)); } boolean DhtSetup(byte pin, byte type) @@ -210,6 +195,17 @@ void DhtInit() } } +void DhtEverySecond() +{ + if (uptime &1) { + DhtReadPrep(); + } else { + for (byte i = 0; i < dht_sensors; i++) { + DhtReadTempHum(i); + } + } +} + void DhtShow(boolean json) { char temperature[10]; @@ -217,34 +213,30 @@ void DhtShow(boolean json) byte dsxflg = 0; for (byte i = 0; i < dht_sensors; i++) { - float t = NAN; - float h = NAN; - if (DhtReadTempHum(i, t, h)) { // Read temperature - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, temperature, humidity); + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, temperature, humidity); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && !dsxflg) { - DomoticzTempHumSensor(temperature, humidity); - dsxflg++; - } + if ((0 == tele_period) && !dsxflg) { + DomoticzTempHumSensor(temperature, humidity); + dsxflg++; + } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } #endif // USE_KNX #ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, Dht[i].stype, temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, Dht[i].stype, humidity); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, Dht[i].stype, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, Dht[i].stype, humidity); #endif // USE_WEBSERVER - } } } } @@ -264,8 +256,8 @@ boolean Xsns06(byte function) case FUNC_INIT: DhtInit(); break; - case FUNC_PREP_BEFORE_TELEPERIOD: - DhtReadPrep(); + case FUNC_EVERY_SECOND: + DhtEverySecond(); break; case FUNC_JSON_APPEND: DhtShow(1); From 39a0867b6ace22264b1766bd43913ea250d85e0e Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 9 Jul 2018 17:59:56 +0200 Subject: [PATCH 06/14] Fix DHT driver Fix DHT driver mixing values for different sensors (#1797) --- sonoff/_releasenotes.ino | 1 + sonoff/xsns_06_dht.ino | 52 +++++++++++++++++----------------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 0bb9f9aec..5669dd625 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Fix DHT driver mixing values for different sensors (#1797) * Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) * Change DS18x20 driver to provide better instant results (#3169) * Change DS18B20 driver to provide better instant results diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 855248a71..a44abf400 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -28,7 +28,6 @@ #define DHT_MAX_SENSORS 3 #define DHT_MAX_RETRY 8 -#define MIN_INTERVAL 2000 uint32_t dht_max_cycles; uint8_t dht_data[5]; @@ -63,15 +62,10 @@ int32_t DhtExpectPulse(byte sensor, bool level) return count; } -void DhtRead(byte sensor) +boolean DhtRead(byte sensor) { int32_t cycles[80]; - uint32_t currenttime = millis(); - - if ((currenttime - Dht[sensor].lastreadtime) < MIN_INTERVAL) { - return; - } - Dht[sensor].lastreadtime = currenttime; + uint8_t error = 0; dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; @@ -99,27 +93,27 @@ void DhtRead(byte sensor) delayMicroseconds(10); if (-1 == DhtExpectPulse(sensor, LOW)) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - Dht[sensor].lastresult++; - return; + error = 1; } - if (-1 == DhtExpectPulse(sensor, HIGH)) { + else if (-1 == DhtExpectPulse(sensor, HIGH)) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - Dht[sensor].lastresult++; - return; + error = 1; } - for (int i = 0; i < 80; i += 2) { - cycles[i] = DhtExpectPulse(sensor, LOW); - cycles[i+1] = DhtExpectPulse(sensor, HIGH); + else { + for (int i = 0; i < 80; i += 2) { + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); + } } interrupts(); + if (error) { return false; } for (int i = 0; i < 40; ++i) { int32_t lowCycles = cycles[2*i]; int32_t highCycles = cycles[2*i+1]; if ((-1 == lowCycles) || (-1 == highCycles)) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - Dht[sensor].lastresult++; - return; + return false; } dht_data[i/8] <<= 1; if (highCycles > lowCycles) { @@ -131,12 +125,12 @@ void DhtRead(byte sensor) dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF); AddLog(LOG_LEVEL_DEBUG); - if (dht_data[4] == ((dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF)) { - Dht[sensor].lastresult = 0; - } else { + if (dht_data[4] != ((dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF)) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE)); - Dht[sensor].lastresult++; + return false; } + + return true; } void DhtReadTempHum(byte sensor) @@ -145,8 +139,7 @@ void DhtReadTempHum(byte sensor) Dht[sensor].t = NAN; Dht[sensor].h = NAN; } - DhtRead(sensor); - if (!Dht[sensor].lastresult) { + if (DhtRead(sensor)) { switch (Dht[sensor].type) { case GPIO_DHT11: Dht[sensor].h = dht_data[0]; @@ -162,6 +155,9 @@ void DhtReadTempHum(byte sensor) break; } Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; } } @@ -211,7 +207,6 @@ void DhtShow(boolean json) char temperature[10]; char humidity[10]; - byte dsxflg = 0; for (byte i = 0; i < dht_sensors; i++) { dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); @@ -219,19 +214,16 @@ void DhtShow(boolean json) if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, temperature, humidity); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && !dsxflg) { + if ((0 == tele_period) && (0 == i)) { DomoticzTempHumSensor(temperature, humidity); - dsxflg++; } #endif // USE_DOMOTICZ - #ifdef USE_KNX - if (0 == tele_period) { + if ((0 == tele_period) && (0 == i)) { KnxSensor(KNX_TEMPERATURE, Dht[i].t); KnxSensor(KNX_HUMIDITY, Dht[i].h); } #endif // USE_KNX - #ifdef USE_WEBSERVER } else { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, Dht[i].stype, temperature, TempUnit()); From e7a21887d38080bbaa82d35ef8a6e7467142b18a Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Tue, 10 Jul 2018 15:50:07 +0200 Subject: [PATCH 07/14] Change SHT1x driver Change SHT1x driver to provide better instant results --- sonoff/_releasenotes.ino | 1 + sonoff/xsns_07_sht1x.ino | 79 ++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 5669dd625..449e402b3 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Change SHT1x driver to provide better instant results * Fix DHT driver mixing values for different sensors (#1797) * Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) * Change DS18x20 driver to provide better instant results (#3169) diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index be86b3c21..b285ab6fd 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -34,9 +34,14 @@ enum { SHT1X_CMD_SOFT_RESET = B00011110 }; +#define SHT_MAX_MISS 5 + uint8_t sht_sda_pin; uint8_t sht_scl_pin; uint8_t sht_type = 0; +uint8_t sht_valid = 0; +float sht_temperature = 0; +float sht_humidity = 0; boolean ShtReset() { @@ -119,46 +124,32 @@ int ShtReadData() return val; } -boolean ShtReadTempHum(float &t, float &h) +boolean ShtRead() { - float tempRaw; - float humRaw; - float rhLinear; + if (sht_valid) { sht_valid--; } + if (!ShtReset()) { return false; } + if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } + if (!ShtAwaitResult()) { return false; } + float tempRaw = ShtReadData(); + if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } + if (!ShtAwaitResult()) { return false; } + float humRaw = ShtReadData(); - t = NAN; - h = NAN; - - if (!ShtReset()) { - return false; - } - if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { - return false; - } - if (!ShtAwaitResult()) { - return false; - } - tempRaw = ShtReadData(); // Temperature conversion coefficients from SHT1X datasheet for version 4 const float d1 = -39.7; // 3.5V const float d2 = 0.01; // 14-bit - t = d1 + (tempRaw * d2); - if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { - return false; - } - if (!ShtAwaitResult()) { - return false; - } - humRaw = ShtReadData(); - // Temperature conversion coefficients from SHT1X datasheet for version 4 + sht_temperature = d1 + (tempRaw * d2); const float c1 = -2.0468; const float c2 = 0.0367; const float c3 = -1.5955E-6; const float t1 = 0.01; const float t2 = 0.00008; - rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; - h = (t - 25) * (t1 + t2 * humRaw) + rhLinear; - t = ConvertTemp(t); - return (!isnan(t) && !isnan(h)); + float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; + sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; + sht_temperature = ConvertTemp(sht_temperature); + + sht_valid = SHT_MAX_MISS; + return true; } /********************************************************************************************/ @@ -169,12 +160,9 @@ void ShtDetect() return; } - float t; - float h; - sht_sda_pin = pin[GPIO_I2C_SDA]; sht_scl_pin = pin[GPIO_I2C_SCL]; - if (ShtReadTempHum(t, h)) { + if (ShtRead()) { sht_type = 1; AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); } else { @@ -183,32 +171,32 @@ void ShtDetect() } } +void ShtEverySecond() +{ + if (!(uptime %3)) { ShtRead(); } // Update every 3 seconds +} + void ShtShow(boolean json) { if (sht_type) { - float t; - float h; - - if (ShtReadTempHum(t, h)) { + if (sht_valid) { char temperature[10]; char humidity[10]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzTempHumSensor(temperature, humidity); #endif // USE_DOMOTICZ - #ifdef USE_KNX if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); + KnxSensor(KNX_TEMPERATURE, sht_temperature); + KnxSensor(KNX_HUMIDITY, sht_humidity); } #endif // USE_KNX - #ifdef USE_WEBSERVER } else { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SHT1X", temperature, TempUnit()); @@ -235,6 +223,9 @@ boolean Xsns07(byte function) case FUNC_INIT: // Move detection to restart only removing interference ShtDetect(); break; + case FUNC_EVERY_SECOND: + ShtEverySecond(); + break; case FUNC_JSON_APPEND: ShtShow(1); break; From 8fdcbaa8e156b5b20f32d7704ab32974d0b9a10f Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Tue, 10 Jul 2018 22:12:16 +0200 Subject: [PATCH 08/14] Add read sensor retry Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 --- sonoff/_releasenotes.ino | 1 + sonoff/i18n.h | 1 + sonoff/sonoff.h | 2 + sonoff/support.ino | 6 ++ sonoff/xsns_05_ds18b20.ino | 32 ++++---- sonoff/xsns_05_ds18x20.ino | 63 ++++++++------- sonoff/xsns_06_dht.ino | 11 ++- sonoff/xsns_07_sht1x.ino | 45 ++++++----- sonoff/xsns_08_htu21.ino | 152 +++++++++++++++++-------------------- 9 files changed, 163 insertions(+), 150 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 449e402b3..af78ba9a9 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 * Change SHT1x driver to provide better instant results * Fix DHT driver mixing values for different sensors (#1797) * Change DHT driver to provide better instant results and add decimals to DHT11 (#3164) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 08e909300..736e42904 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -471,6 +471,7 @@ const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":\"%d const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; +const char JSON_SNS_TEMP[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 1c1f24532..2cc9fa8e6 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -95,6 +95,8 @@ typedef unsigned long power_t; // Power (Relay) type #define LOGSZ 512 // Max number of characters in log #define MIN_MESSZ 893 // Min number of characters in MQTT message +#define SENSOR_MAX_MISS 5 // Max number of missed sensor reads before deciding it's offline + #ifdef USE_MQTT_TLS #define WEB_LOG_SIZE 2000 // Max number of characters in weblog #else diff --git a/sonoff/support.ino b/sonoff/support.ino index 3e3ea7e74..f1d260bf2 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -2080,6 +2080,12 @@ void AddLogSerial(byte loglevel) AddLogSerial(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); } +void AddLogMissed(char *sensor, uint8_t misses) +{ + snprintf_P(log_data, sizeof(log_data), PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); + AddLog(LOG_LEVEL_DEBUG); +} + /*********************************************************************************************\ * \*********************************************************************************************/ diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 505f75a76..668b21307 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -26,11 +26,10 @@ #define W1_CONVERT_TEMP 0x44 #define W1_READ_SCRATCHPAD 0xBE -#define DS18B20_MAX_MISS 5 - float ds18b20_temperature = 0; -uint8_t ds18b20_last_result = 0; +uint8_t ds18b20_valid = 0; uint8_t ds18x20_pin = 0; +char ds18b20_types[] = "DS18B20"; /*********************************************************************************************\ * Embedded stripped and tuned OneWire library @@ -136,12 +135,12 @@ void Ds18b20Convert() // delay(750); // 750ms should be enough for 12bit conv } -void Ds18b20Read() +boolean Ds18b20Read() { uint8_t data[9]; int8_t sign = 1; - if (ds18b20_last_result) { ds18b20_last_result--; } + if (ds18b20_valid) { ds18b20_valid--; } /* if (!OneWireReadBit()) { // Check end of measurement AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_BUSY)); @@ -162,11 +161,12 @@ void Ds18b20Read() sign = -1; } ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625); - ds18b20_last_result = DS18B20_MAX_MISS; - return; + ds18b20_valid = SENSOR_MAX_MISS; + return true; } } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; } /********************************************************************************************/ @@ -177,27 +177,33 @@ void Ds18b20EverySecond() if (uptime &1) { Ds18b20Convert(); // Start conversion, takes up to one second } else { - Ds18b20Read(); // Read temperature + if (!Ds18b20Read()) { // Read temperature + AddLogMissed(ds18b20_types, ds18b20_valid); + } } } void Ds18b20Show(boolean json) { - if (ds18b20_last_result) { // Check for valid temperature + if (ds18b20_valid) { // Check for valid temperature char temperature[10]; dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); if(json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"DS18B20\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, temperature); + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMP, mqtt_data, ds18b20_types, temperature); #ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_TEMP, temperature); } + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); } + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, ds18b20_temperature); + } #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "DS18B20", temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ds18b20_types, temperature, TempUnit()); #endif // USE_WEBSERVER } } diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 5a64ddc29..980bbaf4a 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -33,7 +33,6 @@ #define W1_WRITE_SCRATCHPAD 0x4E #define W1_READ_SCRATCHPAD 0xBE -#define DS18X20_MAX_MISS 5 #define DS18X20_MAX_SENSORS 8 const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; @@ -43,12 +42,12 @@ uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, struct DS18X20STRUCT { uint8_t address[8]; uint8_t index; - uint8_t result; + uint8_t valid; float temperature; } ds18x20_sensor[DS18X20_MAX_SENSORS]; uint8_t ds18x20_sensors = 0; uint8_t ds18x20_pin = 0; -char ds18x20_types[9]; +char ds18x20_types[12]; /*********************************************************************************************\ * Embedded tuned OneWire library @@ -289,7 +288,7 @@ void Ds18x20Convert() // delay(750); // 750ms should be enough for 12bit conv } -void Ds18x20Read(uint8_t sensor) +bool Ds18x20Read(uint8_t sensor) { uint8_t data[9]; int8_t sign = 1; @@ -298,7 +297,7 @@ void Ds18x20Read(uint8_t sensor) float temp9 = 0.0; uint8_t index = ds18x20_sensor[sensor].index; - if (ds18x20_sensor[index].result) { ds18x20_sensor[index].result--; } + if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } for (uint8_t retry = 0; retry < 3; retry++) { OneWireReset(); OneWireSelect(ds18x20_sensor[index].address); @@ -319,8 +318,8 @@ void Ds18x20Read(uint8_t sensor) temp9 = (data[0] >> 1) * sign; } ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - ds18x20_sensor[index].result = DS18X20_MAX_MISS; - return; + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; case DS1822_CHIPID: case DS18B20_CHIPID: if (data[4] != 0x7F) { @@ -340,17 +339,33 @@ void Ds18x20Read(uint8_t sensor) sign = -1; } ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); // Divide by 16 - ds18x20_sensor[index].result = DS18X20_MAX_MISS; - return; + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; case MAX31850_CHIPID: temp14 = (data[1] << 8) + (data[0] & 0xFC); ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); // Divide by 16 - ds18x20_sensor[index].result = DS18X20_MAX_MISS; - return; + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; } } } AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; +} + +void Ds18x20Name(uint8_t sensor) +{ + uint8_t index = sizeof(ds18x20_chipids); + while (index) { + if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { + break; + } + index--; + } + GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); + if (ds18x20_sensors > 1) { + snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s-%d"), ds18x20_types, sensor +1); + } } /********************************************************************************************/ @@ -361,7 +376,10 @@ void Ds18x20EverySecond() Ds18x20Convert(); // Start conversion, takes up to one second } else { for (uint8_t i = 0; i < ds18x20_sensors; i++) { - Ds18x20Read(i); // Read temperature + if (!Ds18x20Read(i)) { // Read temperature + Ds18x20Name(i); + AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); + } } } } @@ -369,25 +387,15 @@ void Ds18x20EverySecond() void Ds18x20Show(boolean json) { char temperature[10]; - char stemp[12]; - bool domoticz_flag = true; for (uint8_t i = 0; i < ds18x20_sensors; i++) { uint8_t index = ds18x20_sensor[i].index; - if (ds18x20_sensor[index].result) { // Check for valid temperature + if (ds18x20_sensor[index].valid) { // Check for valid temperature dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); - uint8_t idx = sizeof(ds18x20_chipids); - while (idx) { - if (ds18x20_sensor[ds18x20_sensor[idx].index].address[0] == ds18x20_chipids[idx]) { - break; - } - idx--; - } - GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), idx, kDs18x20Types); + Ds18x20Name(i); - snprintf_P(stemp, sizeof(stemp), PSTR("%s-%d"), ds18x20_types, i +1); if (json) { if (1 == ds18x20_sensors) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, temperature); @@ -396,12 +404,11 @@ void Ds18x20Show(boolean json) for (byte j = 0; j < 6; j++) { sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, stemp, address, temperature); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, address, temperature); } #ifdef USE_DOMOTICZ - if ((0 == tele_period) && domoticz_flag) { + if ((0 == tele_period) && (0 == i)) { DomoticzSensor(DZ_TEMP, temperature); - domoticz_flag = false; } #endif // USE_DOMOTICZ #ifdef USE_KNX @@ -411,7 +418,7 @@ void Ds18x20Show(boolean json) #endif // USE_KNX #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, (1 == ds18x20_sensors) ? ds18x20_types : stemp, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, ds18x20_types, temperature, TempUnit()); #endif // USE_WEBSERVER } } diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index a44abf400..ada972275 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -121,12 +121,11 @@ boolean DhtRead(byte sensor) } } - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DHT D_RECEIVED " %02X, %02X, %02X, %02X, %02X =? %02X"), - dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF); - AddLog(LOG_LEVEL_DEBUG); - - if (dht_data[4] != ((dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE)); + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %02X, %02X, %02X, %02X, %02X =? %02X"), + dht_data[0], dht_data[1], dht_data[2], dht_data[3], dht_data[4], checksum); + AddLog(LOG_LEVEL_DEBUG); return false; } diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index b285ab6fd..40a76e7a8 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -34,11 +34,10 @@ enum { SHT1X_CMD_SOFT_RESET = B00011110 }; -#define SHT_MAX_MISS 5 - uint8_t sht_sda_pin; uint8_t sht_scl_pin; uint8_t sht_type = 0; +char sht_types[] = "SHT1X"; uint8_t sht_valid = 0; float sht_temperature = 0; float sht_humidity = 0; @@ -148,7 +147,7 @@ boolean ShtRead() sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; sht_temperature = ConvertTemp(sht_temperature); - sht_valid = SHT_MAX_MISS; + sht_valid = SENSOR_MAX_MISS; return true; } @@ -173,36 +172,40 @@ void ShtDetect() void ShtEverySecond() { - if (!(uptime %3)) { ShtRead(); } // Update every 3 seconds + if (sht_type && !(uptime %3)) { // Update every 3 seconds + if (!ShtRead()) { + AddLogMissed(sht_types, sht_valid); + } + } } void ShtShow(boolean json) { - if (sht_type) { - if (sht_valid) { - char temperature[10]; - char humidity[10]; + if (sht_type && sht_valid) { + char temperature[10]; + char humidity[10]; - dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); - dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); + dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); - if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", temperature, humidity); + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, sht_types, temperature, humidity); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzTempHumSensor(temperature, humidity); + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, sht_temperature); - KnxSensor(KNX_HUMIDITY, sht_humidity); - } + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, sht_temperature); + KnxSensor(KNX_HUMIDITY, sht_humidity); + } #endif // USE_KNX #ifdef USE_WEBSERVER - } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SHT1X", temperature, TempUnit()); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "SHT1X", humidity); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sht_types, temperature, TempUnit()); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sht_types, humidity); #endif // USE_WEBSERVER - } } } } diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 3d9e21d3b..ac56b43e8 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -58,8 +58,11 @@ const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; uint8_t htu_address; uint8_t htu_type = 0; -uint8_t delay_temp; -uint8_t delay_humidity = 50; +uint8_t htu_delay_temp; +uint8_t htu_delay_humidity = 50; +uint8_t htu_valid = 0; +float htu_temperature = 0; +float htu_humidity = 0; char htu_types[7]; uint8_t HtuCheckCrc8(uint16_t data) @@ -135,87 +138,62 @@ void HtuInit() HtuSetResolution(HTU21_RES_RH12_T14); } -float HtuReadHumidity(void) +boolean HtuRead() { uint8_t checksum = 0; uint16_t sensorval = 0; - float humidity = 0.0; - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READHUM); - if (Wire.endTransmission() != 0) { - return 0.0; // In case of error - } - delay(delay_humidity); // Sensor time at max resolution - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 <= Wire.available()) { - sensorval = Wire.read() << 8; // MSB - sensorval |= Wire.read(); // LSB - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { - return 0.0; // Checksum mismatch - } - - sensorval ^= 0x02; // clear status bits - humidity = 0.001907 * (float)sensorval - 6; - - if (humidity > 100) { - return 100.0; - } - if (humidity < 0) { - return 0.01; - } - - return humidity; -} - -float HtuReadTemperature() -{ - uint8_t checksum=0; - uint16_t sensorval=0; - float t; + if (htu_valid) { htu_valid--; } Wire.beginTransmission(HTU21_ADDR); Wire.write(HTU21_READTEMP); - if (Wire.endTransmission() != 0) { - return 0.0; // In case of error - } - delay(delay_temp); // Sensor time at max resolution + if (Wire.endTransmission() != 0) { return false; } // In case of error + delay(htu_delay_temp); // Sensor time at max resolution Wire.requestFrom(HTU21_ADDR, 3); if (3 == Wire.available()) { - sensorval = Wire.read() << 8; // MSB - sensorval |= Wire.read(); // LSB + sensorval = Wire.read() << 8; // MSB + sensorval |= Wire.read(); // LSB checksum = Wire.read(); } - if (HtuCheckCrc8(sensorval) != checksum) { - return 0.0; // Checksum mismatch + if (HtuCheckCrc8(sensorval) != checksum) { return false; } // Checksum mismatch + + htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READHUM); + if (Wire.endTransmission() != 0) { return false; } // In case of error + delay(htu_delay_humidity); // Sensor time at max resolution + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 <= Wire.available()) { + sensorval = Wire.read() << 8; // MSB + sensorval |= Wire.read(); // LSB + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } // Checksum mismatch + + sensorval ^= 0x02; // clear status bits + htu_humidity = 0.001907 * (float)sensorval - 6; + if (htu_humidity > 100) { htu_humidity = 100.0; } + if (htu_humidity < 0) { htu_humidity = 0.01; } + + if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { + htu_humidity = 0.0; + } + if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { + htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; } - t = ConvertTemp(0.002681 * (float)sensorval - 46.85); - return t; -} - -float HtuCompensatedHumidity(float humidity, float temperature) -{ - if(humidity == 0.00 && temperature == 0.00) { - return 0.0; - } - if(temperature > 0.00 && temperature < 80.00) { - return (-0.15)*(25-temperature)+humidity; - } - return humidity; + htu_valid = SENSOR_MAX_MISS; + return true; } /********************************************************************************************/ void HtuDetect() { - if (htu_type) { - return; - } + if (htu_type) { return; } htu_address = HTU21_ADDR; htu_type = HtuReadDeviceId(); @@ -224,8 +202,8 @@ void HtuDetect() HtuInit(); switch (htu_type) { case HTU21_CHIPID: - delay_temp = 50; - delay_humidity = 16; + htu_delay_temp = 50; + htu_delay_humidity = 16; break; case SI7021_CHIPID: index++; // 3 @@ -233,13 +211,13 @@ void HtuDetect() index++; // 2 case SI7013_CHIPID: index++; // 1 - delay_temp = 12; - delay_humidity = 23; + htu_delay_temp = 12; + htu_delay_humidity = 23; break; default: index = 4; - delay_temp = 50; - delay_humidity = 23; + htu_delay_temp = 50; + htu_delay_humidity = 23; } GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, htu_types, htu_address); @@ -247,31 +225,41 @@ void HtuDetect() } } +void HtuEverySecond() +{ + if (uptime &1) { + HtuDetect(); + } else { + if (htu_type) { + if (!HtuRead()) { + AddLogMissed(htu_types, htu_valid); + } + } + } +} + void HtuShow(boolean json) { - if (htu_type) { + if (htu_type && htu_valid) { char temperature[10]; char humidity[10]; - float t = HtuReadTemperature(); - float h = HtuReadHumidity(); - h = HtuCompensatedHumidity(h, t); - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, temperature, humidity); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzTempHumSensor(temperature, humidity); + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } #endif // USE_DOMOTICZ - #ifdef USE_KNX if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); + KnxSensor(KNX_TEMPERATURE, htu_temperature); + KnxSensor(KNX_HUMIDITY, htu_humidity); } #endif // USE_KNX - #ifdef USE_WEBSERVER } else { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, htu_types, temperature, TempUnit()); @@ -293,8 +281,8 @@ boolean Xsns08(byte function) if (i2c_flg) { switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: - HtuDetect(); + case FUNC_EVERY_SECOND: + HtuEverySecond(); break; case FUNC_JSON_APPEND: HtuShow(1); From 50ce01cd0b99594eeb7ed6787e3e3c0e5353e615 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Wed, 11 Jul 2018 14:21:11 +0200 Subject: [PATCH 09/14] Update sensor drivers Update sensor drivers to provide instant results --- sonoff/_releasenotes.ino | 1 + sonoff/xsns_08_htu21.ino | 8 +- sonoff/xsns_09_bmp.ino | 204 ++++++++++++++++---------------------- sonoff/xsns_interface.ino | 32 ++++++ 4 files changed, 126 insertions(+), 119 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index af78ba9a9..78ff3a3b5 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Update sensor drivers to provide instant results * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 * Change SHT1x driver to provide better instant results * Fix DHT driver mixing values for different sensors (#1797) diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index ac56b43e8..ecb127dc6 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -227,9 +227,10 @@ void HtuDetect() void HtuEverySecond() { - if (uptime &1) { + if (92 == (uptime %100)) { HtuDetect(); - } else { + } + else if (uptime &1) { if (htu_type) { if (!HtuRead()) { AddLogMissed(htu_types, htu_valid); @@ -281,6 +282,9 @@ boolean Xsns08(byte function) if (i2c_flg) { switch (function) { + case FUNC_INIT: + HtuDetect(); + break; case FUNC_EVERY_SECOND: HtuEverySecond(); break; diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index a3769f8bc..4aac0537e 100644 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -45,6 +45,11 @@ uint8_t bmp_type = 0; uint8_t bmp_model = 0; char bmp_name[7]; +uint8_t bmp_valid = 0; +float bmp_temperature = 0.0; +float bmp_pressure = 0.0; +float bmp_humidity = 0.0; + /*********************************************************************************************\ * BMP085 and BME180 \*********************************************************************************************/ @@ -113,21 +118,15 @@ boolean Bmp180Calibration() return true; } -double Bmp180ReadTemperature() +void Bmp180Read() { I2cWrite8(bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); delay(5); // 5ms conversion time int ut = I2cRead16(bmp_address, BMP180_REG_RESULT); - int32_t x1 = (ut - (int32_t)cal_ac6) * ((int32_t)cal_ac5) >> 15; - int32_t x2 = ((int32_t)cal_mc << 11) / (x1 + (int32_t)cal_md); - bmp180_b5 = x1 + x2; - - return ((bmp180_b5 + 8) >> 4) / 10.0; -} - -double Bmp180ReadPressure() -{ - int32_t p; + int32_t xt1 = (ut - (int32_t)cal_ac6) * ((int32_t)cal_ac5) >> 15; + int32_t xt2 = ((int32_t)cal_mc << 11) / (xt1 + (int32_t)cal_md); + bmp180_b5 = xt1 + xt2; + bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; I2cWrite8(bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); // Highest resolution delay(2 + (4 << BMP180_OSS)); // 26ms conversion time at ultra high resolution @@ -146,19 +145,18 @@ double Bmp180ReadPressure() uint32_t b4 = ((uint32_t)cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); + int32_t p; if (b7 < 0x80000000) { p = (b7 * 2) / b4; } else { p = (b7 / b4) * 2; } - x1 = (p >> 8) * (p >> 8); x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; - p += ((x1 + x2 + (int32_t)3791) >> 4); - return p / 100.0; // convert to mbar + bmp_pressure = p / 100.0; // convert to mbar } /*********************************************************************************************\ @@ -215,8 +213,6 @@ struct BME280CALIBDATA int8_t dig_H6; } Bme280CalibrationData; -int32_t t_fine; - boolean Bmx280Calibrate() { // if (I2cRead8(bmp_address, BMP_REGISTER_CHIPID) != BME280_CHIPID) return false; @@ -267,62 +263,43 @@ boolean Bmx280Calibrate() return true; } -double Bme280ReadTemperature(void) +void Bme280Read(void) { - int32_t var1; - int32_t var2; - int32_t adc_T = I2cRead24(bmp_address, BME280_REGISTER_TEMPDATA); adc_T >>= 4; - var1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData.dig_T1 << 1))) * ((int32_t)Bme280CalibrationData.dig_T2)) >> 11; - var2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1))) >> 12) * + int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData.dig_T1 << 1))) * ((int32_t)Bme280CalibrationData.dig_T2)) >> 11; + int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1))) >> 12) * ((int32_t)Bme280CalibrationData.dig_T3)) >> 14; - t_fine = var1 + var2; + int32_t t_fine = vart1 + vart2; double T = (t_fine * 5 + 128) >> 8; - return T / 100.0; -} - -double Bme280ReadPressure(void) -{ - int64_t var1; - int64_t var2; - int64_t p; - - // Must be done first to get the t_fine variable set up - // Bme280ReadTemperature(); + bmp_temperature = T / 100.0; int32_t adc_P = I2cRead24(bmp_address, BME280_REGISTER_PRESSUREDATA); adc_P >>= 4; - var1 = ((int64_t)t_fine) - 128000; - var2 = var1 * var1 * (int64_t)Bme280CalibrationData.dig_P6; + int64_t var1 = ((int64_t)t_fine) - 128000; + int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData.dig_P6; var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData.dig_P5) << 17); var2 = var2 + (((int64_t)Bme280CalibrationData.dig_P4) << 35); var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData.dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData.dig_P2) << 12); var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData.dig_P1) >> 33; if (0 == var1) { - return 0; // avoid exception caused by division by zero + return; // avoid exception caused by division by zero } - p = 1048576 - adc_P; + int64_t p = 1048576 - adc_P; p = (((p << 31) - var2) * 3125) / var1; var1 = (((int64_t)Bme280CalibrationData.dig_P9) * (p >> 13) * (p >> 13)) >> 25; var2 = (((int64_t)Bme280CalibrationData.dig_P8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData.dig_P7) << 4); - return (double)p / 25600.0; -} + bmp_pressure = (float)p / 25600.0; + + if (BMP280_CHIPID == bmp_type) { return; } -double Bme280ReadHumidity(void) -{ int32_t v_x1_u32r; - // Must be done first to get the t_fine variable set up - // Bme280ReadTemperature(); - int32_t adc_H = I2cRead16(bmp_address, BME280_REGISTER_HUMIDDATA); - v_x1_u32r = (t_fine - ((int32_t)76800)); - v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData.dig_H4) << 20) - (((int32_t)Bme280CalibrationData.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData.dig_H6)) >> 10) * @@ -332,8 +309,8 @@ double Bme280ReadHumidity(void) ((int32_t)Bme280CalibrationData.dig_H1)) >> 4)); v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; - double h = (v_x1_u32r >> 12); - return h / 1024.0; + float h = (v_x1_u32r >> 12); + bmp_humidity = h / 1024.0; } #ifdef USE_BME680 @@ -345,17 +322,14 @@ double Bme280ReadHumidity(void) struct bme680_dev gas_sensor; +float bmp_gas_resistance = 0.0; +uint8_t bme680_state = 0; + static void BmeDelayMs(uint32_t ms) { delay(ms); } -uint8_t bme680_state = 0; -float bme680_temperature; -float bme680_pressure; -float bme680_humidity; -float bme680_gas_resistance; - boolean Bme680Init() { gas_sensor.dev_id = bmp_address; @@ -400,7 +374,7 @@ boolean Bme680Init() return true; } -void Bme680PerformReading() +void Bme680Read() { int8_t rslt = BME680_OK; @@ -424,14 +398,14 @@ void Bme680PerformReading() rslt = bme680_get_sensor_data(&data, &gas_sensor); if (rslt != BME680_OK) { return; } - bme680_temperature = data.temperature / 100.0; - bme680_humidity = data.humidity / 1000.0; - bme680_pressure = data.pressure; + bmp_temperature = data.temperature / 100.0; + bmp_humidity = data.humidity / 1000.0; + bmp_pressure = data.pressure / 100.0; /* Avoid using measurements from an unstable heating setup */ if (data.status & BME680_GASM_VALID_MSK) { - bme680_gas_resistance = data.gas_resistance; + bmp_gas_resistance = data.gas_resistance / 1000.0; } else { - bme680_gas_resistance = 0; + bmp_gas_resistance = 0; } } } @@ -444,9 +418,7 @@ void Bme680PerformReading() void BmpDetect() { - if (bmp_type) { - return; - } + if (bmp_type) { return; } for (byte i = 0; i < sizeof(bmp_addresses); i++) { bmp_address = bmp_addresses[i]; @@ -456,22 +428,21 @@ void BmpDetect() } } if (bmp_type) { + bmp_model = 0; boolean success = false; switch (bmp_type) { case BMP180_CHIPID: success = Bmp180Calibration(); break; - case BMP280_CHIPID: - bmp_model = 1; // 1 - success = Bmx280Calibrate(); - break; case BME280_CHIPID: - bmp_model = 2; // 2 + bmp_model++; // 2 + case BMP280_CHIPID: + bmp_model++; // 1 success = Bmx280Calibrate(); break; #ifdef USE_BME680 case BME680_CHIPID: - bmp_model = 3; // 2 + bmp_model = 3; // 3 success = Bme680Init(); break; #endif // USE_BME680 @@ -487,54 +458,55 @@ void BmpDetect() } } +void BmpRead() +{ + switch (bmp_type) { + case BMP180_CHIPID: + Bmp180Read(); + break; + case BMP280_CHIPID: + case BME280_CHIPID: + Bme280Read(); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + Bme680Read(); + break; +#endif // USE_BME680 + } + if (bmp_temperature != 0.0) { bmp_temperature = ConvertTemp(bmp_temperature); } +} + +void BmpEverySecond() +{ + if (91 == (uptime %100)) { + BmpDetect(); + } + else if (uptime &1) { + BmpRead(); + } +} + void BmpShow(boolean json) { if (bmp_type) { - float t = 0.0; - float p = 0.0; - float h = 0.0; - float g = 0.0; float bmp_sealevel = 0.0; - - switch (bmp_type) { - case BMP180_CHIPID: - t = Bmp180ReadTemperature(); - p = Bmp180ReadPressure(); - break; - case BME280_CHIPID: - h = Bme280ReadHumidity(); - case BMP280_CHIPID: - t = Bme280ReadTemperature(); - p = Bme280ReadPressure(); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - t = bme680_temperature; - p = bme680_pressure / 100.0; - h = bme680_humidity; - g = bme680_gas_resistance / 1000.0; - break; -#endif // USE_BME680 - } - if (t != 0.0) { - t = ConvertTemp(t); - } - if (p != 0.0) { -// bmp_sealevel = p / pow(1.0 - ((float)Settings.altitude / 44330.0), 5.255); // pow adds 8k to the code - bmp_sealevel = (p / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - } - char temperature[10]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); char pressure[10]; - dtostrfd(p, Settings.flag2.pressure_resolution, pressure); char sea_pressure[10]; - dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); char humidity[10]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + + if (bmp_pressure != 0.0) { + bmp_sealevel = (bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; + } + + dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); + dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); + dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); + dtostrfd(bmp_humidity, Settings.flag2.humidity_resolution, humidity); #ifdef USE_BME680 char gas_resistance[10]; - dtostrfd(g, 2, gas_resistance); + dtostrfd(bmp_gas_resistance, 2, gas_resistance); #endif // USE_BME680 if (json) { @@ -555,15 +527,15 @@ void BmpShow(boolean json) if (0 == tele_period) { DomoticzTempHumPressureSensor(temperature, humidity, pressure); #ifdef USE_BME680 - if (bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)g); } + if (bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_gas_resistance); } #endif // USE_BME680 } #endif // USE_DOMOTICZ #ifdef USE_KNX if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); + KnxSensor(KNX_TEMPERATURE, bmp_temperature); + KnxSensor(KNX_HUMIDITY, bmp_humidity); } #endif // USE_KNX @@ -599,13 +571,11 @@ boolean Xsns09(byte function) if (i2c_flg) { switch (function) { + case FUNC_INIT: + BmpDetect(); + break; case FUNC_EVERY_SECOND: - if (tele_period == Settings.tele_period -2) { // Allow 2 seconds to prepare BME680 readings - BmpDetect(); - } -#ifdef USE_BME680 - Bme680PerformReading(); -#endif // USE_BME680 + BmpEverySecond(); break; case FUNC_JSON_APPEND: BmpShow(1); diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 19cd86bb3..e845b628f 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -146,6 +146,38 @@ boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers &Xsns32, #endif +#ifdef XSNS_33 + &Xsns33, +#endif + +#ifdef XSNS_34 + &Xsns34, +#endif + +#ifdef XSNS_35 + &Xsns35, +#endif + +#ifdef XSNS_36 + &Xsns36, +#endif + +#ifdef XSNS_37 + &Xsns37, +#endif + +#ifdef XSNS_38 + &Xsns38, +#endif + +#ifdef XSNS_39 + &Xsns39, +#endif + +#ifdef XSNS_40 + &Xsns40, +#endif + // Optional user defined sensors in range 91 - 99 #ifdef XSNS_91 From 4bc3ce70dda169df622248ec2d8a4c3782dd3501 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Wed, 11 Jul 2018 14:39:07 +0200 Subject: [PATCH 10/14] Updated bmp driver Updated bmp driver --- sonoff/xsns_09_bmp.ino | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 4aac0537e..f532ec5a2 100644 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -83,7 +83,6 @@ int16_t cal_md; uint16_t cal_ac4; uint16_t cal_ac5; uint16_t cal_ac6; -int32_t bmp180_b5 = 0; boolean Bmp180Calibration() { @@ -125,7 +124,7 @@ void Bmp180Read() int ut = I2cRead16(bmp_address, BMP180_REG_RESULT); int32_t xt1 = (ut - (int32_t)cal_ac6) * ((int32_t)cal_ac5) >> 15; int32_t xt2 = ((int32_t)cal_mc << 11) / (xt1 + (int32_t)cal_md); - bmp180_b5 = xt1 + xt2; + int32_t bmp180_b5 = xt1 + xt2; bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; I2cWrite8(bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); // Highest resolution @@ -156,7 +155,7 @@ void Bmp180Read() x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; p += ((x1 + x2 + (int32_t)3791) >> 4); - bmp_pressure = p / 100.0; // convert to mbar + bmp_pressure = (float)p / 100.0; // convert to mbar } /*********************************************************************************************\ @@ -229,20 +228,6 @@ boolean Bmx280Calibrate() Bme280CalibrationData.dig_P7 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P7); Bme280CalibrationData.dig_P8 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P8); Bme280CalibrationData.dig_P9 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_P9); -/* - if (BME280_CHIPID == bmp_type) { - Bme280CalibrationData.dig_H1 = I2cRead8(bmp_address, BME280_REGISTER_DIG_H1); - Bme280CalibrationData.dig_H2 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_H2); - Bme280CalibrationData.dig_H3 = I2cRead8(bmp_address, BME280_REGISTER_DIG_H3); - Bme280CalibrationData.dig_H4 = (I2cRead8(bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); - Bme280CalibrationData.dig_H5 = (I2cRead8(bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_address, BME280_REGISTER_DIG_H5) >> 4); - Bme280CalibrationData.dig_H6 = (int8_t)I2cRead8(bmp_address, BME280_REGISTER_DIG_H6); - - // Set before CONTROL_meas (DS 5.4.3) - I2cWrite8(bmp_address, BME280_REGISTER_CONTROLHUMID, 0x05); // 16x oversampling (Adafruit) - } - I2cWrite8(bmp_address, BME280_REGISTER_CONTROL, 0xB7); // 16x oversampling, normal mode (Adafruit) -*/ if (BME280_CHIPID == bmp_type) { // #1051 Bme280CalibrationData.dig_H1 = I2cRead8(bmp_address, BME280_REGISTER_DIG_H1); Bme280CalibrationData.dig_H2 = I2cReadS16_LE(bmp_address, BME280_REGISTER_DIG_H2); @@ -272,7 +257,7 @@ void Bme280Read(void) int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData.dig_T1))) >> 12) * ((int32_t)Bme280CalibrationData.dig_T3)) >> 14; int32_t t_fine = vart1 + vart2; - double T = (t_fine * 5 + 128) >> 8; + float T = (t_fine * 5 + 128) >> 8; bmp_temperature = T / 100.0; int32_t adc_P = I2cRead24(bmp_address, BME280_REGISTER_PRESSUREDATA); @@ -296,10 +281,9 @@ void Bme280Read(void) if (BMP280_CHIPID == bmp_type) { return; } - int32_t v_x1_u32r; - int32_t adc_H = I2cRead16(bmp_address, BME280_REGISTER_HUMIDDATA); - v_x1_u32r = (t_fine - ((int32_t)76800)); + + int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData.dig_H4) << 20) - (((int32_t)Bme280CalibrationData.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData.dig_H6)) >> 10) * From 29ed5c1a27cfe1dd8e3a3134eb6865f8426d6031 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Wed, 11 Jul 2018 15:35:12 +0200 Subject: [PATCH 11/14] Update sensor drivers Update sensor drivers --- sonoff/xsns_07_sht1x.ino | 3 ++- sonoff/xsns_08_htu21.ino | 3 ++- sonoff/xsns_10_bh1750.ino | 50 +++++++++++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 40a76e7a8..2c0099c9b 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -175,13 +175,14 @@ void ShtEverySecond() if (sht_type && !(uptime %3)) { // Update every 3 seconds if (!ShtRead()) { AddLogMissed(sht_types, sht_valid); +// if (!sht_valid) { sht_type = 0; } } } } void ShtShow(boolean json) { - if (sht_type && sht_valid) { + if (sht_valid) { char temperature[10]; char humidity[10]; diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index ecb127dc6..0f3cfc735 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -234,6 +234,7 @@ void HtuEverySecond() if (htu_type) { if (!HtuRead()) { AddLogMissed(htu_types, htu_valid); +// if (!htu_valid) { htu_type = 0; } } } } @@ -241,7 +242,7 @@ void HtuEverySecond() void HtuShow(boolean json) { - if (htu_type && htu_valid) { + if (htu_valid) { char temperature[10]; char humidity[10]; diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index 9c02f02e0..aa2cee37d 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -33,14 +33,20 @@ uint8_t bh1750_address; uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; uint8_t bh1750_type = 0; +uint8_t bh1750_valid = 0; +uint16_t bh1750_illuminance = 0; +char bh1750_types[] = "BH1750"; -uint16_t Bh1750ReadLux() +bool Bh1750Read() { - Wire.requestFrom(bh1750_address, (uint8_t)2); + if (bh1750_valid) { bh1750_valid--; } + + if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } byte msb = Wire.read(); byte lsb = Wire.read(); - uint16_t value = ((msb << 8) | lsb) / 1.2; - return value; + bh1750_illuminance = ((msb << 8) | lsb) / 1.2; + bh1750_valid = SENSOR_MAX_MISS; + return true; } /********************************************************************************************/ @@ -57,31 +63,46 @@ void Bh1750Detect() Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); if (!Wire.endTransmission()) { bh1750_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "BH1750", bh1750_address); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address); AddLog(LOG_LEVEL_DEBUG); break; } } } +void Bh1750EverySecond() +{ + if (90 == (uptime %100)) { + Bh1750Detect(); + } + else if (uptime &1) { + if (bh1750_type) { + if (!Bh1750Read()) { + AddLogMissed(bh1750_types, bh1750_valid); +// if (!bh1750_valid) { bh1750_type = 0; } + } + } + } +} + #ifdef USE_WEBSERVER const char HTTP_SNS_ILLUMINANCE[] PROGMEM = - "%s{s}BH1750 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = + "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = #endif // USE_WEBSERVER void Bh1750Show(boolean json) { - if (bh1750_type) { - uint16_t illuminance = Bh1750ReadLux(); - + if (bh1750_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"BH1750\":{\"" D_JSON_ILLUMINANCE "\":%d}"), mqtt_data, illuminance); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"), mqtt_data, bh1750_types, bh1750_illuminance); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, illuminance); + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); + } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, illuminance); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, bh1750_types, bh1750_illuminance); #endif // USE_WEBSERVER } } @@ -99,9 +120,12 @@ boolean Xsns10(byte function) if (i2c_flg) { switch (function) { - case FUNC_PREP_BEFORE_TELEPERIOD: + case FUNC_INIT: Bh1750Detect(); break; + case FUNC_EVERY_SECOND: + Bh1750EverySecond(); + break; case FUNC_JSON_APPEND: Bh1750Show(1); break; From a489b4a44a43e268b05b9547892f24bb28bb0c2a Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 12 Jul 2018 12:19:08 +0200 Subject: [PATCH 12/14] Add profile info to drivers Update release notes and add profile info to some drivers --- sonoff/_releasenotes.ino | 72 ++++++++++++++------------------------ sonoff/xsns_05_ds18b20.ino | 2 ++ sonoff/xsns_05_ds18x20.ino | 10 ++++++ sonoff/xsns_06_dht.ino | 2 ++ sonoff/xsns_07_sht1x.ino | 3 +- sonoff/xsns_08_htu21.ino | 2 ++ sonoff/xsns_09_bmp.ino | 4 ++- sonoff/xsns_10_bh1750.ino | 4 ++- sonoff/xsns_13_ina219.ino | 59 ++++++++++++++++++++++++------- sonoff/xsns_interface.ino | 30 ++++++++++++++++ 10 files changed, 126 insertions(+), 62 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 78ff3a3b5..481b0a7da 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -24,16 +24,42 @@ * Fix KNX bug when doing reply of sensors values * Fix rules induced LWT message * Fix possible wifi connection problem (#1366) + * Fix some Pow R2 and S31 checksum errors (#1907) + * Fix display selection of un-available GPIO options in Module Configuration webpage (#2718) + * Fix timer re-trigger within one minute after restart (#2744) + * Fix IRSend not accepting data value of 0 by David Conran (#2751) + * Fix vars on rules by Adrian Scillato (#2769) + * Fix bug in KNX menu by Adrian Scillato (#2770) + * Fix anomalies in rules (#2778) + * Fix HUE bridge V1 software version by Heiko Krupp (#2788) + * Fix Hardware Watchdog restart when using event command (#2853) * Add Ukrainian language file * Add KNX support for DS18S20 Temperature sensor * Add CRC to Settings making future upgrades more fail-safe + * Add feature information to Status 4 + * Add tools folder with python script decode-status.py for decoding some status fields like SetOption and Features + * Add Slots on the KNX Web Menu to select Group Addess to receive data to trigger rules + * Add two rule sets of 511 characters using commands rule1, rule2 and rule3 + * Add Console Commands to send KNX Commands and KNX Values + * Add Slots on the KNX Web Menu to select Group Addess to send data from console commands + * Add Events to trigger rules when a command or read requests is received from KNX * Add command SetOption30 to enforce Hass discovery as light group (#1784) * Add support for BlitzWolf BW-SHP2 (and Homecube, Gosund SP1) Energy Monitoring Smart Socket (#2223) * Add time in minutes to rule Time#Initialized, Time#set and Time#Minute (#2669) + * Add Eastron SDM630 energy meter by Gennaro Tortone (#2735) + * Add KNX communication enhancement by Adrian Scillato (#2742) + * Add KNX energy data by Adrian Scillato (#2750) + * Add rule support for IrReceive and RfReceive (#2758) + * Add python script fw-server.py in tools folder to create a simple OTA server by Gennaro Tortone (#2759) * Add rule variables %time% for minutes since midnight, %uptime%, %sunrise% and %sunset% giving time in minutes (#2669) + * Add rules %mem1% to %mem5% variable names storing data in flash (#2780) + * Add rules test on %varx% or %memx% (#2780) + * Add optional token %id% substituting the unique MAC address to fulltopic by Michael Graf (#2794) * Add support for Sonoff S26 Smart Socket (#2808) + * Add command WebSend [(:,:)] (#2821) * Add increment and decrement value to command Counter (#2838) * Add support for Sonoff iFan02 as module 44 introducing command FanSpeed 0..3 (#2839) + * Add source information to command execution to be shown with logging option 3 (#2843) * Add support for uploading Sonoff Bridge firmware found in tools/fw_efm8bb1 folder build by Portisch using Web Gui File Upload (#2886) * Add command RfRaw to control Portisch firmware features * Add support for I2C temperature sensor LM75AD (#2909) @@ -44,52 +70,6 @@ * Add decimal values support for commands ADD, SUB, MULT and SCALE (#3083, #3089) * Add support for bitflags SetOption50 .. SetOption81 (#3118) * - * 5.14.0b - * Add Console Commands to send KNX Commands - usage: KnxTx_Cmnd[slot] command - where [slot] is any of the 5 slots on the KNX Menu and command is 0 or 1 - example: KnxTx_Cmnd1 0 - * Add Console Commands to send KNX Values - usage: KnxTx_Val[slot] value - where [slot] is any of the 5 slots on the KNX Menu and value is a number - example: KnxTx_Val1 35 - * Add Slots on the KNX Web Menu to select Group Addess to send data from console commands - * Add Events to trigger rules when a command is received from KNX - usage on rules as: event#KnxRx_Cmnd[slot] - where [slot] is any of the 5 slots on the KNX Menu - example: rule on event#KnxRx_Cmnd1 do VAR1 %value% endon - (where %value% can be 0 or 1) - * Add Events to trigger rules when received read requests from KNX - usage on rules as: event#KnxRx_Req[slot] - where [slot] is any of the 5 slots on the KNX Menu - example: rule on event#KnxRx_Req1 do KnxTx_Val1 35 endon - * Add Slots on the KNX Web Menu to select Group Addess to receive data to trigger rules - * Add two rule sets of 511 characters using commands rule1, rule2 and rule3 - * Add Ukranian language file - * Add rule support for IrReceive and RfReceive (#2758) - * Add command WebSend [(:,:)] (#2821) - * Add source information to command execution to be shown with logging option 3 (#2843) - * Fix some Pow R2 and S31 checksum errors (#1907) - * Fix Hardware Watchdog restart when using event command (#2853) - * - * 5.14.0a - * Add feature information to Status 4 - * Add tools folder with python script decode-status.py for decoding some status fields like SetOption and Features - * Add Eastron SDM630 energy meter by Gennaro Tortone (#2735) - * Add KNX communication enhancement by Adrian Scillato (#2742) - * Add KNX energy data by Adrian Scillato (#2750) - * Add python script fw-server.py in tools folder to create a simple OTA server by Gennaro Tortone (#2759) - * Add rules %mem1% to %mem5% variable names storing data in flash (#2780) - * Add rules test on %varx% or %memx% (#2780) - * Add optional token %id% substituting the unique MAC address to fulltopic by Michael Graf (#2794) - * Fix display selection of un-available GPIO options in Module Configuration webpage (#2718) - * Fix timer re-trigger within one minute after restart (#2744) - * Fix IRSend not accepting data value of 0 by David Conran (#2751) - * Fix vars on rules by Adrian Scillato (#2769) - * Fix bug in KNX menu by Adrian Scillato (#2770) - * Fix anomalies in rules (#2778) - * Fix HUE bridge V1 software version by Heiko Krupp (#2788) - * * 5.14.0 20180515 * Update language files * Update TasmotaSerial to 2.0.0 allowing Hardware Serial Fallback when correct connections are configured diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 668b21307..fa0f4fee8 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -175,8 +175,10 @@ void Ds18b20EverySecond() { ds18x20_pin = pin[GPIO_DSB]; if (uptime &1) { + // 2mS Ds18b20Convert(); // Start conversion, takes up to one second } else { + // 12mS if (!Ds18b20Read()) { // Read temperature AddLogMissed(ds18b20_types, ds18b20_valid); } diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index 980bbaf4a..869deac8e 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -21,6 +21,7 @@ /*********************************************************************************************\ * DS18B20 - Temperature - Multiple sensors \*********************************************************************************************/ +//#define USE_DS18x20_RECONFIGURE // When sensor is lost keep retrying or re-configure #define DS18S20_CHIPID 0x10 // +/-0.5C 9-bit #define DS1822_CHIPID 0x22 // +/-2C 12-bit @@ -251,6 +252,7 @@ void Ds18x20Init() uint64_t ids[DS18X20_MAX_SENSORS]; ds18x20_pin = pin[GPIO_DSB]; + OneWireResetSearch(); for (ds18x20_sensors = 0; ds18x20_sensors < DS18X20_MAX_SENSORS; ds18x20_sensors) { if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { @@ -373,12 +375,20 @@ void Ds18x20Name(uint8_t sensor) void Ds18x20EverySecond() { if (uptime &1) { + // 2mS Ds18x20Convert(); // Start conversion, takes up to one second } else { for (uint8_t i = 0; i < ds18x20_sensors; i++) { + // 12mS per device if (!Ds18x20Read(i)) { // Read temperature Ds18x20Name(i); AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); +#ifdef USE_DS18x20_RECONFIGURE + if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { + memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); + Ds18x20Init(); // Re-configure + } +#endif // USE_DS18x20_RECONFIGURE } } } diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index ada972275..048337d25 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -193,9 +193,11 @@ void DhtInit() void DhtEverySecond() { if (uptime &1) { + // <1mS DhtReadPrep(); } else { for (byte i = 0; i < dht_sensors; i++) { + // DHT11 and AM2301 25mS per sensor, SI7021 5mS per sensor DhtReadTempHum(i); } } diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 2c0099c9b..510ee7be3 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -172,7 +172,8 @@ void ShtDetect() void ShtEverySecond() { - if (sht_type && !(uptime %3)) { // Update every 3 seconds + if (sht_type && !(uptime %4)) { // Update every 4 seconds + // 344mS if (!ShtRead()) { AddLogMissed(sht_types, sht_valid); // if (!sht_valid) { sht_type = 0; } diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 0f3cfc735..9534cbbce 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -228,9 +228,11 @@ void HtuDetect() void HtuEverySecond() { if (92 == (uptime %100)) { + // 1mS HtuDetect(); } else if (uptime &1) { + // HTU21: 68mS, SI70xx: 37mS if (htu_type) { if (!HtuRead()) { AddLogMissed(htu_types, htu_valid); diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index f532ec5a2..2ffe02ebe 100644 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -464,9 +464,11 @@ void BmpRead() void BmpEverySecond() { if (91 == (uptime %100)) { + // 1mS BmpDetect(); } - else if (uptime &1) { + else { + // 2mS BmpRead(); } } diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index aa2cee37d..1dd18d90a 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -73,9 +73,11 @@ void Bh1750Detect() void Bh1750EverySecond() { if (90 == (uptime %100)) { + // 1mS Bh1750Detect(); } - else if (uptime &1) { + else { + // 1mS if (bh1750_type) { if (!Bh1750Read()) { AddLogMissed(bh1750_types, bh1750_valid); diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 50bcb1642..deb4d5f4f 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -93,6 +93,11 @@ uint32_t ina219_cal_value = 0; // The following multiplier is used to convert raw current values to mA, taking into account the current config settings uint32_t ina219_current_divider_ma = 0; +uint8_t ina219_valid = 0; +float ina219_voltage = 0; +float ina219_current = 0; +char ina219_types[] = "INA219"; + bool Ina219SetCalibration(uint8_t mode) { uint16_t config = 0; @@ -155,8 +160,20 @@ float Ina219GetCurrent_mA() return value; } +bool Ina219Read() +{ + ina219_voltage = Ina219GetBusVoltage_V() + (Ina219GetShuntVoltage_mV() / 1000); + ina219_current = Ina219GetCurrent_mA() / 1000; + ina219_valid = SENSOR_MAX_MISS; + return true; +} + /*********************************************************************************************\ * Command Sensor13 + * + * 0 - Max 32V 2A range + * 1 - Max 32V 1A range + * 2 - Max 16V 0.4A range \*********************************************************************************************/ bool Ina219CommandSensor() @@ -176,21 +193,36 @@ bool Ina219CommandSensor() void Ina219Detect() { - if (ina219_type) { - return; - } + if (ina219_type) { return; } for (byte i = 0; i < sizeof(ina219_addresses); i++) { ina219_address = ina219_addresses[i]; if (Ina219SetCalibration(Settings.ina219_mode)) { ina219_type = 1; - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "INA219", ina219_address); + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, ina219_types, ina219_address); AddLog(LOG_LEVEL_DEBUG); break; } } } +void Ina219EverySecond() +{ + if (87 == (uptime %100)) { + // 2mS + Ina219Detect(); + } + else { + // 3mS + if (ina219_type) { + if (!Ina219Read()) { + AddLogMissed(ina219_types, ina219_valid); +// if (!ina219_valid) { ina219_type = 0; } + } + } + } +} + #ifdef USE_WEBSERVER const char HTTP_SNS_INA219_DATA[] PROGMEM = "%s" "{s}INA219 " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" @@ -200,21 +232,19 @@ const char HTTP_SNS_INA219_DATA[] PROGMEM = "%s" void Ina219Show(boolean json) { - if (ina219_type) { + if (ina219_valid) { char voltage[10]; char current[10]; char power[10]; - float fvoltage = Ina219GetBusVoltage_V() + (Ina219GetShuntVoltage_mV() / 1000); - float fcurrent = Ina219GetCurrent_mA() / 1000; - float fpower = fvoltage * fcurrent; - dtostrfd(fvoltage, Settings.flag2.voltage_resolution, voltage); + float fpower = ina219_voltage * ina219_current; + dtostrfd(ina219_voltage, Settings.flag2.voltage_resolution, voltage); dtostrfd(fpower, Settings.flag2.wattage_resolution, power); - dtostrfd(fcurrent, Settings.flag2.current_resolution, current); + dtostrfd(ina219_current, Settings.flag2.current_resolution, current); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"INA219\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - mqtt_data, voltage, current, power); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + mqtt_data, ina219_types, voltage, current, power); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); @@ -244,9 +274,12 @@ boolean Xsns13(byte function) result = Ina219CommandSensor(); } break; - case FUNC_PREP_BEFORE_TELEPERIOD: + case FUNC_INIT: Ina219Detect(); break; + case FUNC_EVERY_SECOND: + Ina219EverySecond(); + break; case FUNC_JSON_APPEND: Ina219Show(1); break; diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index e845b628f..7c18fa723 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -249,10 +249,40 @@ boolean XsnsCall(byte Function) { boolean result = false; +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif // PROFILE_XSNS_EVERY_SECOND + for (byte x = 0; x < xsns_present; x++) { + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif // PROFILE_XSNS_SENSOR_EVERY_SECOND + result = xsns_func_ptr[x](Function); + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + snprintf_P(log_data, sizeof(log_data), PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); + AddLog(LOG_LEVEL_DEBUG); + } + } +#endif // PROFILE_XSNS_SENSOR_EVERY_SECOND + if (result) break; } +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + snprintf_P(log_data, sizeof(log_data), PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); + AddLog(LOG_LEVEL_DEBUG); + } + } +#endif // PROFILE_XSNS_EVERY_SECOND + return result; } From 5372cdf511bf8d90e35a335d26983a9edada220b Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 12 Jul 2018 14:24:17 +0200 Subject: [PATCH 13/14] Fix invalid response Fix invalid response using more than 4 switches and domoticz --- sonoff/_releasenotes.ino | 1 + sonoff/xdrv_07_domoticz.ino | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 481b0a7da..9c872e25e 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Fix invalid response using more than 4 switches and domoticz * Update sensor drivers to provide instant results * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 * Change SHT1x driver to provide better instant results diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index f2b972326..f29def2ce 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -271,14 +271,17 @@ boolean DomoticzCommand() boolean DomoticzSendKey(byte key, byte device, byte state, byte svalflg) { - if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); - MqttPublish(domoticz_in_topic); - return 1; - } else { - return 0; + boolean result = 0; + + if (device <= MAX_DOMOTICZ_IDX) { + if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), + (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); + MqttPublish(domoticz_in_topic); + result = 1; + } } + return result; } /*********************************************************************************************\ From bee95c5b56610dfbd6bd366740588d7f31dae098 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Thu, 12 Jul 2018 14:52:35 +0200 Subject: [PATCH 14/14] Add TM1638 switch support Add TM1638 switch support (#2226) --- sonoff/_releasenotes.ino | 1 + sonoff/sonoff.ino | 9 ++++++--- sonoff/xsns_28_tm1638.ino | 35 +++++++++++++++++++++-------------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 9c872e25e..0635beae8 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,5 @@ /* 6.1.0a + * Add TM1638 switch support (#2226) * Fix invalid response using more than 4 switches and domoticz * Update sensor drivers to provide instant results * Add read sensor retry to DS18B20, DS18x20, DHT, SHT1X and HTU21 diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 98fb7b7a3..01051db1f 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -177,7 +177,7 @@ uint8_t multiwindow[MAX_KEYS] = { 0 }; // Max time between button presses t uint8_t multipress[MAX_KEYS] = { 0 }; // Number of button presses within multiwindow uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold -uint8_t virtualswitch[MAX_SWITCHES] = { 0 }; // Virtual switch states +uint8_t virtualswitch[MAX_SWITCHES]; // Virtual switch states mytmplt my_module; // Active copy of Module name and GPIOs uint8_t pin[GPIO_MAX]; // Possible pin configurations @@ -1734,7 +1734,7 @@ void SwitchHandler(byte mode) uint8_t switchflag; for (byte i = 0; i < MAX_SWITCHES; i++) { - if (pin[GPIO_SWT1 +i] < 99) { + if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { if (holdwallswitch[i]) { holdwallswitch[i]--; @@ -2390,10 +2390,13 @@ void GpioInit() } } for (byte i = 0; i < MAX_SWITCHES; i++) { + lastwallswitch[i] = 1; // Init global to virtual switch state; if (pin[GPIO_SWT1 +i] < 99) { pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 :INPUT_PULLUP); - lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check + lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // Set global now so doesn't change the saved power state on first switch check + } + virtualswitch[i] = lastwallswitch[i]; } #ifdef USE_WS2812 diff --git a/sonoff/xsns_28_tm1638.ino b/sonoff/xsns_28_tm1638.ino index 6945261c8..01f2f21a5 100644 --- a/sonoff/xsns_28_tm1638.ino +++ b/sonoff/xsns_28_tm1638.ino @@ -35,19 +35,20 @@ uint8_t tm1638_clock_pin = 0; uint8_t tm1638_data_pin = 0; uint8_t tm1638_strobe_pin = 0; uint8_t tm1638_displays = 8; -uint8_t tm1638_active_display = 0; +uint8_t tm1638_active_display = 1; uint8_t tm1638_intensity = 0; +uint8_t tm1638_state = 0; /*********************************************************************************************\ * Pieces from library https://github.com/rjbatista/tm1638-library + * and from library https://github.com/MartyMacGyver/TM1638-demos-and-examples \*********************************************************************************************/ void Tm16XXSend(byte data) { - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 8; i++) { + digitalWrite(tm1638_data_pin, !!(data & (1 << i))); digitalWrite(tm1638_clock_pin, LOW); - digitalWrite(tm1638_data_pin, data & 1 ? HIGH : LOW); - data >>= 1; delayMicroseconds(TM1638_CLOCK_DELAY); digitalWrite(tm1638_clock_pin, HIGH); } @@ -77,11 +78,10 @@ byte Tm16XXReceive() pinMode(tm1638_data_pin, INPUT); digitalWrite(tm1638_data_pin, HIGH); - for (int i = 0; i < 8; i++) { - temp >>= 1; + for (uint8_t i = 0; i < 8; ++i) { digitalWrite(tm1638_clock_pin, LOW); delayMicroseconds(TM1638_CLOCK_DELAY); - if (digitalRead(tm1638_data_pin)) { temp |= 0x80; } + temp |= digitalRead(tm1638_data_pin) << i; digitalWrite(tm1638_clock_pin, HIGH); } @@ -165,25 +165,32 @@ void TmInit() digitalWrite(tm1638_strobe_pin, HIGH); tm1638_type = 1; + tm1638_state = 1; } } void TmLoop() { - byte buttons = Tm1638GetButtons(); - for (byte i = 0; i < MAX_SWITCHES; i++) { - virtualswitch[i] = buttons &1; - byte color = (virtualswitch[i]) ? TM1638_COLOR_RED : TM1638_COLOR_NONE; - Tm1638SetLED(color, i); - buttons >>= 1; + if (tm1638_state) { + byte buttons = Tm1638GetButtons(); + for (byte i = 0; i < MAX_SWITCHES; i++) { + virtualswitch[i] = (buttons &1) ^1; + byte color = (virtualswitch[i]) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; + Tm1638SetLED(color, i); + buttons >>= 1; + } + SwitchHandler(1); } - SwitchHandler(1); } +/* void TmShow(boolean json) { + if (tm1638_type) { + } } +*/ /*********************************************************************************************\ * Interface