839 units_list *unit; |
839 units_list *unit; |
840 profiles_list *profile; |
840 profiles_list *profile; |
841 prof_step *step; |
841 prof_step *step; |
842 int rc, run = 1, seconds = 0, minutes = 0, temp, deviation; |
842 int rc, run = 1, seconds = 0, minutes = 0, temp, deviation; |
843 int run_seconds, run_minutes, run_hours, tot_minutes; |
843 int run_seconds, run_minutes, run_hours, tot_minutes; |
844 float sp, pv, P_err = 0.0, Out; |
|
845 #ifdef HAVE_WIRINGPI_H |
844 #ifdef HAVE_WIRINGPI_H |
846 struct tm *tm; |
845 struct tm *tm; |
847 int row, key; |
846 int row, key; |
848 #else |
847 #else |
849 long t = 0; |
848 long t = 0; |
850 #endif |
849 #endif |
851 int current_step, valid_step, time_until_now; |
850 int current_step, valid_step, time_until_now; |
852 float previous_target; |
851 float previous_target; |
853 pid_var *pid; |
|
854 |
852 |
855 |
853 |
856 if (lockprog((char *)"thermferm")) { |
854 if (lockprog((char *)"thermferm")) { |
857 syslog(LOG_NOTICE, "Can't lock"); |
855 syslog(LOG_NOTICE, "Can't lock"); |
858 return 1; |
856 return 1; |
924 */ |
922 */ |
925 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->light_state = 0; |
923 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->light_state = 0; |
926 unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; |
924 unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; |
927 if (unit->mode == UNITMODE_PROFILE) { |
925 if (unit->mode == UNITMODE_PROFILE) { |
928 if (!unit->profile) |
926 if (!unit->profile) |
929 syslog(LOG_NOTICE, "Starting unit %s in profile mode, no profile defined.", unit->name); |
927 syslog(LOG_NOTICE, "Starting unit `%s' in profile mode, no profile defined.", unit->name); |
930 else |
928 else |
931 syslog(LOG_NOTICE, "Starting unit %s in profile state %s.", unit->name, PROFSTATE[unit->prof_state]); |
929 syslog(LOG_NOTICE, "Starting unit `%s' in profile state %s.", unit->name, PROFSTATE[unit->prof_state]); |
932 } else if (unit->mode == UNITMODE_BEER) { |
930 } else if (unit->mode == UNITMODE_BEER) { |
933 syslog(LOG_NOTICE, "Starting unit %s beer cooler at %.1f degrees", unit->name, unit->beer_set); |
931 syslog(LOG_NOTICE, "Starting unit `%s' beer cooler at %.1f degrees", unit->name, unit->beer_set); |
934 } else if (unit->mode == UNITMODE_FRIDGE) { |
932 } else if (unit->mode == UNITMODE_FRIDGE) { |
935 syslog(LOG_NOTICE, "Starting unit %s as refridgerator at %.1f degrees", unit->name, unit->fridge_set); |
933 syslog(LOG_NOTICE, "Starting unit `%s' as refridgerator at %.1f degrees", unit->name, unit->fridge_set); |
936 } else if (unit->mode == UNITMODE_NONE) { |
934 } else if (unit->mode == UNITMODE_NONE) { |
937 syslog(LOG_NOTICE, "Starting unit %s in inactive state", unit->name); |
935 syslog(LOG_NOTICE, "Starting unit `%s' in inactive state", unit->name); |
938 } else { |
936 } else { |
939 syslog(LOG_NOTICE, "Starting unit %s in off state", unit->name); |
937 syslog(LOG_NOTICE, "Starting unit `%s' in off state", unit->name); |
940 } |
938 } |
941 } |
939 } |
942 |
940 |
943 #ifdef HAVE_WIRINGPI_H |
941 #ifdef HAVE_WIRINGPI_H |
944 piLock(LOCK_LCD); |
942 piLock(LOCK_LCD); |
1377 |
1375 |
1378 /* |
1376 /* |
1379 * Temperature control in this unit |
1377 * Temperature control in this unit |
1380 */ |
1378 */ |
1381 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { |
1379 if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { |
1382 int usePid = TRUE; |
1380 |
1383 |
1381 /* |
1384 sp = unit->beer_set; |
1382 * Set both PID's to their input values. |
1385 pv = unit->beer_temperature / 1000.0; |
1383 */ |
|
1384 unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; |
1386 if (unit->mode == UNITMODE_FRIDGE) { |
1385 if (unit->mode == UNITMODE_FRIDGE) { |
1387 sp = unit->fridge_set; |
1386 unit->PID_cool->SetP = unit->PID_heat->SetP = unit->fridge_set; |
1388 pv = unit->air_temperature / 1000.0; |
1387 unit->PID_cool->Input = unit->PID_heat->Input = unit->air_temperature / 1000.0; |
1389 usePid = FALSE; |
1388 unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_BOO; |
|
1389 } else if (unit->mode == UNITMODE_BEER) { |
|
1390 unit->PID_cool->SetP = unit->PID_heat->SetP = unit->beer_set; |
|
1391 unit->PID_cool->Input = unit->PID_heat->Input = unit->beer_temperature / 1000.0; |
|
1392 unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_AUTO; |
1390 } else if (unit->mode == UNITMODE_PROFILE) { |
1393 } else if (unit->mode == UNITMODE_PROFILE) { |
1391 sp = unit->prof_target; |
1394 unit->PID_cool->SetP = unit->PID_heat->SetP = unit->prof_target; |
1392 } |
1395 unit->PID_cool->Input = unit->PID_heat->Input = unit->beer_temperature / 1000.0; |
1393 |
1396 unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_AUTO; |
1394 P_err = sp - pv; |
1397 } |
1395 if (P_err < unit->idle_rangeH && P_err > unit->idle_rangeL && usePid == FALSE) { |
1398 |
1396 P_err = 0.0; |
1399 /* |
1397 } |
1400 * PID controller compute |
1398 |
1401 */ |
1399 if (usePid) { |
1402 if (unit->heater_address) { |
1400 /* |
1403 UpdatePID(unit->PID_heat); |
1401 * PID controller compute |
1404 |
1402 */ |
1405 if (debug) |
1403 pid = (pid_var *)malloc(sizeof(pid_var)); |
1406 fprintf(stdout, "Heat: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f\n", |
1404 pid->dState = unit->PID_dState; |
1407 unit->PID_heat->SetP, unit->PID_heat->Input, unit->PID_heat->InputD, unit->PID_heat->Err, unit->PID_heat->OutP); |
1405 pid->iState = unit->PID_iState; |
1408 if (((unit->PID_heat->OutP >= 1) && unit->heater_address) || (seconds == 60) || unit->heater_state) { |
1406 pid->iMax = 100.0; |
1409 syslog(LOG_NOTICE, "Heat: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f", |
1407 pid->iMin = -100.0; |
1410 unit->PID_heat->SetP, unit->PID_heat->Input, unit->PID_heat->InputD, unit->PID_heat->Err, unit->PID_heat->OutP); |
1408 pid->pGain = unit->PID_Kp; |
1411 } |
1409 pid->iGain = unit->PID_Ki; |
1412 } |
1410 pid->dGain = unit->PID_Kd; |
1413 if (unit->cooler_address) { |
1411 |
1414 UpdatePID(unit->PID_cool); |
1412 Out = UpdatePID(pid, P_err, pv); |
|
1413 |
|
1414 if (Out > 100.0) |
|
1415 Out = 100.0; |
|
1416 if (Out < -100.0) |
|
1417 Out = -100.0; |
|
1418 |
1415 |
1419 if (debug) |
1416 if (debug) |
1420 fprintf(stdout, "sp=%.2f pv=%.2f dState=%.2f P_err=%.2f iState=%.2f Out=%.2f\n", |
1417 fprintf(stdout, "Cool: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f\n", |
1421 sp, pv, unit->PID_dState, P_err, unit->PID_iState, Out); |
1418 unit->PID_cool->SetP, unit->PID_cool->Input, unit->PID_cool->InputD, unit->PID_cool->Err, unit->PID_cool->OutP); |
1422 if (((Out >= 1) && unit->heater_address) || ((Out <= -1) && unit->cooler_address) || |
1419 if (((unit->PID_cool->OutP >= 1) && unit->cooler_address) || (seconds == 60) || unit->cooler_state) { |
1423 (seconds == 60) || unit->heater_state || unit->cooler_state) { |
1420 syslog(LOG_NOTICE, "Cool: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f", |
1424 syslog(LOG_NOTICE, "sp=%.2f pv=%.2f P_err=%.2f dState=%.2f iState=%.2f Out=%.2f", |
1421 unit->PID_cool->SetP, unit->PID_cool->Input, unit->PID_cool->InputD, unit->PID_cool->Err, unit->PID_cool->OutP); |
1425 sp, pv, P_err, unit->PID_dState, unit->PID_iState, Out); |
|
1426 } |
1422 } |
1427 |
1423 } |
1428 unit->PID_iState = pid->iState; |
1424 |
1429 unit->PID_dState = pid->dState; |
1425 if (unit->PID_cool->OutP && unit->PID_heat->OutP) { |
1430 free(pid); |
1426 syslog(LOG_NOTICE, "Heat and Cool lockdown"); |
1431 pid = NULL; |
1427 unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; |
1432 } else { |
|
1433 /* |
|
1434 * Simple temperature control |
|
1435 */ |
|
1436 if (P_err > 0) { |
|
1437 Out = 100.0; |
|
1438 } else if (P_err < 0) { |
|
1439 Out = -100.0; |
|
1440 } else { |
|
1441 Out = 0.0; |
|
1442 } |
|
1443 // if (((Out >= 1) && unit->heater_address) || ((Out <= -1) && unit->cooler_address) || |
|
1444 // (seconds == 60) || unit->heater_state || unit->cooler_state) { |
|
1445 // syslog(LOG_NOTICE, "sp=%.2f pv=%.2f P_err=%.2f Out=%.2f", sp, pv, P_err, Out); |
|
1446 // } |
|
1447 } |
1428 } |
1448 |
1429 |
1449 if (unit->heater_address && ! unit->cooler_state) { |
1430 if (unit->heater_address && ! unit->cooler_state) { |
1450 if (Out >= 1) { |
1431 if (unit->PID_heat->OutP >= 1) { |
1451 if (unit->heater_wait < unit->heater_delay) { |
1432 if (unit->heater_wait < unit->heater_delay) { |
1452 unit->heater_wait++; |
1433 unit->heater_wait++; |
1453 // syslog(LOG_NOTICE, "heater_wait + %d/%d", unit->heater_wait, unit->heater_delay); |
1434 // syslog(LOG_NOTICE, "heater_wait + %d/%d", unit->heater_wait, unit->heater_delay); |
1454 } else { |
1435 } else { |
1455 int power = round(Out); |
1436 int power = round(unit->PID_heat->OutP); |
1456 if (unit->heater_state != power) { |
1437 if (unit->heater_state != power) { |
1457 syslog(LOG_NOTICE, "Unit `%s' heater %d%% => %d%%", unit->name, unit->heater_state, power); |
1438 syslog(LOG_NOTICE, "Unit `%s' heater %d%% => %d%%", unit->name, unit->heater_state, power); |
1458 unit->heater_state = power; |
1439 unit->heater_state = power; |
1459 } |
1440 } |
1460 } |
1441 } |
1474 else |
1455 else |
1475 device_out(unit->heater_address, 0); |
1456 device_out(unit->heater_address, 0); |
1476 } |
1457 } |
1477 |
1458 |
1478 if (unit->cooler_address && ! unit->heater_state) { |
1459 if (unit->cooler_address && ! unit->heater_state) { |
1479 if (Out <= -1) { |
1460 if (unit->PID_cool->OutP >= 1) { |
1480 if (unit->cooler_wait < unit->cooler_delay) { |
1461 if (unit->cooler_wait < unit->cooler_delay) { |
1481 unit->cooler_wait++; |
1462 unit->cooler_wait++; |
1482 // syslog(LOG_NOTICE, "cooler_wait + %d/%d", unit->cooler_wait, unit->cooler_delay); |
1463 // syslog(LOG_NOTICE, "cooler_wait + %d/%d", unit->cooler_wait, unit->cooler_delay); |
1483 } else { |
1464 } else { |
1484 int power = round(0 - Out); |
1465 int power = round(unit->PID_cool->OutP); |
1485 if (unit->cooler_state != power) { |
1466 if (unit->cooler_state != power) { |
1486 syslog(LOG_NOTICE, "Unit `%s' cooler %d%% => %d%%", unit->name, unit->cooler_state, power); |
1467 syslog(LOG_NOTICE, "Unit `%s' cooler %d%% => %d%%", unit->name, unit->cooler_state, power); |
1487 unit->cooler_state = power; |
1468 unit->cooler_state = power; |
1488 } |
1469 } |
1489 } |
1470 } |