Tue, 05 Aug 2014 21:33:06 +0200
PID finetuning
--- a/thermferm/devices.c Tue Aug 05 16:24:17 2014 +0200 +++ b/thermferm/devices.c Tue Aug 05 21:33:06 2014 +0200 @@ -38,16 +38,21 @@ devices_list *device; char buf[40]; int i, rc; + time_t now; if (uuid == NULL) return 0; - if (debug) - fprintf(stdout, "device_out(%s, %d)\n", uuid, value); + now = time(NULL); for (device = Config.devices; device; device = device->next) { if (strcmp(uuid, device->uuid) == 0) { - if (value != device->value) { + /* + * Execute command if different then the old value. But also + * every 2 minutes because commands can get lost of devices were + * disconnected, or with radio problems. + */ + if ((value != device->value) || (((int)now - (int)device->timestamp) > 120)) { #ifdef HAVE_WIRINGPI_H rc = 0; @@ -81,6 +86,7 @@ } } } + return 0; }
--- a/thermferm/rdconfig.c Tue Aug 05 16:24:17 2014 +0200 +++ b/thermferm/rdconfig.c Tue Aug 05 21:33:06 2014 +0200 @@ -680,7 +680,7 @@ unit->idle_rangeH = 1.0; unit->idle_rangeL = -1.0; unit->prof_started = (time_t)0; - unit->PID_err_old = 0.0; + unit->PID_err_old = unit->PID_I_err = 0.0; cur = cur->xmlChildrenNode; while (cur != NULL) {
--- a/thermferm/server.c Tue Aug 05 16:24:17 2014 +0200 +++ b/thermferm/server.c Tue Aug 05 21:33:06 2014 +0200 @@ -1028,7 +1028,7 @@ unit->idle_rangeH = 1.0; unit->idle_rangeL = -1.0; unit->prof_started = (time_t)0; - unit->PID_err_old = 0.0; + unit->PID_err_old = unit->PID_I_err = 0.0; if (Config.units == NULL) { Config.units = unit;
--- a/thermferm/thermferm.c Tue Aug 05 16:24:17 2014 +0200 +++ b/thermferm/thermferm.c Tue Aug 05 21:33:06 2014 +0200 @@ -249,7 +249,7 @@ time_t now, last = (time_t)0; units_list *unit; int rc, run = 1, seconds = 0, minutes = 0, piddelay = 0, temp, deviation; - float err = 0.0, sp, pv, P_err, I_err = 0.0, D_err, Out; + float err = 0.0, sp, pv, P_err, D_err, Out; #ifdef HAVE_WIRINGPI_H struct tm *tm; int row; @@ -446,20 +446,28 @@ unit->PID_err_old = err; err = sp - pv; - if (err < unit->idle_rangeH && err > unit->idle_rangeL) + if (err < unit->idle_rangeH && err > unit->idle_rangeL) { err = 0; + unit->PID_I_err -= unit->PID_err_old; + } else { + unit->PID_I_err += unit->PID_err_old; + } + /* Limit intergral error */ + if (unit->PID_I_err < -10.0) + unit->PID_I_err = -10.0; + if (unit->PID_I_err > 10.0) + unit->PID_I_err = 10.0; P_err = err; - I_err += unit->PID_err_old; D_err = err - unit->PID_err_old; /* * A postive value means heating, a negative value cooling. */ - Out = (5.0*P_err) + (0.25*I_err) + (1.5*D_err); - // Kp 0.1 Ki 0.3 Kd 0.02 + Out = (10.0*P_err) + (0.1*unit->PID_I_err) + (5*D_err); + // Kp 0.1 Ki 0.3 Kd 0.02 if (debug) fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f err=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f\n", - sp, pv, unit->PID_err_old, err, P_err, I_err, D_err, Out); + sp, pv, unit->PID_err_old, err, P_err, unit->PID_I_err, D_err, Out); if (unit->heater_address) { if (Out >= 2) unit->heater_state = 100; @@ -476,7 +484,7 @@ } } else { err = 0.0; - I_err = 0.0; + unit->PID_I_err = 0.0; unit->PID_err_old = 0.0; } }
--- a/thermferm/thermferm.h Tue Aug 05 16:24:17 2014 +0200 +++ b/thermferm/thermferm.h Tue Aug 05 21:33:06 2014 +0200 @@ -91,6 +91,7 @@ time_t prof_started; /* Profile start time */ int prof_state; /* Profile OFF|PAUSE|RUN|DONE */ float prof_target; /* Profile current target temp */ + float PID_I_err; /* PID Intergal error */ float PID_err_old; /* PID old error value */ } units_list;
--- a/www-thermferm/liveview.php Tue Aug 05 16:24:17 2014 +0200 +++ b/www-thermferm/liveview.php Tue Aug 05 21:33:06 2014 +0200 @@ -110,9 +110,9 @@ $outstr .= ' { name: \'Beer\', type: \'float\' },'.PHP_EOL; $outstr .= ' { name: \'Target\', type: \'float\' },'.PHP_EOL; $outstr .= ' { name: \'Heater\' },'.PHP_EOL; - $outstr .= ' { name: \'Cooler\' },'.PHP_EOL; + $outstr .= ' { name: \'Cooler\', type: \'int\' },'.PHP_EOL; $outstr .= ' { name: \'Fan\' },'.PHP_EOL; - $outstr .= ' { name: \'Door\' }'.PHP_EOL; + $outstr .= ' { name: \'Door\', type: \'bool\' }'.PHP_EOL; $outstr .= ' ],'.PHP_EOL; $outstr .= ' url: \'getlog.php?unit='.$unit.'\''.PHP_EOL; $outstr .= ' };'.PHP_EOL; @@ -150,18 +150,25 @@ $outstr .= ' },'.PHP_EOL; $outstr .= ' series: ['.PHP_EOL; $outstr .= ' { dataField: \'Air\', displayText: \'Air\' },'.PHP_EOL; - $outstr .= ' { dataField: \'Beer\', displayText: \'Beer\' }'.PHP_EOL; + $outstr .= ' { dataField: \'Beer\', displayText: \'Beer\' },'.PHP_EOL; + $outstr .= ' { dataField: \'Target\', displayText: \'Target\' }'.PHP_EOL; $outstr .= ' ]'.PHP_EOL; $outstr .= ' }]'.PHP_EOL; $outstr .= ' };'.PHP_EOL; + /* Direct draw for the first time */ $outstr .= ' $("#fermentor_chart_'.$unit.'").jqxChart(settings'.$unr.');'.PHP_EOL; + /* Regular updates of the chart */ +// $outstr .= ' setInterval(function(){'.PHP_EOL; +// $outstr .= ' $("#fermentor_chart_'.$unit.'").jqxChart("update");'.PHP_EOL; +// $outstr .= ' }, 3000);'.PHP_EOL; + $outstr .= ' setInterval(function(){'.PHP_EOL; - $outstr .= ' $.getJSON("getstate.php?uuid='.$unit.'", function(data) {'.PHP_EOL; - $outstr .= ' $("#load_air_'.$unr.'").html(data.air_temperature);'.PHP_EOL; - $outstr .= ' $("#load_beer_'.$unr.'").html(data.beer_temperature);'.PHP_EOL; - $outstr .= ' $("#load_target_'.$unr.'").html(data.target_temperature);'.PHP_EOL; - $outstr .= ' });'.PHP_EOL; - $outstr .= ' }, 10000);'.PHP_EOL; + $outstr .= ' $.getJSON("getstate.php?uuid='.$unit.'", function(data) {'.PHP_EOL; + $outstr .= ' $("#load_air_'.$unr.'").html(data.air_temperature);'.PHP_EOL; + $outstr .= ' $("#load_beer_'.$unr.'").html(data.beer_temperature);'.PHP_EOL; + $outstr .= ' $("#load_target_'.$unr.'").html(data.target_temperature);'.PHP_EOL; + $outstr .= ' });'.PHP_EOL; + $outstr .= ' }, 10000);'.PHP_EOL; $outstr .= ' });'.PHP_EOL; $outstr .= ' </script>'.PHP_EOL; $outstr .= ' <div id="fermentor">'.PHP_EOL;