832 char use_heater[40], use_cooler[40], use_fan[40]; |
832 char use_heater[40], use_cooler[40], use_fan[40]; |
833 time_t now, last = (time_t)0; |
833 time_t now, last = (time_t)0; |
834 units_list *unit; |
834 units_list *unit; |
835 profiles_list *profile; |
835 profiles_list *profile; |
836 prof_step *step; |
836 prof_step *step; |
837 int rc, run = 1, seconds = 0, minutes = 0, piddelay = 0, temp, deviation; |
837 int rc, run = 1, seconds = 0, minutes = 0, temp, deviation; |
838 int run_seconds, run_minutes, run_hours, tot_minutes; |
838 int run_seconds, run_minutes, run_hours, tot_minutes; |
839 float sp, pv, P_err = 0.0, D_err, Out; |
839 float sp, pv, P_err = 0.0, Out; |
840 #ifdef HAVE_WIRINGPI_H |
840 #ifdef HAVE_WIRINGPI_H |
841 struct tm *tm; |
841 struct tm *tm; |
842 int row, key; |
842 int row, key; |
843 #else |
843 #else |
844 long t = 0; |
844 long t = 0; |
1300 piUnlock(LOCK_LCD); |
1300 piUnlock(LOCK_LCD); |
1301 } |
1301 } |
1302 #endif |
1302 #endif |
1303 } |
1303 } |
1304 |
1304 |
1305 piddelay++; |
1305 /* |
1306 if (piddelay == 5) { |
1306 * PID controller per unit, each second |
1307 piddelay = 0; |
1307 */ |
1308 |
1308 for (unit = Config.units; unit; unit = unit->next) { |
1309 for (unit = Config.units; unit; unit = unit->next) { |
1309 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { |
1310 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { |
1310 double pTerm, dTerm, iTerm; |
1311 /* |
1311 |
1312 * PID controller |
1312 sp = unit->beer_set; |
1313 */ |
1313 pv = unit->beer_temperature / 1000.0; |
1314 sp = unit->beer_set; |
1314 if (unit->mode == UNITMODE_FRIDGE) { |
1315 pv = unit->beer_temperature / 1000.0; |
1315 sp = unit->fridge_set; |
1316 if (unit->mode == UNITMODE_FRIDGE) { |
1316 pv = unit->air_temperature / 1000.0; |
1317 sp = unit->fridge_set; |
1317 } else if (unit->mode == UNITMODE_PROFILE) { |
1318 pv = unit->air_temperature / 1000.0; |
1318 sp = unit->prof_target; |
1319 } else if (unit->mode == UNITMODE_PROFILE) { |
1319 } |
1320 sp = unit->prof_target; |
1320 |
1321 } |
1321 /* |
1322 |
1322 * PID controller compute |
1323 P_err = sp - pv; |
1323 */ |
1324 if (P_err < unit->idle_rangeH && P_err > unit->idle_rangeL) { |
1324 P_err = sp - pv; |
1325 P_err = 0.0; |
1325 // if (P_err < unit->idle_rangeH && P_err > unit->idle_rangeL) { |
1326 } |
1326 // P_err = 0.0; |
1327 unit->PID_I_err += (unit->PID_Ki * P_err); |
1327 // } |
1328 // unit->PID_I_err -= unit->PID_err_old; |
1328 pTerm = unit->PID_Kp * P_err; |
1329 // } else { |
1329 |
1330 // unit->PID_I_err += unit->PID_err_old; |
1330 /* |
|
1331 * Calculate the intergral state with appropriate limiting |
|
1332 */ |
|
1333 unit->PID_I_err += P_err; |
|
1334 /* Limit integral error */ |
|
1335 if (unit->PID_I_err < -100.0) |
|
1336 unit->PID_I_err = -100.0; |
|
1337 if (unit->PID_I_err > 100.0) |
|
1338 unit->PID_I_err = 100.0; |
|
1339 iTerm = unit->PID_I_err * unit->PID_Ki; |
|
1340 dTerm = unit->PID_err_old * unit->PID_Kd; |
|
1341 |
|
1342 /* |
|
1343 * A postive value means heating, a negative value cooling. |
|
1344 * Start with Kp, Kd and Ki set to 0. |
|
1345 * Increase Kp until small oscillation. |
|
1346 * Increase Kd until a little damping. |
|
1347 * Increase Ki after Kp and Kd are set until longterm convergence. |
|
1348 */ |
|
1349 Out = pTerm + dTerm + iTerm; |
|
1350 if (Out > 100.0) |
|
1351 Out = 100.0; |
|
1352 if (Out < -100.0) |
|
1353 Out = -100.0; |
|
1354 // if /* (P_err != 0.0) */ (i == 1) { |
|
1355 if (debug) |
|
1356 fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f Out=%.2f\n", |
|
1357 sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, Out); |
|
1358 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", |
|
1359 sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, Out, pTerm, iTerm, dTerm, pTerm + dTerm + iTerm); |
1331 // } |
1360 // } |
1332 /* Limit integral error */ |
1361 unit->PID_err_old = P_err; |
1333 if (unit->PID_I_err < -100.0) |
1362 |
1334 unit->PID_I_err = -100.0; |
1363 if (unit->heater_address) { |
1335 if (unit->PID_I_err > 100.0) |
|
1336 unit->PID_I_err = 100.0; |
|
1337 D_err = P_err - unit->PID_err_old; |
|
1338 |
|
1339 /* |
|
1340 * A postive value means heating, a negative value cooling. |
|
1341 * Start with Kp, Kd and Ki set to 0. |
|
1342 * Increase Kp until small oscillation. |
|
1343 * Increase Kd until a little damping. |
|
1344 * Increase Ki after Kp and Kd are set until longterm convergence. |
|
1345 */ |
|
1346 Out = (unit->PID_Kp * P_err) + unit->PID_I_err - (unit->PID_Kd * D_err); |
|
1347 if (Out > 100.0) |
|
1348 Out = 100.0; |
|
1349 if (Out < -100.0) |
|
1350 Out = -100.0; |
|
1351 // if (P_err != 0.0) { |
|
1352 if (debug) |
|
1353 fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f\n", |
|
1354 sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, D_err, Out); |
|
1355 syslog(LOG_NOTICE, "sp=%.2f pv=%.2f err_old=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f", |
|
1356 sp, pv, unit->PID_err_old, P_err, unit->PID_I_err, D_err, Out); |
|
1357 // } |
|
1358 unit->PID_err_old = P_err; |
|
1359 |
|
1360 if (unit->heater_address) { |
|
1361 if (Out >= 1) { |
1364 if (Out >= 1) { |
1362 if (unit->heater_wait < unit->heater_delay) { |
1365 if (unit->heater_wait < unit->heater_delay) { |
1363 unit->heater_wait++; |
1366 unit->heater_wait++; |
1364 syslog(LOG_NOTICE, "heater_wait + %d/%d", unit->heater_wait, unit->heater_delay); |
1367 syslog(LOG_NOTICE, "heater_wait + %d/%d", unit->heater_wait, unit->heater_delay); |
1365 } else { |
1368 } else { |