mirror of https://github.com/arendst/Tasmota.git
Merge pull request #8283 from malbinola/new-windmeter-sensor
New windmeter sensor
This commit is contained in:
commit
40d71e7ad9
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL - RX"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL - TX"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -674,6 +674,7 @@
|
|||
#define D_SENSOR_HRXL_RX "HRXL Rx"
|
||||
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
|
||||
#define D_SENSOR_AS3935 "AS3935"
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
|
||||
#define D_GPIO_WEBCAM_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
|
|
@ -666,7 +666,10 @@
|
|||
#define USE_TASMOTA_SLAVE_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
|
||||
#define USE_TASMOTA_SLAVE_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini
|
||||
|
||||
//#define USE_WINDMETER // Add support for analog anemometer
|
||||
|
||||
//#define USE_OPENTHERM // Use OpenTherm implementation
|
||||
|
||||
// -- End of general directives -------------------
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
|
|
@ -533,8 +533,13 @@ struct {
|
|||
uint8_t zb_free_byte; // F33
|
||||
uint16_t pms_wake_interval; // F34
|
||||
uint8_t config_version; // F36
|
||||
uint8_t windmeter_pulses_x_rot; // F37
|
||||
uint16_t windmeter_radius; // F38
|
||||
uint16_t windmeter_pulse_debounce; // F3A
|
||||
int16_t windmeter_speed_factor; // F3C
|
||||
uint8_t windmeter_tele_pchange; // F3E
|
||||
|
||||
uint8_t free_f37[129]; // F37 - Decrement if adding new Setting variables just above and below
|
||||
uint8_t free_f3f[121]; // F3F - Decrement if adding new Setting variables just above and below
|
||||
|
||||
// Only 32 bit boundary variables below
|
||||
uint16_t pulse_counter_debounce_low; // FB8
|
||||
|
|
|
@ -555,10 +555,12 @@ void GetFeatures(void)
|
|||
feature6 |= 0x00000080; // xdrv_38_ping.ino
|
||||
#endif
|
||||
#ifdef USE_THERMOSTAT
|
||||
feature6 |= 0x00000200; // xsns_68_opentherm.ino
|
||||
feature6 |= 0x00000100; // xsns_68_opentherm.ino
|
||||
#endif
|
||||
// feature6 |= 0x00000100;
|
||||
// feature6 |= 0x00000200;
|
||||
#ifdef USE_WINDMETER
|
||||
feature6 |= 0x00000200; // xsns_69_windmeter.ino
|
||||
#endif
|
||||
|
||||
// feature6 |= 0x00000400;
|
||||
// feature6 |= 0x00000800;
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@
|
|||
#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code)
|
||||
//#define USE_A4988_STEPPER // Add support for A4988/DRV8825 stepper-motor-driver-circuit (+10k5 code)
|
||||
//#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
|
||||
//#define USE_WINDMETER // Add support for analog anemometer
|
||||
#undef DEBUG_THEO // Disable debug code
|
||||
#undef USE_DEBUG_DRIVER // Disable debug code
|
||||
#endif // FIRMWARE_SENSORS
|
||||
|
|
|
@ -232,6 +232,7 @@ enum UserSelectablePins {
|
|||
GPIO_PMS5003_TX, // Plantower PMS5003 Serial interface
|
||||
GPIO_BOILER_OT_RX, // OpenTherm Boiler RX pin
|
||||
GPIO_BOILER_OT_TX, // OpenTherm Boiler TX pin
|
||||
GPIO_WINDMETER_SPEED, // WindMeter speed counter pin
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality
|
||||
|
@ -320,7 +321,8 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_HRXL_RX "|"
|
||||
D_SENSOR_ELECTRIQ_MOODL "|"
|
||||
D_SENSOR_AS3935 "|" D_SENSOR_PMS5003_TX "|"
|
||||
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX
|
||||
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
|
||||
D_SENSOR_WINDMETER_SPEED
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
|
@ -594,6 +596,9 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||
#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR)
|
||||
GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin
|
||||
#endif
|
||||
#ifdef USE_WINDMETER
|
||||
GPIO_WINDMETER_SPEED,
|
||||
#endif
|
||||
#ifdef USE_MP3_PLAYER
|
||||
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
xsns_68_windmeter.ino - Analog wind sensor support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Matteo Albinola
|
||||
(inspired by great works of Thomas Eckerstorfer, Norbert Richter, Maarten Damen 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
|
||||
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_WINDMETER
|
||||
/*********************************************************************************************\
|
||||
* WindMeter sensor (speed)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_68 68
|
||||
|
||||
#define D_WINDMETER_NAME "WindMeter"
|
||||
|
||||
#define WINDMETER_DEF_RADIUS 61 // Radius in millimeters (calculated by measuring the distance from the centre to the edge of one of the cups)
|
||||
#define WINDMETER_DEF_PULSES_X_ROT 1 // Number of pulses for a complete rotation
|
||||
#define WINDMETER_DEF_PULSE_DEBOUNCE 10 // Pulse counter debounce time (milliseconds)
|
||||
#define WINDMETER_DEF_COMP_FACTOR 1.18 // Compensation factor
|
||||
#define WINDMETER_DEF_TELE_PCHANGE 255 // Minimum percentage change between current and last reported speed in order to trigger a new tele message (0...100, 255 means off)
|
||||
#define WINDMETER_WEIGHT_AVG_SAMPLE 150 // No of samples to take
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
#define D_WINDMETER_WIND_AVG "∅"
|
||||
#define D_WINDMETER_WIND_ANGLE "∠"
|
||||
#define D_WINDMETER_WIND_DEGREE "°"
|
||||
const char HTTP_SNS_WINDMETER[] PROGMEM =
|
||||
"{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED "{m}%s %s{e}"
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
"{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED " " D_WINDMETER_WIND_AVG "{m}%s %s{e}"
|
||||
"{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s %s{e}"
|
||||
"{s}" D_WINDMETER_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s %s{e}"
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
// "{s}WindMeter " D_TX20_WIND_DIRECTION "{m}%s %s" D_WINDMETER_WIND_DEGREE "{e}"
|
||||
//#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
// "{s}WindMeter " D_TX20_WIND_DIRECTION " " D_WINDMETER_WIND_AVG "{m}%s %s" D_WINDMETER_WIND_DEGREE "{e}"
|
||||
// "{s}WindMeter " D_TX20_WIND_DIRECTION " " D_WINDMETER_WIND_ANGLE "{m}%s" D_WINDMETER_WIND_DEGREE " (%s,%s)" D_WINDMETER_WIND_DEGREE;
|
||||
//#endif // USE_WINDMETER_NOSTATISTICS
|
||||
;
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
// float saves 48 byte
|
||||
float const windmeter_pi = 3.1415926535897932384626433; // Pi
|
||||
float const windmeter_2pi = windmeter_pi * 2;
|
||||
|
||||
struct WINDMETER {
|
||||
uint32_t counter_time;
|
||||
unsigned long counter = 0;
|
||||
//uint32_t speed_time;
|
||||
float speed = 0;
|
||||
float last_tele_speed = 0;
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
float speed_min = 0;
|
||||
float speed_max = 0;
|
||||
float speed_avg = 0;
|
||||
uint32_t samples_count = 0;
|
||||
uint32_t avg_samples_no;
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
} WindMeter;
|
||||
|
||||
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception
|
||||
void WindMeterUpdateSpeed(void) ICACHE_RAM_ATTR;
|
||||
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
|
||||
|
||||
void WindMeterUpdateSpeed(void)
|
||||
{
|
||||
uint32_t time = micros();
|
||||
uint32_t time_diff = time - WindMeter.counter_time;
|
||||
if (time_diff > Settings.windmeter_pulse_debounce * 1000) {
|
||||
WindMeter.counter_time = time;
|
||||
WindMeter.counter++;
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("WMET: Counter %d"), WindMeter.counter);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void WindMeterInit(void)
|
||||
{
|
||||
if (!Settings.flag2.speed_conversion) {
|
||||
Settings.flag2.speed_conversion = 2; // 0 = none, 1 = m/s, 2 = km/h, 3 = kn, 4 = mph, 5 = ft/s, 6 = yd/s
|
||||
}
|
||||
if (!Settings.windmeter_radius) {
|
||||
Settings.windmeter_radius = WINDMETER_DEF_RADIUS;
|
||||
}
|
||||
if (!Settings.windmeter_pulses_x_rot) {
|
||||
Settings.windmeter_pulses_x_rot = WINDMETER_DEF_PULSES_X_ROT;
|
||||
}
|
||||
if (!Settings.windmeter_pulse_debounce) {
|
||||
Settings.windmeter_pulse_debounce = WINDMETER_DEF_PULSE_DEBOUNCE;
|
||||
}
|
||||
if (!Settings.windmeter_speed_factor) {
|
||||
Settings.windmeter_speed_factor = (int16_t)(WINDMETER_DEF_COMP_FACTOR * 1000);
|
||||
}
|
||||
if (!Settings.windmeter_tele_pchange) {
|
||||
Settings.windmeter_tele_pchange = WINDMETER_DEF_TELE_PCHANGE;
|
||||
}
|
||||
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
WindMeterResetStatData();
|
||||
WindMeterCheckSampleCount();
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
|
||||
pinMode(Pin(GPIO_WINDMETER_SPEED), INPUT_PULLUP);
|
||||
attachInterrupt(Pin(GPIO_WINDMETER_SPEED), WindMeterUpdateSpeed, FALLING);
|
||||
}
|
||||
|
||||
void WindMeterEverySecond(void)
|
||||
{
|
||||
//uint32_t time = micros();
|
||||
//uint32_t delta_time = time - WindMeter.speed_time;
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("delta_time: %d"), delta_time);
|
||||
|
||||
// speed = ( (pulses / pulses_per_rotation) * (2 * pi * radius) ) / delta_time
|
||||
WindMeter.speed = ((WindMeter.counter / Settings.windmeter_pulses_x_rot) * (windmeter_2pi * ((float)Settings.windmeter_radius / 1000))) * ((float)Settings.windmeter_speed_factor / 1000);
|
||||
//WindMeter.speed = (((WindMeter.counter / Settings.windmeter_pulses_x_rot) * (windmeter_2pi * ((float)Settings.windmeter_radius / 1000))) / ((float)delta_time / 1000000)) * ((float)Settings.windmeter_speed_factor / 1000);
|
||||
WindMeter.counter = 0;
|
||||
//WindMeter.speed_time = time;
|
||||
|
||||
//char speed_string[FLOATSZ];
|
||||
//dtostrfd(WindMeter.speed, 2, speed_string);
|
||||
//char uspeed_string[FLOATSZ];
|
||||
//dtostrfd(ConvertSpeed(WindMeter.speed), 2, uspeed_string);
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("WMET: Speed %s [m/s] - %s [unit]"), speed_string, uspeed_string);
|
||||
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
if (WindMeter.speed < WindMeter.speed_min) {
|
||||
WindMeter.speed_min = WindMeter.speed;
|
||||
}
|
||||
if (WindMeter.speed > WindMeter.speed_max) {
|
||||
WindMeter.speed_max = WindMeter.speed;
|
||||
}
|
||||
|
||||
// exponentially weighted average is not quite as smooth as the arithmetic average
|
||||
// but close enough to the moving average and does not require the regular reset
|
||||
// of the divider with the associated jump in avg values after period is over
|
||||
if (WindMeter.samples_count <= WindMeter.avg_samples_no) {
|
||||
WindMeter.samples_count++;
|
||||
}
|
||||
WindMeter.speed_avg -= WindMeter.speed_avg / WindMeter.samples_count;
|
||||
WindMeter.speed_avg += float(WindMeter.speed) / WindMeter.samples_count;
|
||||
|
||||
WindMeterCheckSampleCount();
|
||||
if (0==Settings.tele_period) {
|
||||
WindMeterResetStatData();
|
||||
}
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
|
||||
if (WindMeterShouldTriggerTele()) {
|
||||
WindMeterTriggerTele();
|
||||
}
|
||||
}
|
||||
|
||||
bool WindMeterShouldTriggerTele()
|
||||
{
|
||||
if (Settings.windmeter_tele_pchange > 100) {
|
||||
return false;
|
||||
} else if (WindMeter.last_tele_speed == 0) {
|
||||
return WindMeter.speed > 0;
|
||||
} else {
|
||||
float perc_change = (WindMeter.speed / WindMeter.last_tele_speed) -1;
|
||||
return (perc_change * ((perc_change < 0) ? -100 : 100)) >= Settings.windmeter_tele_pchange;
|
||||
}
|
||||
}
|
||||
|
||||
void WindMeterResetStatData(void)
|
||||
{
|
||||
WindMeter.speed_min = WindMeter.speed;
|
||||
WindMeter.speed_max = WindMeter.speed;
|
||||
//WindMeter.direction_min = WindMeter.direction;
|
||||
//WindMeter.direction_max = WindMeter.direction;
|
||||
}
|
||||
|
||||
void WindMeterCheckSampleCount(void)
|
||||
{
|
||||
uint32_t prev_avg_samples_no = WindMeter.avg_samples_no;
|
||||
if (Settings.tele_period) {
|
||||
// number for avg samples = teleperiod value if set
|
||||
WindMeter.avg_samples_no = Settings.tele_period;
|
||||
} else {
|
||||
// otherwise use default number of samples for this driver
|
||||
WindMeter.avg_samples_no = WINDMETER_WEIGHT_AVG_SAMPLE;
|
||||
}
|
||||
if (prev_avg_samples_no != WindMeter.avg_samples_no) {
|
||||
WindMeter.speed_avg = WindMeter.speed;
|
||||
WindMeter.samples_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WindMeterShow(bool json)
|
||||
{
|
||||
char speed_string[FLOATSZ];
|
||||
dtostrfd(ConvertSpeed(WindMeter.speed), 2, speed_string);
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
char speed_min_string[FLOATSZ];
|
||||
dtostrfd(ConvertSpeed(WindMeter.speed_min), 2, speed_min_string);
|
||||
char speed_max_string[FLOATSZ];
|
||||
dtostrfd(ConvertSpeed(WindMeter.speed_max), 2, speed_max_string);
|
||||
char speed_avg_string[FLOATSZ];
|
||||
dtostrfd(ConvertSpeed(WindMeter.speed_avg), 2, speed_avg_string);
|
||||
//char direction_avg_string[FLOATSZ];
|
||||
//dtostrfd(WindMeter.direction_avg, 1, direction_avg_string);
|
||||
//char direction_avg_cardinal_string[4];
|
||||
//GetTextIndexed(direction_avg_cardinal_string, sizeof(direction_avg_cardinal_string), int((WindMeter.direction_avg/22.5f)+0.5f) % 16, kWindMeterDirections);
|
||||
//char direction_range_string[FLOATSZ];
|
||||
//dtostrfd(Tx2xNormalize(WindMeter.direction_max-WindMeter.direction_min)*22.5, 1, direction_range_string);
|
||||
//char direction_min_string[FLOATSZ];
|
||||
//dtostrfd(Tx2xNormalize(WindMeter.direction_min)*22.5, 1, direction_min_string);
|
||||
//char direction_max_string[FLOATSZ];
|
||||
//dtostrfd(Tx2xNormalize(WindMeter.direction_max)*22.5, 1, direction_max_string);
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
|
||||
if (json) {
|
||||
WindMeter.last_tele_speed = WindMeter.speed;
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
ResponseAppend_P(PSTR(",\"" D_WINDMETER_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s,\"Avg\":%s,\"AvgCard\":\"%s\",\"Min\":%s,\"Max\":%s,\"Range\":%s}}"),
|
||||
speed_string,
|
||||
speed_avg_string,
|
||||
speed_min_string,
|
||||
speed_max_string,
|
||||
"n/a", //direction_cardinal_string,
|
||||
"n/a", //direction_string,
|
||||
"n/a", //direction_avg_string,
|
||||
"n/a", //direction_avg_cardinal_string,
|
||||
"n/a", //direction_min_string,
|
||||
"n/a", //direction_max_string,
|
||||
"n/a" //direction_range_string
|
||||
);
|
||||
#else // USE_WINDMETER_NOSTATISTICS
|
||||
ResponseAppend_P(PSTR(",\"" D_WINDMETER_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s}}"),
|
||||
speed_string,
|
||||
"n/a", //wind_direction_cardinal_string,
|
||||
"n/a" //wind_direction_string
|
||||
);
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_WINDMETER,
|
||||
speed_string,
|
||||
SpeedUnit().c_str(),
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
speed_avg_string,
|
||||
SpeedUnit().c_str(),
|
||||
speed_min_string,
|
||||
SpeedUnit().c_str(),
|
||||
speed_max_string,
|
||||
SpeedUnit().c_str(),
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
"n/a", //wind_direction_cardinal_string,
|
||||
"n/a" //wind_direction_string
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
,"n/a", //,wind_direction_avg_cardinal_string,
|
||||
"n/a", //wind_direction_avg_string,
|
||||
"n/a", //wind_direction_range_string,
|
||||
"n/a", //wind_direction_min_string,
|
||||
"n/a" //wind_direction_max_string
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
void WindMeterTriggerTele(void)
|
||||
{
|
||||
mqtt_data[0] = '\0';
|
||||
if (MqttShowSensor()) {
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
#ifdef USE_RULES
|
||||
RulesTeleperiod(); // Allow rule based HA messages
|
||||
#endif // USE_RULES
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns68Cmnd(void)
|
||||
{
|
||||
bool serviced = true;
|
||||
bool show_parms = true;
|
||||
char sub_string[XdrvMailbox.data_len +1];
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 1:
|
||||
if (strstr(XdrvMailbox.data, ",") != nullptr) {
|
||||
Settings.windmeter_radius = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (strstr(XdrvMailbox.data, ",") != nullptr) {
|
||||
Settings.windmeter_pulses_x_rot = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (strstr(XdrvMailbox.data, ",") != nullptr) {
|
||||
Settings.windmeter_pulse_debounce = (uint16_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (strstr(XdrvMailbox.data, ",") != nullptr) {
|
||||
Settings.windmeter_speed_factor = (int16_t)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 1000);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (strstr(XdrvMailbox.data, ",") != nullptr) {
|
||||
Settings.windmeter_tele_pchange = (uint8_t)strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (show_parms) {
|
||||
char speed_factor_string[FLOATSZ];
|
||||
dtostrfd((float)Settings.windmeter_speed_factor / 1000, 3, speed_factor_string);
|
||||
char tele_pchange_string[4] = "off";
|
||||
if (Settings.windmeter_tele_pchange <= 100) {
|
||||
itoa(Settings.windmeter_tele_pchange, tele_pchange_string, 10);
|
||||
}
|
||||
Response_P(PSTR("{\"" D_WINDMETER_NAME "\":{\"Radius\":%d,\"PulsesPerRot\":%d,\"PulseDebounce\":%d,\"SpeedFactor\":%s,\"TeleTriggerMin%Change\":%s}}"),
|
||||
Settings.windmeter_radius, Settings.windmeter_pulses_x_rot, Settings.windmeter_pulse_debounce, speed_factor_string, tele_pchange_string);
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns68(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
if (PinUsed(GPIO_WINDMETER_SPEED)) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
WindMeterInit();
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
WindMeterEverySecond();
|
||||
break;
|
||||
#ifndef USE_WINDMETER_NOSTATISTICS
|
||||
case FUNC_AFTER_TELEPERIOD:
|
||||
WindMeterResetStatData();
|
||||
break;
|
||||
#endif // USE_WINDMETER_NOSTATISTICS
|
||||
case FUNC_JSON_APPEND:
|
||||
WindMeterShow(true);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_SENSOR:
|
||||
WindMeterShow(false);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_COMMAND_SENSOR:
|
||||
if (XSNS_68 == XdrvMailbox.index) {
|
||||
result = Xsns68Cmnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_WINDMETER
|
Loading…
Reference in New Issue