Merge branch 'development' into add-wemos-motor-shield-v1

This commit is contained in:
Denis 2020-02-20 21:05:55 -08:00
commit 19ca1eb2d4
41 changed files with 520 additions and 234 deletions

View File

@ -64,5 +64,5 @@ Index | Define | Driver | Device | Address(es) | Description
41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor
42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor
42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor
43 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x30 | WEMOS motor shield v1.0.0 (6612FNG)
43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor
44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG)

View File

@ -52,14 +52,12 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog
### Version 8.1.0.8
### Version 8.1.0.9
- Change Lights: simplified gamma correction and 10 bits internal computation
- Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items
- Change IRremoteESP8266 library updated to v2.7.3
- Change Zigbee command prefix from ``Zigbee*`` to ``Zb*``
- Change wifi connectivity stability (#7602)
- Change some wifi code to attempt faster connection (#7621)
- Change MQTT message size with additional 200 characters
- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12"
- Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging
@ -75,6 +73,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Fix PWM flickering at low levels (#7415)
- Fix Hass sensor discovery part 1/4 by Federico Leoni (#7582, #7548)
- Fix MaxPower functionality (#7647)
- Fix relation between RSSI and signal strength
- Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355)
- Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380
- Add command ``SetOption84 1`` to send AWS IoT device shadow updates (alternative to retained)
@ -104,3 +103,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add support for FiF LE-01MR energy meter by saper-2 (#7584)
- Add new DHT driver. The old driver can still be used using define USE_DHT_OLD (#7468)
- Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717)
- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596)

View File

@ -226,10 +226,10 @@ build_flags = ${esp82xx_defaults.build_flags}
[core_stage]
; *** Esp8266 core for Arduino version latest beta
platform = espressif8266@2.3.1
platform = espressif8266@2.3.2
platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git
board_build.ldscript = eagle.flash.1m.ld
build_flags = ${esp82xx_defaults.build_flags}
-Wl,-Teagle.flash.1m.ld
-DBEARSSL_SSL_BASIC
-DNOPRINTFLOAT
; NONOSDK221

View File

@ -1,10 +1,16 @@
## Unreleased (development)
### 8.1.0.9 20200220
- Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621)
- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596)
### 8.1.0.8 20200212
- Change MQTT message size with additional 200 characters
- Change some wifi code to attempt faster connection (#7621)
- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12"
- Fix relation between RSSI and signal strength
- Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717)
### 8.1.0.7 20200210

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RF TX"
#define D_SENSOR_RFRECV "RF RX"
#define D_SENSOR_TUYA_TX "Tuya TX"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFRecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -564,7 +564,7 @@
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_TX2X_TX "TX2x"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"

View File

@ -486,6 +486,7 @@
// #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6)
// #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 code)
// #define USE_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code)
// #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code)
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
@ -620,7 +621,9 @@
#define USE_HX711 // Add support for HX711 load cell (+1k5 code)
// #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code)
//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code)
// Select none or only one of the below defines
//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code)
//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code)
//#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram)

View File

@ -51,7 +51,8 @@ void OsWatchTicker(void)
uint32_t last_run = abs(t - oswatch_last_loop_time);
#ifdef DEBUG_THEO
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), last_run);
int32_t rssi = WiFi.RSSI();
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run);
#endif // DEBUG_THEO
if (last_run >= (OSWATCH_RESET_TIME * 1000)) {
// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); // Save iram space

View File

@ -367,7 +367,7 @@ void GetFeatures(void)
#ifdef USE_PZEM_DC
feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino
#endif
#ifdef USE_TX20_WIND_SENSOR
#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR)
feature_sns2 |= 0x00002000; // xsns_35_tx20.ino
#endif
#ifdef USE_MGC3130
@ -513,11 +513,13 @@ void GetFeatures(void)
#ifdef USE_LE01MR
feature5 |= 0x08000000; // xnrg_13_fif_le01mr.ino
#endif
#ifdef USE_AHT1x
feature5 |= 0x10000000; // xsns_63_aht1x.ino
#endif
#ifdef USE_WEMOS_MOTOR_V1
feature5 |= 0x10000000; // xdrv_34_wemos_motor_v1.ino
feature5 |= 0x20000000; // xdrv_34_wemos_motor_v1.ino
#endif
// feature5 |= 0x20000000;
// feature5 |= 0x40000000;
// feature5 |= 0x80000000;

View File

@ -47,7 +47,6 @@ struct RTC {
uint32_t ntp_time = 0;
uint32_t midnight = 0;
uint32_t restart_time = 0;
int32_t drift_time = 0;
int32_t time_timezone = 0;
uint8_t ntp_sync_minute = 0;
bool midnight_now = false;
@ -64,11 +63,6 @@ uint32_t LocalTime(void)
return Rtc.local_time;
}
int32_t DriftTime(void)
{
return Rtc.drift_time;
}
uint32_t Midnight(void)
{
return Rtc.midnight;
@ -380,7 +374,6 @@ void RtcSecond(void)
Rtc.ntp_time = sntp_get_current_timestamp();
if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on)
ntp_force_sync = false;
if (Rtc.utc_time > START_VALID_TIME) { Rtc.drift_time = Rtc.ntp_time - Rtc.utc_time; }
Rtc.utc_time = Rtc.ntp_time;
Rtc.ntp_sync_minute = 60; // Sync so block further requests
if (Rtc.restart_time == 0) {
@ -392,8 +385,8 @@ void RtcSecond(void)
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
// Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9
PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ")%s, (" D_DST_TIME ")%s, (" D_STD_TIME ")%s"),
DriftTime(), GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"),
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01
rules_flag.time_init = 1;

View File

@ -647,9 +647,10 @@ void MqttShowState(void)
MqttShowPWMState();
}
int32_t rssi = WiFi.RSSI();
ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"),
Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(),
WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str());
WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str());
}
void MqttPublishTeleState(void)

View File

@ -22,17 +22,14 @@
\*********************************************************************************************/
#ifndef WIFI_RSSI_THRESHOLD
// Decrease the roam threshold from 10 to 5 to address devices connecting at very low RSSI and being close to inoperative
#define WIFI_RSSI_THRESHOLD 5 // Difference in dB between current network and scanned network
#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network
#endif
#ifndef WIFI_RESCAN_MINUTES
// Increase rescan interval from 44 to 5 minutes to improve ability for devices to reach network harmony
#define WIFI_RESCAN_MINUTES 5 // Number of minutes between wifi network rescan
#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan
#endif
const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart
// Drop from 20 seconds to 5 seconds since we control the reconnections, not the Arduino SDK
const uint8_t WIFI_CHECK_SEC = 5; // seconds
const uint8_t WIFI_CHECK_SEC = 20; // seconds
const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
@ -52,8 +49,7 @@ struct WIFI {
uint8_t config_counter = 0;
uint8_t mdns_begun = 0; // mDNS active
uint8_t scan_state;
uint8_t bssid[6] = {0};
uint8_t bssid_last[6] = {0}; // store the last connect bssid
uint8_t bssid[6];
int8_t best_network_db;
} Wifi;
@ -187,11 +183,7 @@ void WifiBegin(uint8_t flag, uint8_t channel)
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N
// if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G
if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); }
// Handle the reconnection in WifiCheckIp() since the autoreconnect keeps sending deauthentication messages which causes the AP to block traffic as it looks like an DoS attack
// This needs to be explicitly called as "false" otherwise the default is enabled
// WiFi.setAutoReconnect(false); // See #7621
// WiFi.setAutoReconnect(true);
switch (flag) {
case 0: // AP1
case 1: // AP2
@ -249,7 +241,7 @@ void WifiBeginAfterScan(void)
if (2 == Wifi.scan_state) {
uint8_t* bssid = WiFi.BSSID(); // Get current bssid
memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid));
Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold
Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold
if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) {
Wifi.best_network_db += WIFI_RSSI_THRESHOLD;
}
@ -273,12 +265,6 @@ void WifiBeginAfterScan(void)
}
// Scan done
if (5 == Wifi.scan_state) {
uint32_t number_known = 0; // count the number of known AP's so we can clear the Wifi.bssid_last if there is only one
int32_t channel_max = 0; // No scan result
int8_t ap_max = 3; // AP default if not found
uint8_t bssid_max[6]; // Save last bssid
memcpy((void*) &bssid_max, (void*) &Wifi.bssid, sizeof(bssid_max)); // store the strongest bssid
int32_t channel = 0; // No scan result
int8_t ap = 3; // AP default if not found
uint8_t last_bssid[6]; // Save last bssid
@ -302,25 +288,12 @@ void WifiBeginAfterScan(void)
for (j = 0; j < MAX_SSIDS; j++) {
if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match
known = true;
number_known++;
if (rssi_scan > Wifi.best_network_db) { // Best network
if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan
// store the max values in case there is only one AP and we need to try to reconnect
memcpy((void*) &bssid_max, (void*) bssid_scan, sizeof(bssid_max));
channel_max = chan_scan;
ap_max = j;
// if the bssid is not the same as the last failed attempt, force picking the next strongest AP to prevent getting stuck on a strong RSSI, but poor channel health
for (uint32_t i = 0; i < sizeof(Wifi.bssid_last); i++) {
if (bssid_scan[i] != Wifi.bssid_last[i]) {
Wifi.best_network_db = (int8_t)rssi_scan;
channel = chan_scan;
ap = j; // AP1 or AP2
memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid));
// save the last bssid used
memcpy((void*) &Wifi.bssid_last, (void*) bssid_scan, sizeof(Wifi.bssid_last));
break;
}
}
Wifi.best_network_db = (int8_t)rssi_scan;
channel = chan_scan;
ap = j; // AP1 or AP2
memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid));
}
}
break;
@ -340,16 +313,6 @@ void WifiBeginAfterScan(void)
WiFi.scanDelete(); // Clean up Ram
delay(0);
}
// reset the last bssid if there is only one AP to allow the reconnect of the same AP on the next cycle
if (number_known == 1) {
// clear the last value
memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last));
memcpy((void*) &Wifi.bssid, (void*) bssid_max, sizeof(Wifi.bssid));
channel = channel_max;
ap = ap_max;
}
Wifi.scan_state = 0;
// If bssid changed then (re)connect wifi
for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) {
@ -424,13 +387,15 @@ void WifiCheckIp(void)
#else
if ((WL_CONNECTED == WiFi.status()) && (static_cast<uint32_t>(WiFi.localIP()) != 0)) {
#endif // LWIP_IPV6=1
// initialize the last connect bssid since we had a successful connection
memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last));
WifiSetState(1);
Wifi.counter = WIFI_CHECK_SEC;
Wifi.retry = Wifi.retry_init;
if (Wifi.status != WL_CONNECTED) {
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECTED));
// AddLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses"));
Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP();
Settings.ip_address[2] = (uint32_t)WiFi.subnetMask();
Settings.ip_address[3] = (uint32_t)WiFi.dnsIP();
}
Wifi.status = WL_CONNECTED;
#ifdef USE_DISCOVERY
@ -448,13 +413,11 @@ void WifiCheckIp(void)
switch (Wifi.status) {
case WL_CONNECTED:
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS));
// if poor channel health prevents DHCP broadcast from succeeding, restart the request
// The code will eventually do a recoonect when the 1/2 interval is hit to try another access point if this remains unsuccessful
wifi_station_dhcpc_start();
Wifi.status = 0;
Wifi.retry = Wifi.retry_init;
break;
case WL_NO_SSID_AVAIL:
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED));
if (WIFI_WAIT == Settings.sta_config) {
Wifi.retry = Wifi.retry_init;
} else {
@ -465,21 +428,17 @@ void WifiCheckIp(void)
Wifi.retry = 0;
}
}
break;
case WL_CONNECT_FAILED:
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD));
if (Wifi.retry > (Wifi.retry_init / 2)) {
Wifi.retry = Wifi.retry_init / 2;
}
else if (Wifi.retry) {
Wifi.retry = 0;
}
break;
default: // WL_IDLE_STATUS and WL_DISCONNECTED
// log on the 1/2 or full interval
if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) {
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT));
} else {
@ -491,11 +450,9 @@ void WifiCheckIp(void)
}
}
}
if (Wifi.retry) {
if (Settings.flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's
// check the 1/2 interval as well when rescanning - scan state machine takes 4 seconds
if ((Wifi.retry_init == Wifi.retry) || ((Wifi.retry_init / 2) == Wifi.retry)){
if (Wifi.retry_init == Wifi.retry) {
Wifi.scan_state = 1; // Select scanned SSID
}
} else {
@ -642,6 +599,7 @@ String WifiGetOutputPower(void)
dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1);
return String(stemp1);
}
void WifiSetOutputPower(void)
{
WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10);
@ -653,9 +611,7 @@ void WifiConnect(void)
WifiSetOutputPower();
WiFi.persistent(false); // Solve possible wifi init errors
Wifi.status = 0;
// lower the rety times now Tasmota control the reconnections, not the Arduino SDK
// Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2);
Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF);
Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2);
Wifi.retry = Wifi.retry_init;
Wifi.counter = 1;
}

View File

@ -164,6 +164,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
//#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code)
//#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code)
#define USE_HIH6 // Enable Honywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6)
//#define USE_AHT1x // Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code)
#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
@ -211,7 +212,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code)
#define USE_HX711 // Add support for HX711 load cell (+1k5 code)
//#define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code)
//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code)
//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code)
//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code)
#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram)
#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code)
@ -406,6 +408,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8
#undef USE_HX711 // Disable support for HX711 load cell
#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer
#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer
#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code)
@ -515,6 +518,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8
#undef USE_HX711 // Disable support for HX711 load cell
#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer
#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer
#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code)
@ -627,6 +631,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8
#undef USE_HX711 // Disable support for HX711 load cell
#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer
#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer
#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code)

View File

@ -128,7 +128,7 @@ enum UserSelectablePins {
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_HX711_SCK, // HX711 Load Cell clock
GPIO_HX711_DAT, // HX711 Load Cell data
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin
GPIO_RFSEND, // RF transmitter
GPIO_RFRECV, // RF receiver
GPIO_TUYA_TX, // Tuya Serial interface
@ -267,7 +267,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|"
D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|"
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
D_SENSOR_TX20_TX "|"
D_SENSOR_TX2X_TX "|"
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|"
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|"
D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|"
@ -721,8 +721,8 @@ const uint8_t kGpioNiceList[] PROGMEM = {
#ifdef USE_PMS5003
GPIO_PMS5003, // Plantower PMS5003 Serial interface
#endif
#ifdef USE_TX20_WIND_SENSOR
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR)
GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin
#endif
#ifdef USE_MP3_PLAYER
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface

View File

@ -20,7 +20,7 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
const uint32_t VERSION = 0x08010008;
const uint32_t VERSION = 0x08010009;
// Lowest compatible version
const uint32_t VERSION_COMPATIBLE = 0x07010006;

View File

@ -1719,16 +1719,17 @@ void HandleWifiConfiguration(void)
//display networks in page
for (uint32_t i = 0; i < n; i++) {
if (-1 == indices[i]) { continue; } // skip dups
int32_t rssi = WiFi.RSSI(indices[i])
DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"),
WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i]));
int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i]));
WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi);
int quality = WifiGetRssiAsQuality(rssi);
int auth = WiFi.encryptionType(indices[i]);
char encryption[20];
WSContentSend_P(PSTR("<div><a href='#p' onclick='c(this)'>%s</a>&nbsp;(%d)&nbsp<span class='q'>%s %d%% (%d dBm)</span></div>"),
HtmlEscape(WiFi.SSID(indices[i])).c_str(),
WiFi.channel(indices[i]),
GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType),
quality, WiFi.RSSI(indices[i])
quality, rssi
);
delay(0);
@ -2067,7 +2068,8 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i));
}
WSContentSend_P(PSTR("}1}2&nbsp;")); // Empty line
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI());
int32_t rssi = WiFi.RSSI();
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(rssi), rssi);
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "");
#if LWIP_IPV6
String ipv6_addr = WifiGetIPv6();

View File

@ -114,6 +114,7 @@ void (* const TuyaCommand[])(void) PROGMEM = {
TuyaSend<x> dpId,data
TuyaSend0 -> Sends TUYA_CMD_QUERY_STATE
TuyaSend1 11,1 -> Sends boolean (Type 1) data 0/1 to dpId 11 (Max data length 1 byte)
TuyaSend2 11,100 -> Sends integer (Type 2) data 100 to dpId 11 (Max data length 4 bytes)
TuyaSend2 11,0xAABBCCDD -> Sends 4 bytes (Type 2) data to dpId 11 (Max data length 4 bytes)
@ -124,9 +125,13 @@ TuyaSend4 11,1 -> Sends enum (Type 4) data 0/1/2/3/4/5 to dpId 11 (Max data leng
void CmndTuyaSend(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) {
if (XdrvMailbox.index > 4) {
return;
}
if (XdrvMailbox.index == 0) {
TuyaRequestState();
} else {
if (XdrvMailbox.data_len > 0) {
char *p;
char *data;
uint8_t i = 0;
@ -150,8 +155,8 @@ void CmndTuyaSend(void) {
TuyaSendEnum(dpId, strtoul(data, nullptr, 0));
}
}
ResponseCmndDone();
}
ResponseCmndDone();
}
/*
@ -682,10 +687,31 @@ void TuyaSerialInput(void)
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
uint8_t dpidStart = 6;
while (dpidStart + 4 < Tuya.byte_counter) {
uint8_t dpId = Tuya.buffer[dpidStart];
uint8_t dpDataType = Tuya.buffer[dpidStart + 1];
uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3];
ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char)));
if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) {
ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]);
const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4];
const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char));
if (TUYA_CMD_STATE == Tuya.buffer[3]) {
ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId);
if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) {
ResponseAppend_P(PSTR("%u"), dpData[0]);
} else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) {
uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0;
ResponseAppend_P(PSTR("%u"), dpValue);
} else if (TUYA_TYPE_STRING == dpDataType) {
ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData);
} else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) {
ResponseAppend_P(PSTR("%u"), dpData[0]);
} else {
ResponseAppend_P(PSTR("\"0x%s\""), dpHexData);
}
}
ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData);
if (TUYA_TYPE_STRING == dpDataType) {
ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData);
}
ResponseAppend_P(PSTR("}"));
dpidStart += dpDataLen + 4;

View File

@ -24,7 +24,7 @@
*
* I2C Address: 0x30
* Command format:
* driver43 <command>,<motor>,<direction>{,<duty>}
* driver44 <command>,<motor>,<direction>{,<duty>}
* command:
* RESET - reset a motor shield
* SETMOTOR - seter motor state
@ -42,7 +42,7 @@
\*********************************************************************************************/
#define XDRV_34 34
#define XI2C_43 43 // See I2CDEVICES.md
#define XI2C_44 44 // See I2CDEVICES.md
#define MOTOR_A 0
#define MOTOR_B 1
@ -164,7 +164,7 @@ bool Motor_Command(void)
bool Xdrv34(uint8_t function)
{
if (!I2cEnabled(XI2C_43))
if (!I2cEnabled(XI2C_44))
{
return false;
}
@ -176,7 +176,7 @@ bool Xdrv34(uint8_t function)
}
else if (wemos_driver_detected)
{
if (FUNC_COMMAND_DRIVER == function && XI2C_43 == XdrvMailbox.index)
if (FUNC_COMMAND_DRIVER == function && XI2C_44 == XdrvMailbox.index)
{
result = Motor_Command();
}

View File

@ -1,7 +1,7 @@
/*
xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Tasmota
xsns_35_Tx20.ino - La Crosse Tx20/Tx23 wind sensor support for Tasmota
Copyright (C) 2020 Thomas Eckerstorfer and Theo Arends
Copyright (C) 2020 Thomas Eckerstorfer, Norbert Richter and Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -17,19 +17,31 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_TX20_WIND_SENSOR
#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR)
#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR)
#undef USE_TX20_WIND_SENSOR
#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled ****
#endif
/*********************************************************************************************\
* La Crosse Tx20 wind sensor
* La Crosse TX20/TX23 Anemometer
*
* based on https://github.com/bunnyhu/ESP8266_TX20_wind_sensor/
* http://blog.bubux.de/windsensor-tx20-mit-esp8266/
* https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/
* http://www.rd-1000.com/chpm78/lacrosse/Lacrosse_TX23_protocol.html
* https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/
*
* TX23 RJ11 connection:
* 1 yellow - GND
* 2 green - NC
* 3 red - Vcc 3.3V
* 4 black/brown - TxD Signal (GPIOxx)
\*********************************************************************************************/
#define XSNS_35 35
#define TX20_BIT_TIME 1220 // microseconds
#define TX20_RESET_VALUES 60 // seconds
#define TX2X_BIT_TIME 1220 // microseconds
#define TX2X_RESET_VALUES 60 // seconds
// The Arduino standard GPIO routines are not enough,
// must use some from the Espressif SDK as well
@ -37,17 +49,21 @@ extern "C" {
#include "gpio.h"
}
#ifdef USE_TX20_WIND_SENSOR
#define D_TX2x_NAME "TX20"
#else
#define D_TX2x_NAME "TX23"
#endif
#ifdef USE_WEBSERVER
const char HTTP_SNS_TX20[] PROGMEM =
"{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"
"{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"
"{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"
"{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}";
const char HTTP_SNS_TX2X[] PROGMEM =
"{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"
"{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"
"{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"
"{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s (%s&deg;){e}";
#endif // USE_WEBSERVER
const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|"
const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|"
D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|"
D_TX20_NORTH D_TX20_EAST "|"
D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|"
@ -64,133 +80,218 @@ const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|"
D_TX20_NORTH D_TX20_WEST "|"
D_TX20_NORTH D_TX20_NORTH D_TX20_WEST;
uint8_t tx20_sa = 0;
uint8_t tx20_sb = 0;
uint8_t tx20_sd = 0;
uint8_t tx20_se = 0;
uint16_t tx20_sc = 0;
uint16_t tx20_sf = 0;
uint8_t tx2x_sa = 0;
uint8_t tx2x_sb = 0;
uint8_t tx2x_sd = 0;
uint8_t tx2x_se = 0;
uint16_t tx2x_sc = 0;
uint16_t tx2x_sf = 0;
float tx20_wind_speed_kmh = 0;
float tx20_wind_speed_max = 0;
float tx20_wind_speed_avg = 0;
float tx20_wind_sum = 0;
int tx20_count = 0;
uint8_t tx20_wind_direction = 0;
float tx2x_wind_speed_kmh = 0;
float tx2x_wind_speed_max = 0;
float tx2x_wind_speed_avg = 0;
float tx2x_wind_sum = 0;
int tx2x_count = 0;
uint8_t tx2x_wind_direction = 0;
bool tx20_available = false;
bool tx2x_available = false;
#ifdef USE_TX23_WIND_SENSOR
uint8_t tx23_stage = 0;
#endif
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception
void Tx20StartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too
void TX2xStartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
void Tx20StartRead(void)
void TX2xStartRead(void)
{
/* La Crosse TX20 Anemometer datagram every 2 seconds
/**
* La Crosse TX20 Anemometer datagram every 2 seconds
* 0-0 11011 0011 111010101111 0101 1100 000101010000 0-0 - Received pin data at 1200 uSec per bit
* sa sb sc sd se sf
* 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first
* sa - Start frame always 00100
* sa - Start frame (invert) 00100
* sb - Wind direction (invert) 0 - 15
* sc - Wind speed 0 (invert) - 511
* sd - Checksum (invert)
* se - Wind direction 0 - 15
* sf - Wind speed 0 - 511
*
* La Crosse TX23 Anemometer datagram after setting TxD to low/high
* 1-1 0 1 0-0 11011 0011 111010101111 0101 1100 000101010000 1-1 - Received pin data at 1200 uSec per bit
* t s c sa sb sc sd se sf
* 1 0 1-1 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first
* t - host pulls TxD low - signals TX23 to sent measurement
* s - TxD released - TxD is pulled high due to pullup
* c - TX23U pulls TxD low - calculation in progress
* sa - Start frame 11011
* sb - Wind direction 0 - 15
* sc - Wind speed 0 - 511
* sd - Checksum
* se - Wind direction 0 - 15
* sf - Wind speed 0 - 511
* se - Wind direction (invert) 0 - 15
* sf - Wind speed (invert) 0 - 511
*/
#ifdef USE_TX23_WIND_SENSOR
if (0!=tx23_stage)
{
if ((2==tx23_stage) || (3==tx23_stage))
{
#endif
tx2x_available = false;
tx20_available = false;
tx2x_sa = 0;
tx2x_sb = 0;
tx2x_sd = 0;
tx2x_se = 0;
tx2x_sc = 0;
tx2x_sf = 0;
tx20_sa = 0;
tx20_sb = 0;
tx20_sd = 0;
tx20_se = 0;
tx20_sc = 0;
tx20_sf = 0;
delayMicroseconds(TX2X_BIT_TIME / 2);
delayMicroseconds(TX20_BIT_TIME / 2);
for (int32_t bitcount = 41; bitcount > 0; bitcount--) {
uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK]));
#ifdef USE_TX23_WIND_SENSOR
if (bitcount > 41 - 5) {
// start
tx2x_sa = (tx2x_sa << 1) | (dpin);
} else if (bitcount > 41 - 5 - 4) {
// wind dir
tx2x_sb = tx2x_sb >> 1 | ((dpin) << 3);
} else if (bitcount > 41 - 5 - 4 - 12) {
// windspeed
tx2x_sc = tx2x_sc >> 1 | ((dpin) << 11);
} else if (bitcount > 41 - 5 - 4 - 12 - 4) {
// checksum
tx2x_sd = tx2x_sd >> 1 | ((dpin) << 3);
} else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) {
// wind dir (invert)
tx2x_se = tx2x_se >> 1 | ((dpin ^ 1) << 3);
} else {
// windspeed (invert)
tx2x_sf = tx2x_sf >> 1 | ((dpin ^ 1) << 11);
}
#else
if (bitcount > 41 - 5) {
// start frame (invert)
tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1);
} else if (bitcount > 41 - 5 - 4) {
// wind dir (invert)
tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3);
} else if (bitcount > 41 - 5 - 4 - 12) {
// windspeed (invert)
tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11);
} else if (bitcount > 41 - 5 - 4 - 12 - 4) {
// checksum (invert)
tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3);
} else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) {
// wind dir
tx2x_se = tx2x_se >> 1 | (dpin << 3);
} else {
// windspeed
tx2x_sf = tx2x_sf >> 1 | (dpin << 11);
}
#endif
delayMicroseconds(TX2X_BIT_TIME);
}
for (int32_t bitcount = 41; bitcount > 0; bitcount--) {
uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK]));
if (bitcount > 41 - 5) {
// start, inverted
tx20_sa = (tx20_sa << 1) | (dpin ^ 1);
} else if (bitcount > 41 - 5 - 4) {
// wind dir, inverted
tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3);
} else if (bitcount > 41 - 5 - 4 - 12) {
// windspeed, inverted
tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11);
} else if (bitcount > 41 - 5 - 4 - 12 - 4) {
// checksum, inverted
tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3);
} else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) {
// wind dir
tx20_se = tx20_se >> 1 | (dpin << 3);
} else {
// windspeed
tx20_sf = tx20_sf >> 1 | (dpin << 11);
uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf));
chk &= 0xf;
#ifdef USE_TX23_WIND_SENSOR
// check checksum, non-inverted with inverted values and max. speed
if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) {
tx2x_available = true;
}
#else
if ((chk == tx2x_sd) && (tx2x_sc < 511)) { // if checksum seems to be ok and wind speed below 51.1 m/s
tx2x_available = true;
}
#endif
#ifdef USE_TX23_WIND_SENSOR
}
delayMicroseconds(TX20_BIT_TIME);
tx23_stage++;
}
#endif
uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf));
chk &= 0xf;
if ((chk == tx20_sd) && (tx20_sc < 400)) { // if checksum seems to be ok and wind speed below 40 m/s
tx20_available = true;
}
/*
if ((tx20_sb == tx20_se) && (tx20_sc == tx20_sf) && (tx20_sc < 400)) {
tx20_available = true;
}
*/
// Must clear this bit in the interrupt register,
// it gets set even when interrupts are disabled
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]);
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]);
}
void Tx20Read(void)
void Tx2xReset(void)
{
if (!(uptime % TX20_RESET_VALUES)) {
tx20_count = 0;
tx20_wind_sum = 0;
tx20_wind_speed_max = 0;
tx2x_count = 0;
tx2x_wind_sum = 0;
tx2x_wind_speed_max = 0;
}
void Tx2xRead(void)
{
#ifdef USE_TX23_WIND_SENSOR
// note: TX23 speed calculation is unstable when conversion starts
// less than 2 seconds after last request
if ((uptime % 3)==0) {
// TX23 start transmission by pulling down TxD line for at minimum 500ms
// so we pull TxD signal to low every 3 seconds
tx23_stage = 0;
pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT);
digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW);
} else if ((uptime % 3)==1) {
// after pulling down TxD every 3 second we pull-up TxD every 3+1 seconds
// to trigger start transmission
tx23_stage = 1; // first rising signal is invalid
pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP);
}
else if (tx20_available) {
tx20_wind_speed_kmh = float(tx20_sc) * 0.36;
if (tx20_wind_speed_kmh > tx20_wind_speed_max) {
tx20_wind_speed_max = tx20_wind_speed_kmh;
#endif
if (0==Settings.tele_period && !(uptime % TX2X_RESET_VALUES)) {
Tx2xReset();
}
else if (tx2x_available) {
// Wind speed spec: 0 to 180 km/h (0 to 50 m/s)
tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36;
if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) {
tx2x_wind_speed_max = tx2x_wind_speed_kmh;
}
tx20_count++;
tx20_wind_sum += tx20_wind_speed_kmh;
tx20_wind_speed_avg = tx20_wind_sum / tx20_count;
tx20_wind_direction = tx20_sb;
tx2x_count++;
tx2x_wind_sum += tx2x_wind_speed_kmh;
tx2x_wind_speed_avg = tx2x_wind_sum / tx2x_count;
tx2x_wind_direction = tx2x_sb;
}
}
void Tx20Init(void) {
pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT);
attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING);
void Tx2xInit(void)
{
#ifdef USE_TX23_WIND_SENSOR
tx23_stage = 0;
pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT);
digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW);
#else
pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT);
#endif
attachInterrupt(pin[GPIO_TX2X_TXD_BLACK], TX2xStartRead, RISING);
}
void Tx20Show(bool json)
void Tx2xShow(bool json)
{
char wind_speed_string[33];
dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string);
dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string);
char wind_speed_max_string[33];
dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string);
dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string);
char wind_speed_avg_string[33];
dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string);
dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string);
char wind_direction_string[4];
GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions);
GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections);
char wind_direction_degree[33];
dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree);
if (json) {
ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"),
wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string);
ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"),
wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree);
Tx2xReset();
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string);
WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree);
#endif // USE_WEBSERVER
}
}
@ -203,20 +304,20 @@ bool Xsns35(uint8_t function)
{
bool result = false;
if (pin[GPIO_TX20_TXD_BLACK] < 99) {
if (pin[GPIO_TX2X_TXD_BLACK] < 99) {
switch (function) {
case FUNC_INIT:
Tx20Init();
Tx2xInit();
break;
case FUNC_EVERY_SECOND:
Tx20Read();
Tx2xRead();
break;
case FUNC_JSON_APPEND:
Tx20Show(1);
Tx2xShow(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
Tx20Show(0);
Tx2xShow(0);
break;
#endif // USE_WEBSERVER
}
@ -224,4 +325,4 @@ bool Xsns35(uint8_t function)
return result;
}
#endif // USE_TX20_WIND_SENSOR
#endif // USE_TX20_WIND_SENSOR || USE_TX23_WIND_SENSOR

190
tasmota/xsns_63_aht1x.ino Normal file
View File

@ -0,0 +1,190 @@
/*
xsns_63_AHT1x.ino - AHT10 I2C temperature and humidity sensor support for Tasmota
Copyright (C) 2020 Martin Wagner
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_AHT1x
/*********************************************************************************************\
* AHT10/15 - Temperature and Humidity
*
* I2C Address: 0x38
\*********************************************************************************************/
#define XSNS_63 63
#define XI2C_43 43 // See I2CDEVICES.md
#define AHT10_ADDR 0x38
uint8_t eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00};
uint8_t eSensorNormalCmd[3] = {0xA8, 0x00, 0x00};
uint8_t eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00};
uint8_t eSensorResetCmd = 0xBA;
struct AHT10 {
float humidity = NAN;
float temperature = NAN;
uint8_t valid = 0;
uint8_t count = 0;
char name[6] = "AHT1x";
} AHT10;
bool AHT10Read(void)
{
if (AHT10.valid) { AHT10.valid--; }
uint8_t data[6];
Wire.beginTransmission(AHT10_ADDR);
Wire.write(eSensorMeasureCmd, 3);
Wire.endTransmission();
delay(100);
Wire.requestFrom(AHT10_ADDR, 6);
for (uint32_t i = 0; Wire.available() > 0; i++) {
data[i] = Wire.read();
}
uint32_t result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4;
uint32_t result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
float humidity = result_h * 100 / 1048576;
float temperature = ((200 * result_t) / 1048576) - 50;
if (isnan(temperature) || isnan(humidity)) { return false; }
AHT10.humidity = ConvertHumidity(humidity);
AHT10.temperature = ConvertTemp(temperature);
AHT10.valid = SENSOR_MAX_MISS;
return true;
}
/********************************************************************************************/
bool AHT10Init(void)
{
Wire.begin(AHT10_ADDR);
Wire.beginTransmission(AHT10_ADDR);
Wire.write(eSensorCalibrateCmd, 3);
Wire.endTransmission();
delay(500); // ?!?! too long
return (0x08 == (AHT10ReadStatus() & 0x68));
}
uint8_t AHT10ReadStatus(void)
{
Wire.requestFrom(AHT10_ADDR, 1);
uint8_t result = Wire.read();
return result;
}
void AHT10Reset(void)
{
Wire.beginTransmission(AHT10_ADDR);
Wire.write(eSensorResetCmd);
Wire.endTransmission();
delay(20);
}
/********************************************************************************************/
void AHT10Detect(void)
{
if (I2cActive(AHT10_ADDR)) { return; }
if (AHT10Init()) {
I2cSetActiveFound(AHT10_ADDR, AHT10.name);
AHT10.count = 1;
}
}
void AHT10EverySecond(void)
{
if (uptime &1) {
// AHT10: 55mS
if (!AHT10Read()) {
AddLogMissed(AHT10.name, AHT10.valid);
}
}
}
void AHT10Show(bool json)
{
if (AHT10.valid) {
char temperature[33];
dtostrfd(AHT10.temperature, Settings.flag2.temperature_resolution, temperature);
char humidity[33];
dtostrfd(AHT10.humidity, Settings.flag2.humidity_resolution, humidity);
if (json) {
ResponseAppend_P(JSON_SNS_TEMPHUM, AHT10.name, 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, AHT10.temperature);
KnxSensor(KNX_HUMIDITY, AHT10.humidity);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_TEMP, AHT10.name, temperature, TempUnit());
WSContentSend_PD(HTTP_SNS_HUM, AHT10.name, humidity);
#endif // USE_WEBSERVER
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns63(uint8_t function)
{
if (!I2cEnabled(XI2C_43)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
AHT10Detect();
}
else if (AHT10.count) {
switch (function) {
case FUNC_EVERY_SECOND:
AHT10EverySecond();
break;
case FUNC_JSON_APPEND:
AHT10Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
AHT10Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_AHT10
#endif // USE_I2C

View File

@ -193,7 +193,7 @@ a_features = [[
"USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591",
"USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG",
"USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR",
"","","",""
"USE_AHT1x","","",""
],[
"","","","",
"","","","",
@ -236,7 +236,7 @@ else:
obj = json.load(fp)
def StartDecode():
print ("\n*** decode-status.py v20200210 by Theo Arends and Jacek Ziolkowski ***")
print ("\n*** decode-status.py v20200220 by Theo Arends and Jacek Ziolkowski ***")
# print("Decoding\n{}".format(obj))