Index: com.c =================================================================== --- com.c (revision 363) +++ com.c (working copy) @@ -306,8 +306,13 @@ print_hexXX(CTL_integratorBlock); print_s_p(PSTR(" Ic: ")); //jr print_hexXX(CTL_interatorCredit); - print_s_p(PSTR(" Ie: ")); //jr - print_hexXX(CTL_creditExpiration); + print_s_p(PSTR(" bo: ")); //jr + print_hexXX(PID_boost_timeout); + print_s_p(PSTR(" Iac ")); //jr + print_hexXX(average_sumerr_count); + print_s_p(PSTR(" Isl ")); + print_hexXXXX(lastTempChangeSumError>>16); //jr + print_hexXXXX(lastTempChangeSumError); //jr #endif if (CTL_error!=0) { print_s_p(PSTR(" E:")); Index: controller.c =================================================================== --- controller.c (revision 363) +++ controller.c (working copy) @@ -58,7 +58,8 @@ int8_t CTL_interatorCredit; uint8_t CTL_creditExpiration; #if BOOST_CONTROLER_AFTER_CHANGE - uint8_t PID_boost_timeout=0; //boost timout in minutes + uint8_t PID_boost_timeout; //boost timout in minutes + uint8_t PID_boost; //boost value, either valve max or min #endif static uint16_t PID_update_timeout=AVERAGE_LEN+1; // timer to next PID controler action/first is 16 sec after statup int8_t PID_force_update=AVERAGE_LEN+1; // signed value, val<0 means disable force updates \todo rename @@ -67,6 +68,7 @@ static uint8_t pid_Controller(int16_t setPoint, int16_t processValue, uint8_t old_result, bool updateNow); uint8_t CTL_error=0; +uint8_t CTL_error_jr=0; #if (HW_WINDOW_DETECTION) static void CTL_window_detection(void) { @@ -175,12 +177,12 @@ } else { new_valve = pid_Controller(calc_temp(temp),temp_average,valveHistory[0],updateNow); } - CTL_temp_wanted_last=temp; + CTL_temp_wanted_last=temp; { int8_t i; #if BLOCK_INTEGRATOR_AFTER_VALVE_CHANGE if (valveHistory[0]!=new_valve) { - CTL_integratorBlock=DEFINE_INTEGRATOR_BLOCK; //block Integrator if valve moves + CTL_integratorBlock=CTL_INTEGRATOR_BLOCK; //block Integrator if valve moves } #endif @@ -245,7 +247,7 @@ // change menu_temp_rewoke=CTL_temp_auto; #if BOOST_CONTROLER_AFTER_CHANGE - PID_boost_timeout = 0; //jr disable boost + PID_boost_timeout = 0; //to disable boost change mode, then change setpoint and change back mode #endif CTL_mode_auto=!CTL_mode_auto; PID_force_update = 9; @@ -268,8 +270,8 @@ //! Summation of errors, used for integrate calculations int32_t sumError=0; static uint8_t lastErrorSign = 0; -static uint16_t lastAbsError; -static uint16_t last2AbsError; +static uint16_t lastAbsError = 0xFF; //set invalid +static uint16_t last2AbsError= 0xFE; //set invalid and different to lastAbsError uint8_t CTL_integratorBlock; //! The scalling_factor for PID constants #define scalling_factor (256) @@ -287,13 +289,14 @@ * \param processValue Measured value. */ -static uint16_t lastTempChangeErrorAbs; -static int32_t lastTempChangeSumError; +static uint16_t lastTempChangeErrorAbs=0xffff; +int32_t lastTempChangeSumError=0; +uint8_t average_sumerr_count=0; // counting # of averages, just for diagnosis purposes static void testIntegratorRevert(uint16_t absErr) { if ((absErr>=((lastTempChangeErrorAbs*3)>>2)) && (absErr > (I_ERR_TOLLERANCE_AROUND_0*2))) { - // if error could not be reduced to 3/4 and Error is larger than I_ERR_TOLLERANCE_AROUND_0°C + // if error could not be reduced to 3/4 and Error is larger than I_ERR_TOLLERANCE_AROUND_0*2 °C sumError=lastTempChangeSumError; } lastTempChangeErrorAbs = 0xffff; // function can be called more time but only first is valid @@ -318,16 +321,27 @@ if (updateNow) { CTL_interatorCredit=config.I_max_credit; CTL_creditExpiration=config.I_credit_expiration; - CTL_integratorBlock=DEFINE_INTEGRATOR_BLOCK; // do not allow update integrator immediately after temp change + CTL_integratorBlock=CTL_INTEGRATOR_BLOCK; // do not allow update integrator immediately after temp change testIntegratorRevert(lastAbsError); + if ((lastAbsError==last2AbsError) && (lastAbsError<(I_ERR_TOLLERANCE_AROUND_0*2))) {//stable error & error < 0,3°C) + average_sumerr_count++; //just for diagnosis, how often do we average + lastTempChangeSumError += (sumError-lastTempChangeSumError)/I_SUMERR_CHANGE_WEIGHT; + //imapct of SumErr changes on lastSummError, averaging for integrator revert + } lastTempChangeErrorAbs = absErr; - lastTempChangeSumError = sumError; + // lastTempChangeSumError = sumError; #if BOOST_CONTROLER_AFTER_CHANGE - if ((abs(setPoint-CTL_temp_wanted_last)>=config.temp_boost_setpoint_diff) // change of wanted temp large enough to start boost (0,5°C) - && (absErr>=(int16_t)config.temp_boost_error)) { // error large enough to start boost (0,3°C) - PID_boost_timeout = (error16 >= 0) ? config.temp_boost_time_heat : config.temp_boost_time_cool ; - PID_boost_timeout = (uint8_t)(MIN(255,abs(error16)/10*(int16_t)PID_boost_timeout/(int16_t)config.temp_boost_tempchange)); //boosttime=error/10(0,1°C)*time/tempchange - } + PID_boost_timeout = 0; + if (absErr>=(int16_t)config.temp_boost_error) { // error large enough to start boost (0,3°C) + if (error16 >= 0) { + PID_boost = config.valve_max; + PID_boost_timeout = config.temp_boost_time_heat; + } else { + PID_boost = config.valve_min; + PID_boost_timeout = config.temp_boost_time_cool; + } + PID_boost_timeout = (uint8_t)(MIN(255,abs(error16)/10*(int16_t)PID_boost_timeout/CTL_BOOST_TEMPCHANGE)); //boosttime=error/10(0,1°C)*time/CTL_BOOST_TEMPCHANGE(0,5°C) + } #endif } else { if (CTL_integratorBlock == 0) { @@ -337,10 +351,9 @@ CTL_interatorCredit=0; } if ((error16 >= 0) ? (old_result < config.valve_max) : (old_result > config.valve_min)) { - if (((lastErrorSign != ((uint8_t)(error16>>8)&0x80))) || - ((absErr==last2AbsError) && (absErr<=I_ERR_TOLLERANCE_AROUND_0))) { //sign of last error16 != sign of current OR abserror around 0 - - CTL_interatorCredit=config.I_max_credit; // ? optional + if ( // ((lastErrorSign != ((uint8_t)(error16>>8)&0x80))) || //sign of last error16 != sign of current + ((absErr==last2AbsError) && (absErr<=I_ERR_TOLLERANCE_AROUND_0))) { //abserror around 0 with slow change + CTL_interatorCredit=config.I_max_credit; CTL_creditExpiration=config.I_credit_expiration; goto INTEGRATOR; // next integration, do not change CTL_interatorCredit } @@ -368,16 +381,9 @@ #if BOOST_CONTROLER_AFTER_CHANGE if (PID_boost_timeout > 0) { - if ((abs(error16)<=(int16_t)(config.temp_boost_error-config.temp_boost_hystereses))) { // error <= temp_boost_error-temp_boost_hystereses - PID_boost_timeout=0; // end boost earlier, if error got to small (0,2°) - } else { - CTL_integratorBlock=DEFINE_INTEGRATOR_BLOCK; //block Integrator - if (error16>0) { - return config.valve_max; //boost to max, no PID calculation - } else { - return config.valve_min; //boost to min, no PID calculation - } - } + CTL_integratorBlock=CTL_INTEGRATOR_BLOCK; //block Integrator + CTL_creditExpiration=config.I_credit_expiration; + return PID_boost; //return valve_MAX or MIN } #endif Index: controller.h =================================================================== --- controller.h (revision 363) +++ controller.h (working copy) @@ -39,6 +39,7 @@ extern uint8_t CTL_mode_auto; extern int8_t PID_force_update; // signed value, val<0 means disable force updates extern uint8_t CTL_error; +extern uint8_t CTL_error_jr; //jr extern uint8_t CTL_mode_window; #define mode_window() (CTL_mode_window!=0) @@ -59,9 +60,11 @@ #define CTL_CLOSE_WINDOW_FORCE -3 void CTL_change_mode(int8_t dif); -#define DEFINE_INTEGRATOR_BLOCK 6 +#define CTL_INTEGRATOR_BLOCK 6 //jr was=6 #define I_ERR_TOLLERANCE_AROUND_0 15 // unit 0,01°C. Set it quite restrictive ! #define I_ERR_WEIGHT 25 //impact of error on I part +#define I_SUMERR_CHANGE_WEIGHT 10 //imapct of SumErr changes on lastSummError, averaging for integrator revert +#define CTL_BOOST_TEMPCHANGE 5 //unit 0,1°C, estimated change of temp during boosttime, for calculating boost time extern uint8_t CTL_integratorBlock; @@ -78,4 +81,8 @@ extern int32_t sumError; extern int8_t CTL_interatorCredit; +extern uint8_t PID_boost_timeout; extern uint8_t CTL_creditExpiration; +extern int32_t lastTempChangeSumError; +extern uint8_t average_sumerr_count; + Index: eeprom.h =================================================================== --- eeprom.h (revision 363) +++ eeprom.h (working copy) @@ -98,10 +98,7 @@ /* 2a */ uint8_t window_open_timeout; //!< maximum time for window open state [minutes] #endif #if BOOST_CONTROLER_AFTER_CHANGE - /* */ uint8_t temp_boost_setpoint_diff; - /* */ uint8_t temp_boost_hystereses; /* */ uint8_t temp_boost_error; - /* */ uint8_t temp_boost_tempchange; /* */ uint8_t temp_boost_time_cool; /* */ uint8_t temp_boost_time_heat; #endif @@ -203,12 +200,12 @@ /* 06 */ {8, 8, 0, 255}, //!< P_Factor; /* 07 */ {32, 32, 0, 255}, //!< I_Factor; /* 08 */ {40, 40, 0, 127}, //!< I_max_credit - /* 09 */ {30, 30, 0, 255}, //!< I_credit_expiration unit is PID_interval, default 2 hour + /* 09 */ {255, 30, 0, 255}, //!< I_credit_expiration unit is PID_interval, default 2 hour /* 0a */ {240/5, 240/5, 20/5, 255}, //!< PID_interval*5 = interval in seconds; min=20sec, max=21.25 minutes - /* 0b */ {30, 30, 0, 100}, //!< valve_min - /* 0c */ {45, 45, 0, 100}, //!< valve_center - /* 0d */ {80, 80, 0, 100}, //!< valve_max - /* 0e */ {64, 64, 0, 127}, //!< valve_hysteresis; valve movement hysteresis (unit is 1/128%), must be <128 + /* 0b */ {2*16+6, 30, 0, 100}, //!< az0x36 kz0x3a bad0x26 valve_min typically opens MIN+4 + /* 0c */ {3*16+6, 45, 0, 100}, //!< valve_center, motor_pos_max az2c6 kz2b3 bad 1fe + /* 0d */ {96, 80, 0, 100}, //!< valve_max + /* 0e */ {26, 64, 0, 127}, //!< +-0,2% valve_hysteresis; valve movement hysteresis (unit is 1/128%), must be <128 /* 0f */ {32, 32, 32, 255}, //!< min motor_pwm PWM setting /* 10 */ {250, 250, 50, 255}, //!< max motor_pwm PWM setting /* 11 */ {100, 100, 1, 255}, //!< motor_eye_low @@ -254,15 +251,12 @@ /* 2a */ {90, 90, 2, 255}, //!< window_open_timeout #endif #if BOOST_CONTROLER_AFTER_CHANGE - /* */ {50, 0, 0, 255}, //!< temp_boost_setpoint_diff, unit 0,01°C - /* */ {10, 0, 0, 255}, //!< temp_boost_hystereses, unit 0,01°C - /* */ {30, 0, 0, 255}, //!< temp_boost_error, unit 0,01°C - /* */ {5, 0, 0, 255}, //!< temp_boost_tempchange_heat,0,1°C, boosttime=error/10(0,1°C)*time/tempchange - /* */ {64, 0, 0, 255}, //!< temp_boost_time_cool, minutes - /* */ {15, 0, 0, 255}, //!< temp_boost_time_heat, minutes + /* */ {30, 30, 10, 255}, //!< temp_boost_error,start boost if error to new setpoint is larger than this,unit0,01°C + /* */ {64, 64, 0, 255}, //!< temp_boost_time_cool, minutes boost should last during heat up, if error = CTL_BOOST_TEMP_CHANGE(0,5°C) + /* */ {48, 48, 0, 255}, //!< temp_boost_time_heat, minutes boost should last during cool down, if error = CTL_BOOST_TEMP_CHANGE(0,5°C) #endif #if TEMP_COMPENSATE_OPTION - /* */ {0, 0, 0, 255}, //!< offset to roomtemp 1=0,1°C, binary complement for <0 + /* */ {17, 0, 0, 255}, //!< bad, 25=x18 offset to roomtemp 1=0,1°C, binary complement for <0 #endif #if (RFM==1) /* */ {RFM_DEVICE_ADDRESS, RFM_DEVICE_ADDRESS, 0, 29}, //!< RFM_devaddr: HR20's own device address in RFM radio networking. Index: motor.c =================================================================== --- motor.c (revision 363) +++ motor.c (working copy) @@ -108,7 +108,7 @@ #if CALIBRATION_RESETS_sumError sumError=0; // new calibration need found new sumError #endif - CTL_integratorBlock=DEFINE_INTEGRATOR_BLOCK; + CTL_integratorBlock=CTL_INTEGRATOR_BLOCK; CTL_interatorCredit=config.I_max_credit; } else { @@ -332,6 +332,7 @@ if (MOTOR_calibration_step != 0) { MOTOR_calibration_step = -1; // calibration error CTL_error |= CTL_ERR_MOTOR; + CTL_error_jr = 1; //jr CTL_ERR_MOTOR; } } else { // stop on timeout if (d == open) { // stopped on end @@ -348,6 +349,7 @@ } else { MOTOR_calibration_step = -1; // calibration error CTL_error |= CTL_ERR_MOTOR; + CTL_error_jr = 2; //jr CTL_ERR_MOTOR; } } else { MOTOR_Control(close); @@ -366,6 +368,7 @@ } else if (MOTOR_PosAct>MOTOR_MIN_IMPULSES) { MOTOR_calibration_step = -1; // calibration error CTL_error |= CTL_ERR_MOTOR; + CTL_error_jr = 3; //jr CTL_ERR_MOTOR; } MOTOR_PosAct = 0; // cleanup position } @@ -375,6 +378,7 @@ (MOTOR_PosMax