mirror of https://github.com/arendst/Tasmota.git
Merge branch 'arendst/development' into development
This commit is contained in:
commit
431c9bb469
|
@ -21,6 +21,17 @@ This file is part of the Joba_Tsl2561 Library.
|
|||
|
||||
#include <Tsl2561Util.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
@ -21,6 +21,17 @@ This file is part of the Joba_Tsl2561 Library.
|
|||
|
||||
#include <Tsl2561.h>
|
||||
|
||||
// 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();
|
||||
}
|
|
@ -22,11 +22,22 @@ This file is part of the Joba_Tsl2561 Library.
|
|||
|
||||
#include <Tsl2561.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
@ -21,6 +21,17 @@ This file is part of the Joba_Tsl2561 Library.
|
|||
|
||||
#include <Tsl2561Util.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
@ -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]
|
|
@ -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
|
||||
|
|
@ -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 <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
// 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
|
|
@ -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":
|
|
@ -1,5 +1,5 @@
|
|||
name=Joba Tsl2561 Library
|
||||
version=2.0.1
|
||||
version=2.0.7
|
||||
author=joba-1
|
||||
maintainer=joba-1 <joban123.psn@gmail.com>
|
||||
sentence=IoT library for using the Tsl2561 luminosity sensor
|
|
@ -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
|
|
@ -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<status_t>(_wire.endTransmission(false))) == ERR_OK ) {
|
||||
if( _wire.requestFrom(_addr, 1) == 1 ) {
|
||||
val = static_cast<uint8_t>(_wire.read());
|
||||
}
|
||||
else {
|
||||
_status = ERR_RW;
|
||||
}
|
||||
}
|
||||
return (_status = static_cast<status_t>(_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<status_t>(_wire.endTransmission(false))) == ERR_OK ) {
|
||||
if( _wire.requestFrom(_addr, 2) == 2 ) {
|
||||
val = static_cast<uint16_t>(_wire.read()) & 0xff;
|
||||
val |= (static_cast<uint16_t>(_wire.read()) & 0xff) << 8;
|
||||
}
|
||||
else {
|
||||
_status = ERR_RW;
|
||||
}
|
||||
}
|
||||
return (_status = static_cast<status_t>(_wire.endTransmission())) == ERR_OK;
|
||||
return _status == ERR_OK;
|
||||
}
|
||||
|
||||
bool Tsl2561::writeByte( register_t reg, uint8_t val ) {
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -1,4 +1,15 @@
|
|||
/* 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
|
||||
* 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)
|
||||
* 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)
|
||||
* Add experimental (untested) TM1638 switch support (#2226)
|
||||
* Add support for APDS9960 proximity sensor (#3051)
|
||||
|
@ -15,16 +26,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 [<host>(:<port>,<user>:<password>)] <command> (#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)
|
||||
|
@ -35,52 +72,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 [<host>(:<port>,<user>:<password>)] <command> (#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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
|
|
@ -26,9 +26,10 @@
|
|||
#define W1_CONVERT_TEMP 0x44
|
||||
#define W1_READ_SCRATCHPAD 0xBE
|
||||
|
||||
float ds18b20_last_temperature = 0;
|
||||
uint16_t ds18b20_last_result = 0;
|
||||
float ds18b20_temperature = 0;
|
||||
uint8_t ds18b20_valid = 0;
|
||||
uint8_t ds18x20_pin = 0;
|
||||
char ds18b20_types[] = "DS18B20";
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Embedded stripped and tuned OneWire library
|
||||
|
@ -126,12 +127,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 +135,16 @@ void Ds18x20Convert()
|
|||
// delay(750); // 750ms should be enough for 12bit conv
|
||||
}
|
||||
|
||||
boolean Ds18b20Read(float &t)
|
||||
boolean 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_valid) { ds18b20_valid--; }
|
||||
/*
|
||||
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,44 +160,55 @@ 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;
|
||||
ds18b20_temperature = ConvertTemp(sign * temp12 * 0.0625);
|
||||
ds18b20_valid = SENSOR_MAX_MISS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR));
|
||||
return !isnan(t);
|
||||
return false;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ds18b20Show(boolean json)
|
||||
{
|
||||
float t;
|
||||
|
||||
if (Ds18b20Read(t)) { // Check if read failed
|
||||
if (ds18b20_valid) { // 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);
|
||||
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, t);
|
||||
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
|
||||
}
|
||||
}
|
||||
Ds18x20Convert(); // Start conversion, takes up to one second
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -225,11 +223,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);
|
||||
|
|
|
@ -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
|
||||
|
@ -38,11 +39,16 @@
|
|||
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 };
|
||||
|
||||
struct DS18X20STRUCT {
|
||||
uint8_t address[8];
|
||||
uint8_t index;
|
||||
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
|
||||
|
@ -246,28 +252,29 @@ 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_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 +290,7 @@ void Ds18x20Convert()
|
|||
// delay(750); // 750ms should be enough for 12bit conv
|
||||
}
|
||||
|
||||
boolean Ds18x20Read(uint8_t sensor, float &t)
|
||||
bool Ds18x20Read(uint8_t sensor)
|
||||
{
|
||||
uint8_t data[9];
|
||||
int8_t sign = 1;
|
||||
|
@ -291,17 +298,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].valid) { ds18x20_sensor[index].valid--; }
|
||||
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 +319,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].valid = SENSOR_MAX_MISS;
|
||||
return true;
|
||||
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,72 +340,99 @@ 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].valid = SENSOR_MAX_MISS;
|
||||
return true;
|
||||
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].valid = SENSOR_MAX_MISS;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!isnan(t)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]) {
|
||||
break;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types);
|
||||
if (ds18x20_sensor[index].valid) { // Check for valid temperature
|
||||
dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature);
|
||||
|
||||
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);
|
||||
} 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);
|
||||
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
|
||||
if ((0 == tele_period) && (0 == i)) {
|
||||
KnxSensor(KNX_TEMPERATURE, t);
|
||||
KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature);
|
||||
}
|
||||
#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
|
||||
}
|
||||
}
|
||||
}
|
||||
Ds18x20Convert(); // Start conversion, takes up to one second
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -415,8 +450,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);
|
||||
|
|
|
@ -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) {
|
||||
|
@ -127,57 +121,43 @@ void 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)) {
|
||||
Dht[sensor].lastresult = 0;
|
||||
} else {
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE));
|
||||
Dht[sensor].lastresult++;
|
||||
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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (DhtRead(sensor)) {
|
||||
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);
|
||||
Dht[sensor].lastresult = 0;
|
||||
} else {
|
||||
Dht[sensor].lastresult++;
|
||||
}
|
||||
return (!isnan(t) && !isnan(h));
|
||||
}
|
||||
|
||||
boolean DhtSetup(byte pin, byte type)
|
||||
|
@ -210,41 +190,46 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DhtShow(boolean json)
|
||||
{
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
|
||||
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++;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
|
||||
#ifdef USE_KNX
|
||||
if (0 == tele_period) {
|
||||
KnxSensor(KNX_TEMPERATURE, t);
|
||||
KnxSensor(KNX_HUMIDITY, 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);
|
||||
#endif // USE_WEBSERVER
|
||||
if ((0 == tele_period) && (0 == i)) {
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
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());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, Dht[i].stype, humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,8 +249,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);
|
||||
|
|
|
@ -37,6 +37,10 @@ enum {
|
|||
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;
|
||||
|
||||
boolean ShtReset()
|
||||
{
|
||||
|
@ -119,46 +123,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 = SENSOR_MAX_MISS;
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -169,12 +159,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,38 +170,44 @@ void ShtDetect()
|
|||
}
|
||||
}
|
||||
|
||||
void ShtEverySecond()
|
||||
{
|
||||
if (sht_type && !(uptime %4)) { // Update every 4 seconds
|
||||
// 344mS
|
||||
if (!ShtRead()) {
|
||||
AddLogMissed(sht_types, sht_valid);
|
||||
// if (!sht_valid) { sht_type = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShtShow(boolean json)
|
||||
{
|
||||
if (sht_type) {
|
||||
float t;
|
||||
float h;
|
||||
if (sht_valid) {
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
|
||||
if (ShtReadTempHum(t, h)) {
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature);
|
||||
dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity);
|
||||
|
||||
dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
|
||||
dtostrfd(h, 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);
|
||||
#endif // USE_DOMOTICZ
|
||||
|
||||
#ifdef USE_KNX
|
||||
if (0 == tele_period) {
|
||||
KnxSensor(KNX_TEMPERATURE, t);
|
||||
KnxSensor(KNX_HUMIDITY, h);
|
||||
}
|
||||
#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);
|
||||
#endif // USE_WEBSERVER
|
||||
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);
|
||||
}
|
||||
#endif // USE_KNX
|
||||
#ifdef USE_WEBSERVER
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,9 +224,13 @@ 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_EVERY_SECOND:
|
||||
ShtEverySecond();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
ShtShow(1);
|
||||
break;
|
||||
|
|
|
@ -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,45 @@ 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);
|
||||
// if (!htu_valid) { htu_type = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HtuShow(boolean json)
|
||||
{
|
||||
if (htu_type) {
|
||||
if (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,9 +285,12 @@ boolean Xsns08(byte function)
|
|||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
case FUNC_PREP_BEFORE_TELEPERIOD:
|
||||
case FUNC_INIT:
|
||||
HtuDetect();
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
HtuEverySecond();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
HtuShow(1);
|
||||
break;
|
||||
|
|
|
@ -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
|
||||
\*********************************************************************************************/
|
||||
|
@ -78,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()
|
||||
{
|
||||
|
@ -113,21 +117,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);
|
||||
int32_t 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 +144,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 = (float)p / 100.0; // convert to mbar
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -215,8 +212,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;
|
||||
|
@ -233,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);
|
||||
|
@ -267,62 +248,42 @@ 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;
|
||||
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();
|
||||
int32_t t_fine = vart1 + vart2;
|
||||
float T = (t_fine * 5 + 128) >> 8;
|
||||
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;
|
||||
|
||||
double Bme280ReadHumidity(void)
|
||||
{
|
||||
int32_t v_x1_u32r;
|
||||
|
||||
// Must be done first to get the t_fine variable set up
|
||||
// Bme280ReadTemperature();
|
||||
if (BMP280_CHIPID == bmp_type) { return; }
|
||||
|
||||
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) *
|
||||
|
@ -332,8 +293,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 +306,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 +358,7 @@ boolean Bme680Init()
|
|||
return true;
|
||||
}
|
||||
|
||||
void Bme680PerformReading()
|
||||
void Bme680Read()
|
||||
{
|
||||
int8_t rslt = BME680_OK;
|
||||
|
||||
|
@ -424,14 +382,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 +402,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 +412,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 +442,57 @@ 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)) {
|
||||
// 1mS
|
||||
BmpDetect();
|
||||
}
|
||||
else {
|
||||
// 2mS
|
||||
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 +513,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 +557,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);
|
||||
|
|
|
@ -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,48 @@ 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)) {
|
||||
// 1mS
|
||||
Bh1750Detect();
|
||||
}
|
||||
else {
|
||||
// 1mS
|
||||
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} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
"%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#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 +122,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}"),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -217,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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue