thermferm/thermferm.c

changeset 312
7b0f819a3805
parent 311
f3b0e9ac9bcb
child 313
8448fcf3d799
--- 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;
-		    }
 		}
 	    }
 

mercurial