diff -r f3b0e9ac9bcb -r 7b0f819a3805 thermferm/thermferm.c --- a/thermferm/thermferm.c Sun Feb 15 23:09:00 2015 +0100 +++ b/thermferm/thermferm.c Mon Feb 16 19:52:42 2015 +0100 @@ -834,9 +834,9 @@ units_list *unit; profiles_list *profile; prof_step *step; - int rc, run = 1, seconds = 0, minutes = 0, piddelay = 0, temp, deviation; + int rc, run = 1, seconds = 0, minutes = 0, temp, deviation; int run_seconds, run_minutes, run_hours, tot_minutes; - float sp, pv, P_err = 0.0, D_err, Out; + float sp, pv, P_err = 0.0, Out; #ifdef HAVE_WIRINGPI_H struct tm *tm; int row, key; @@ -1302,62 +1302,65 @@ #endif } - piddelay++; - if (piddelay == 5) { - piddelay = 0; + /* + * PID controller per unit, each second + */ + for (unit = Config.units; unit; unit = unit->next) { + if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { + double pTerm, dTerm, iTerm; + + sp = unit->beer_set; + pv = unit->beer_temperature / 1000.0; + if (unit->mode == UNITMODE_FRIDGE) { + sp = unit->fridge_set; + pv = unit->air_temperature / 1000.0; + } else if (unit->mode == UNITMODE_PROFILE) { + sp = unit->prof_target; + } + + /* + * PID controller compute + */ + P_err = sp - pv; +// if (P_err < unit->idle_rangeH && P_err > unit->idle_rangeL) { +// P_err = 0.0; +// } + pTerm = unit->PID_Kp * P_err; - for (unit = Config.units; unit; unit = unit->next) { - if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { - /* - * PID controller - */ - sp = unit->beer_set; - pv = unit->beer_temperature / 1000.0; - if (unit->mode == UNITMODE_FRIDGE) { - sp = unit->fridge_set; - pv = unit->air_temperature / 1000.0; - } else if (unit->mode == UNITMODE_PROFILE) { - sp = unit->prof_target; - } + /* + * Calculate the intergral state with appropriate limiting + */ + unit->PID_I_err += P_err; + /* Limit integral error */ + if (unit->PID_I_err < -100.0) + unit->PID_I_err = -100.0; + if (unit->PID_I_err > 100.0) + unit->PID_I_err = 100.0; + iTerm = unit->PID_I_err * unit->PID_Ki; + dTerm = unit->PID_err_old * unit->PID_Kd; - P_err = sp - pv; - if (P_err < unit->idle_rangeH && P_err > unit->idle_rangeL) { - P_err = 0.0; - } - unit->PID_I_err += (unit->PID_Ki * P_err); -// unit->PID_I_err -= unit->PID_err_old; -// } else { -// unit->PID_I_err += unit->PID_err_old; + /* + * A postive value means heating, a negative value cooling. + * Start with Kp, Kd and Ki set to 0. + * Increase Kp until small oscillation. + * Increase Kd until a little damping. + * Increase Ki after Kp and Kd are set until longterm convergence. + */ + Out = pTerm + dTerm + iTerm; + if (Out > 100.0) + Out = 100.0; + if (Out < -100.0) + Out = -100.0; +// if /* (P_err != 0.0) */ (i == 1) { + if (debug) + fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f Out=%.2f\n", + sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, Out); + syslog(LOG_NOTICE, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f Out=%.2f pTerm=%.2f iTerm=%.2f dTerm=%.2f, N=%.2f", + sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, Out, pTerm, iTerm, dTerm, pTerm + dTerm + iTerm); // } - /* Limit integral error */ - if (unit->PID_I_err < -100.0) - unit->PID_I_err = -100.0; - if (unit->PID_I_err > 100.0) - unit->PID_I_err = 100.0; - D_err = P_err - unit->PID_err_old; + unit->PID_err_old = P_err; - /* - * A postive value means heating, a negative value cooling. - * Start with Kp, Kd and Ki set to 0. - * Increase Kp until small oscillation. - * Increase Kd until a little damping. - * Increase Ki after Kp and Kd are set until longterm convergence. - */ - Out = (unit->PID_Kp * P_err) + unit->PID_I_err - (unit->PID_Kd * D_err); - if (Out > 100.0) - Out = 100.0; - if (Out < -100.0) - Out = -100.0; -// if (P_err != 0.0) { - if (debug) - fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f\n", - sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, D_err, Out); - syslog(LOG_NOTICE, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f", - sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, D_err, Out); -// } - unit->PID_err_old = P_err; - - if (unit->heater_address) { + if (unit->heater_address) { if (Out >= 1) { if (unit->heater_wait < unit->heater_delay) { unit->heater_wait++; @@ -1380,8 +1383,8 @@ } } device_out(unit->heater_address, unit->heater_state); - } - if (unit->cooler_address) { + } + if (unit->cooler_address) { if (Out <= -1) { if (unit->cooler_wait < unit->cooler_delay) { unit->cooler_wait++; @@ -1404,8 +1407,8 @@ } } device_out(unit->cooler_address, unit->cooler_state); - } - if (unit->heater_address && unit->cooler_address && unit->fan_address) { + } + if (unit->heater_address && unit->cooler_address && unit->fan_address) { /* * If the temperature difference between air and beer is more then * xxx degrees, turn the fan on to make an airflow. @@ -1424,12 +1427,11 @@ unit->fan_state = 0; } device_out(unit->fan_address, unit->fan_state); - } - } else { + } + } else { P_err = 0.0; unit->PID_I_err = 0.0; unit->PID_err_old = 0.0; - } } }