diff --git a/BUILDS.md b/BUILDS.md index d21fd9f15..3b311a6eb 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -106,6 +106,7 @@ | USE_PAJ7620 | - | - | - | - | - | - | - | | USE_PCF8574 | - | - | - | - | - | - | - | | USE_HIH6 | - | - | - | - | x | - | - | +| USE_DHT12 | - | - | - | - | x | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | diff --git a/I2CDEVICES.md b/I2CDEVICES.md index 73f4a9c6b..6d0de4e1a 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -61,4 +61,5 @@ Index | Define | Driver | Device | Address(es) | Description 38 | USE_DISPLAY_ILI9488 | xdsp_08 | FT6236 | 0x38 | Touch panel controller 39 | USE_DISPLAY_RA8876 | xdsp_10 | FT5316 | 0x38 | Touch panel controller 40 | USE_TSL2591 | xsns_57 | TLS2591 | 0x29 | Light intensity sensor + 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b11d0ce44..5d7ec4613 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -58,6 +58,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) +- Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) - Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188) - Add rule var ``%topic%`` by Adrian Scillato (#5522) @@ -74,3 +75,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode - Add fallback support from version 8.x - Add restriction if fallback firmware is incompatible with settings resulting in unreachable device +- Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 622645aa8..5106122a7 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -10,10 +10,12 @@ - Change some more Settings locations freeing up space for future single char allowing variable length text - Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE +- Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor - Add fallback support from version 8.x - Add restriction if fallback firmware is incompatible with settings resulting in unreachable device +- Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp ### 7.1.2.5 20191213 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 04318d9c8..73a965d30 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -418,6 +418,7 @@ // #define USE_PAJ7620 // [I2cDriver34] Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) // #define USE_PCF8574 // [I2cDriver2] Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) // #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_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index be4c8f6a4..31428d03b 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -489,7 +489,9 @@ void GetFeatures(void) #ifdef USE_TSL2591 feature5 |= 0x00080000; #endif -// feature5 |= 0x00100000; +#ifdef USE_DHT12 + feature5 |= 0x00100000; +#endif // feature5 |= 0x00200000; // feature5 |= 0x00400000; // feature5 |= 0x00800000; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 75f35cd92..b095fdbf2 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -135,6 +135,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) //#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) #define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) +#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code) //#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) //#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e13bba771..8392bebad 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -27,11 +27,13 @@ #define D_SHUTTER "SHUTTER" const uint16_t MOTOR_STOP_TIME = 500; // in mS +const uint8_t steps_per_second = 20; // FUNC_EVERY_50_MSECOND uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; uint16_t messwerte[5] = {30,50,70,90,100}; +uint16_t last_execute_step; -enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE }; +enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" @@ -68,43 +70,51 @@ struct SHUTTER { uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. int16_t pwm_frequency; // frequency of PWN for stepper motors - uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency that can be used. depend on the motor and drivers + uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency for openig the shutter. depend on the motor and drivers + uint16_t max_close_pwm_frequency[MAX_SHUTTERS];// maximum of PWM frequency for closeing the shutter. depend on the motor and drivers uint8_t skip_relay_change; // avoid overrun at endstops + int32_t accelerator[MAX_SHUTTERS]; // speed of ramp-up, ramp down of shutter } Shutter; void ShutterRtc50mS(void) { for (uint32_t i = 0; i < shutters_present; i++) { Shutter.time[i]++; + if (Shutter.accelerator[i]) { + Shutter.pwm_frequency += Shutter.accelerator[i]; + Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency)); + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + } } } -int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) +int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t i) { - if (Settings.shutter_set50percent[index] != 50) { - return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; + if (Settings.shutter_set50percent[i] != 50) { + return percent <= 5 ? Settings.shuttercoeff[2][i] * percent : Settings.shuttercoeff[1][i] * percent + Settings.shuttercoeff[0][i]; } else { int32_t realpos; // check against DIV 0 for (uint8_t j=0 ; j < 5 ; j++) { - if (Settings.shuttercoeff[j][index] == 0) { + if (Settings.shuttercoeff[j][i] == 0) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); for (uint8_t k=0 ; k < 5 ; k++) { - Settings.shuttercoeff[k][index] = messwerte[k] * 1000 / messwerte[4]; + Settings.shuttercoeff[k][i] = messwerte[k] * 1000 / messwerte[4]; } } } - for (uint8_t i=0 ; i < 5 ; i++) { - if (percent*10 > Settings.shuttercoeff[i][index]) { - realpos = Shutter.open_max[index] * calibrate_pos[i+1] / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]); + for (uint8_t l=0 ; l < 5 ; l++) { + if (percent*10 > Settings.shuttercoeff[l][i]) { + realpos = Shutter.open_max[i] * calibrate_pos[l+1] / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[l][i]); } else { - if ( i == 0) { - realpos = percent * Shutter.open_max[index] * calibrate_pos[i+1] / Settings.shuttercoeff[i][index] / 10; + if ( l == 0) { + realpos = percent * Shutter.open_max[i] * calibrate_pos[l+1] / Settings.shuttercoeff[l][i] / 10; } else { - //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[i+1] - calibrate_pos[i]), (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); - realpos += ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; + //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l]) / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[l+1] - calibrate_pos[l]), (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l])); + realpos += ( percent*10 - Settings.shuttercoeff[l-1][i] ) * Shutter.open_max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][i]) / 100; } break; } @@ -113,25 +123,25 @@ int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) } } -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index) +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t i) { - if (Settings.shutter_set50percent[index] != 50) { - return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; + if (Settings.shutter_set50percent[i] != 50) { + return Settings.shuttercoeff[2][i] * 5 > realpos ? realpos / Settings.shuttercoeff[2][i] : (realpos-Settings.shuttercoeff[0][i]) / Settings.shuttercoeff[1][i]; } else { int16_t realpercent; - for (uint8_t i=0 ; i < 5 ; i++) { - if (realpos > Shutter.open_max[index] * calibrate_pos[i+1] / 100) { - realpercent = Settings.shuttercoeff[i][index] /10; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[index] * calibrate_pos[i+1] / 100); + for (uint8_t j=0 ; j < 5 ; j++) { + if (realpos > Shutter.open_max[i] * calibrate_pos[j+1] / 100) { + realpercent = Settings.shuttercoeff[j][i] /10; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[i] * calibrate_pos[i+1] / 100); } else { if ( i == 0) { - realpercent = ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * Settings.shuttercoeff[i][index] / calibrate_pos[i+1] / Shutter.open_max[index]; + realpercent = ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * Settings.shuttercoeff[j][i] / calibrate_pos[j+1] / Shutter.open_max[i]; } else { - //uint16_t addon = ( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[index]; - //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[index]/100, (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); - realpercent += ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i]) / Shutter.open_max[index] ; + //uint16_t addon = ( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][i] - Settings.shuttercoeff[i-1][i]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[i]; + //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i]) / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[i]/100, (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i])); + realpercent += ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][i] - Settings.shuttercoeff[j-1][i]) / (calibrate_pos[j+1] - calibrate_pos[j]) / Shutter.open_max[i] ; } break; } @@ -148,12 +158,11 @@ void ShutterInit(void) Shutter.old_power = power; bool relay_in_interlock = false; + // if shutter 4 is unused + if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) { + Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency; + } for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - // upgrade to 0.1sec calculation base. - if ( Settings.shutter_accuracy == 0) { - Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10; - Settings.shutter_opentime[i] = Settings.shutter_opentime[i] * 10; - } // set startrelay to 1 on first init, but only to shutter 1. 90% usecase Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); if (Settings.shutter_startrelay[i] && Settings.shutter_startrelay[i] <9) { @@ -177,7 +186,8 @@ void ShutterInit(void) } } else { Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; - if (pin[GPIO_PWM1+i] < 99) { + if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i]) { + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); analogWrite(pin[GPIO_PWM1+i], 50); @@ -195,6 +205,8 @@ void ShutterInit(void) // Update Calculation 20 because time interval is 0.05 sec Shutter.open_max[i] = 200 * Shutter.open_time[i]; Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; + Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i]/Shutter.close_time[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]); // calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part if (Settings.shutter_set50percent[i] != 50) { @@ -222,43 +234,54 @@ void ShutterInit(void) // terminate loop at first INVALID shutter. break; } - if (shutters_present < 4) { - Shutter.max_pwm_frequency = Settings.shuttercoeff[4][4] > 0 ? Settings.shuttercoeff[4][4] : Shutter.max_pwm_frequency; - } + Settings.shutter_accuracy = 1; } } void ShutterUpdatePosition(void) { + char scommand[CMDSZ]; char stopic[TOPSZ]; char stemp2[10]; for (uint32_t i = 0; i < shutters_present; i++) { if (Shutter.direction[i] != 0) { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { + int32_t stop_position_delta = 20; + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { // Calculate position with counter. Much more accurate and no need for motordelay workaround // adding some steps to stop early - Shutter.real_position[i] = Shutter.direction[i] * 20 + ShutterCounterBasedPosition(i);; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + + int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; + int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec; + int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ; + + int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; + stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); + //int32_t act_freq_change = max_freq_change_per_sec/20; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, + Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); + + if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { + + Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); + } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) { + Shutter.accelerator[i] = 0; + } } else { Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); } - - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99) { - uint16_t freq_change = Shutter.max_pwm_frequency/(Shutter.motordelay[i]+1); - // ramp up phase. calculate frequency - Shutter.pwm_frequency = tmin(freq_change * Shutter.time[i],Shutter.max_pwm_frequency); - // ramp down at the end of the movement time will not be exactly motordelay - Shutter.pwm_frequency = tmax(tmin(freq_change * (Shutter.target_position[i]-Shutter.real_position[i])*Shutter.direction[i]/30, Shutter.pwm_frequency),10); - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 50); - } - if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) { + if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) { // calculate relay number responsible for current movement. //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]); uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; + int16_t missing_steps; switch (Shutter.mode) { case SHT_PULSE_OPEN__PULSE_CLOSE: @@ -269,29 +292,34 @@ void ShutterUpdatePosition(void) last_source = SRC_SHUTTER; } break; - case SHT_OFF_ON__OPEN_CLOSE: - // This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction - // Only allow PWM microstepping if PWM and COUNTER are defined. - // see wiki to connect PWM and COUNTER - if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { - int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; - //prepare for stop PWM - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { - delay(1); - } - analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); - + case SHT_OFF_ON__OPEN_CLOSE_STEPPER: + missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; + //prepare for stop PWM + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { + delay(1); } + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); } break; + case SHT_OFF_ON__OPEN_CLOSE: + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; case SHT_OFF_OPEN__OFF_CLOSE: // avoid switching OFF a relay already OFF if ((1 << (cur_relay-1)) & power) { @@ -302,7 +330,7 @@ void ShutterUpdatePosition(void) } Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); - dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); + dtostrfd((float)Shutter.time[i] / steps_per_second, 1, stemp2); AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); Shutter.start_position[i] = Shutter.real_position[i]; @@ -332,50 +360,51 @@ bool ShutterState(uint8_t device) (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); } -void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos) +void ShutterStartInit(uint8_t i, int8_t direction, int32_t target_pos) { - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index], Shutter.real_position[index] / Shutter.close_velocity[index], 2+Shutter.motordelay[index]); - if ( ( direction == 1 && (Shutter.open_max[index] - Shutter.real_position[index]) / 100 <= 2 ) - || ( direction == -1 && Shutter.real_position[index] / Shutter.close_velocity[index] <= 2)) { + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[i] - Shutter.real_position[i]) / Shutter.close_velocity[i], Shutter.real_position[i] / Shutter.close_velocity[i], 2+Shutter.motordelay[i]); + if ( ( direction == 1 && (Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2 ) + || ( direction == -1 && Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) { Shutter.skip_relay_change = 1 ; } else { - if (pin[GPIO_PWM1+index] < 99) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 0); + analogWrite(pin[GPIO_PWM1+i], 0); // can be operated without counter, but then not that acurate. - if (pin[GPIO_CNTR1+index] < 99) { - RtcSettings.pulse_counter[index] = 0; + if (pin[GPIO_CNTR1+i] < 99) { + RtcSettings.pulse_counter[i] = 0; } + Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); } - Shutter.target_position[index] = target_pos; - Shutter.start_position[index] = Shutter.real_position[index]; - Shutter.time[index] = 0; + Shutter.target_position[i] = target_pos; + Shutter.start_position[i] = Shutter.real_position[i]; + Shutter.time[i] = 0; Shutter.skip_relay_change = 0; - Shutter.direction[index] = direction; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[index], Shutter.start_position[index] ,RtcSettings.pulse_counter[index],Shutter.max_pwm_frequency , Shutter.direction[index] ,Shutter.max_pwm_frequency ); + Shutter.direction[i] = direction; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); } - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), i, Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i]); } -void ShutterWaitForMotorStop(uint8_t index) +void ShutterWaitForMotorStop(uint8_t i) { AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { - if (pin[GPIO_PWM1+index] < 99 && pin[GPIO_CNTR1+index] < 99 ) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + if ( Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency); - while (Shutter.pwm_frequency > 100) { - Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-(Shutter.max_pwm_frequency/(Shutter.motordelay[index]+1)) , 0); + while (Shutter.pwm_frequency > 0) { + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 50); + analogWrite(pin[GPIO_PWM1+i], 50); delay(50); } - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 0); - Shutter.real_position[index] = ShutterCounterBasedPosition(index); + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); } else { - ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); delay(MOTOR_STOP_TIME); } } else { @@ -391,7 +420,7 @@ void ShutterReportPosition(void) if (Shutter.direction[i] != 0) { char stemp2[10]; uint8_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); - dtostrfd((float)Shutter.time[i] / 20, 2, stemp2); + dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); shutter_moving = 1; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); @@ -430,7 +459,7 @@ void ShutterRelayChanged(void) //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); if (manual_relays_changed) { //Shutter.skip_relay_change = true; - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { ShutterWaitForMotorStop(i); switch (powerstate_local) { case 1: @@ -478,7 +507,7 @@ void ShutterSetPosition(uint8_t device, uint8_t position) void CmndShutterOpen(void) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i); if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { XdrvMailbox.index = XdrvMailbox.payload; } @@ -489,7 +518,7 @@ void CmndShutterOpen(void) void CmndShutterClose(void) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i); if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { XdrvMailbox.index = XdrvMailbox.payload; } @@ -505,14 +534,14 @@ void CmndShutterStop(void) if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { XdrvMailbox.index = XdrvMailbox.payload; } - uint32_t index = XdrvMailbox.index -1; - if (Shutter.direction[index] != 0) { + uint32_t i = XdrvMailbox.index -1; + if (Shutter.direction[i] != 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[index]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); // set stop position 10 steps ahead (0.5sec to allow normal stop) - int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index])); - XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index); - //XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index]; + int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); + //XdrvMailbox.payload = Settings.shuttercoeff[2][i] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][i] : (temp_realpos-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; last_source = SRC_WEBGUI; CmndShutterPosition(); } else { @@ -524,7 +553,7 @@ void CmndShutterStop(void) void CmndShutterPosition(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index -1; + uint32_t index = XdrvMailbox.index-1; //limit the payload AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); @@ -542,6 +571,7 @@ void CmndShutterPosition(void) if (XdrvMailbox.payload != -99) { //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + Shutter.accelerator[index] = Shutter.max_pwm_frequency / (Shutter.motordelay[index]>0 ? Shutter.motordelay[index] : 1); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } @@ -561,7 +591,7 @@ void CmndShutterPosition(void) } } if (Shutter.direction[index] != new_shutterdirection ) { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); ShutterWaitForMotorStop(index); ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); @@ -617,11 +647,11 @@ void CmndShutterMotorDelay(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if (XdrvMailbox.data_len > 0) { - Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(20 * CharToFloat(XdrvMailbox.data)); + Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); ShutterInit(); } char time_chr[10]; - dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / 20, 2, time_chr); + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); ResponseCmndIdxChar(time_chr); } } @@ -660,8 +690,9 @@ void CmndShutterFrequency(void) if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { Shutter.max_pwm_frequency = XdrvMailbox.payload; if (shutters_present < 4) { - Settings.shuttercoeff[4][4] = Shutter.max_pwm_frequency; + Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency; } + ShutterInit(); ResponseCmndNumber(XdrvMailbox.payload); // ???? } else { ResponseCmndNumber(Shutter.max_pwm_frequency); @@ -707,8 +738,8 @@ void CmndShutterCalibration(void) // ???? messwerte[i] = field; } for (i=0 ; i < 5 ; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index-1] = messwerte[i] * 1000 / messwerte[4]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index-1,Settings.shuttercoeff[i][XdrvMailbox.index-1], messwerte[i]); + Settings.shuttercoeff[i][XdrvMailbox.index -1] = messwerte[i] * 1000 / messwerte[4]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); } ShutterInit(); ResponseCmndIdxChar(XdrvMailbox.data); diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index c830a092e..f0a8de685 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -103,7 +103,7 @@ void DeepSleepPrepare(void) // if more then 10% timeslip = 0 == non valid wakeup; maybe manual timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; if (timeslip) { - RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / (Settings.deepsleep - (millis() / 1000)); + RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); // Avoid crazy numbers. Again maximum 10% deviation. RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); RtcSettings.nextwakeup += Settings.deepsleep; diff --git a/tasmota/xsns_58_dht12.ino b/tasmota/xsns_58_dht12.ino new file mode 100644 index 000000000..1c60329b8 --- /dev/null +++ b/tasmota/xsns_58_dht12.ino @@ -0,0 +1,140 @@ +/* + xsns_58_dht12.ino - DHT12 I2C temperature and humidity sensor support for Tasmota + + Copyright (C) 2019 Stefan Oskamp 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 . +*/ + +#ifdef USE_I2C +#ifdef USE_DHT12 +/*********************************************************************************************\ + * DHT12 - Temperature and Humidity + * + * I2C Address: 0x5C +\*********************************************************************************************/ + +#define XSNS_58 58 +#define XI2C_41 41 // See I2CDEVICES.md + +#define DHT12_ADDR (uint8_t) 0x5C + +char dht12_name[] = "DHT12-0x00"; +uint8_t dht12_count = 0; +float dht12_temperature = NAN; +float dht12_humidity = NAN; + +bool Dht12Read(void) +{ + Wire.beginTransmission(DHT12_ADDR); + Wire.write(0); + if (Wire.endTransmission() != 0) { + return false; + } + delay(50); + Wire.requestFrom(DHT12_ADDR, (uint8_t) 5); + delay(5); + uint8_t humidity = Wire.read(); + uint8_t humidityTenth = Wire.read(); + uint8_t temp = Wire.read(); + uint8_t tempTenth = Wire.read(); + uint8_t checksum = Wire.read(); + dht12_humidity = (float) humidity + (float) humidityTenth/(float) 10.0; + dht12_temperature = (float) temp + (float) tempTenth/(float) 10.0; + return (!isnan(dht12_temperature) && !isnan(dht12_humidity)); +} + +void Dht12Detect(void) +{ + if (Dht12Read()) { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, dht12_name, DHT12_ADDR); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(dht12_name, sizeof(dht12_name), PSTR("%s%c0x%02X"), "DHT12", IndexSeparator(), DHT12_ADDR); + dht12_count = 1; + } +} + +void Dht12Show(bool json) +{ + if (dht12_count > 0) + { + char temperature[33]; + dtostrfd(dht12_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(dht12_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) + { + ResponseAppend_P(JSON_SNS_TEMPHUM, dht12_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, dht12_temperature); + KnxSensor(KNX_HUMIDITY, dht12_humidity); + } +#endif // USE_KNX + +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_TEMP, dht12_name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, dht12_name, humidity); +#endif // USE_WEBSERVER + } + } +} + + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns58(uint8_t function) +{ + if (!I2cEnabled(XI2C_41)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Dht12Detect(); + } + else if (dht12_count > 0) { + switch (function) { + case FUNC_EVERY_SECOND: + Dht12Read(); + break; + case FUNC_JSON_APPEND: + Dht12Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Dht12Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_DHT12 +#endif // USE_I2C diff --git a/tools/decode-status.py b/tools/decode-status.py index be79cf921..e6751ae92 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -187,7 +187,7 @@ a_features = [[ "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", - "","","","", + "USE_DHT12","","","", "","","","", "","","","" ]]