229 int server(void) |
246 int server(void) |
230 { |
247 { |
231 char buf[1024], *filename, target[40], heater[40], cooler[40], fan[40], door[40]; |
248 char buf[1024], *filename, target[40], heater[40], cooler[40], fan[40], door[40]; |
232 time_t now, last = (time_t)0; |
249 time_t now, last = (time_t)0; |
233 units_list *unit; |
250 units_list *unit; |
234 int rc, run = 1, seconds = 0, minutes = 0; |
251 int rc, run = 1, seconds = 0, minutes = 0, piddelay = 0, temp, deviation; |
235 float err = 0.0, sp, pv, P_err, I_err = 0.0, D_err, Out; |
252 float err = 0.0, sp, pv, P_err, I_err = 0.0, D_err, Out; |
236 #ifdef HAVE_WIRINGPI_H |
253 #ifdef HAVE_WIRINGPI_H |
237 struct tm *tm; |
254 struct tm *tm; |
238 int row; |
255 int row; |
239 #else |
256 #else |
277 syslog(LOG_NOTICE, "my_server_loop thread didn't start rc=%d", rc); |
294 syslog(LOG_NOTICE, "my_server_loop thread didn't start rc=%d", rc); |
278 #ifndef HAVE_WIRINGPI_H |
295 #ifndef HAVE_WIRINGPI_H |
279 } else { |
296 } else { |
280 t++; |
297 t++; |
281 #endif |
298 #endif |
|
299 } |
|
300 |
|
301 /* |
|
302 * Initialize units for processing |
|
303 */ |
|
304 for (unit = Config.units; unit; unit = unit->next) { |
|
305 /* |
|
306 * Safety, turn everything off |
|
307 */ |
|
308 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = 0; |
|
309 if (unit->profile && (int)unit->prof_started && (unit->mode == UNITMODE_PROFILE)) { |
|
310 syslog(LOG_NOTICE, "Starting unit %s profile %s", unit->name, unit->profile); |
|
311 } else if (unit->mode == UNITMODE_BEER) { |
|
312 syslog(LOG_NOTICE, "Starting unit %s beer cooler at %.1f degrees", unit->name, unit->beer_set); |
|
313 } else if (unit->mode == UNITMODE_FRIDGE) { |
|
314 syslog(LOG_NOTICE, "Starting unit %s as refridgerator at %.1f degrees", unit->name, unit->fridge_set); |
|
315 } else if (unit->mode == UNITMODE_NONE) { |
|
316 syslog(LOG_NOTICE, "Starting unit %s in inactive state", unit->name); |
|
317 } else { |
|
318 syslog(LOG_NOTICE, "Starting unit %s in off state", unit->name); |
|
319 } |
282 } |
320 } |
283 |
321 |
284 #ifdef HAVE_WIRINGPI_H |
322 #ifdef HAVE_WIRINGPI_H |
285 rc = piThreadCreate(my_units_loop); |
323 rc = piThreadCreate(my_units_loop); |
286 #else |
324 #else |
321 #ifdef HAVE_WIRINGPI_H |
359 #ifdef HAVE_WIRINGPI_H |
322 row = 3; |
360 row = 3; |
323 tm = localtime(&now); |
361 tm = localtime(&now); |
324 lcd_buf_write(row++, " %02d-%02d-%04d ", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900); |
362 lcd_buf_write(row++, " %02d-%02d-%04d ", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900); |
325 lcd_buf_write(row++, " %02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); |
363 lcd_buf_write(row++, " %02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); |
|
364 #endif |
326 |
365 |
327 for (unit = Config.units; unit; unit = unit->next) { |
366 for (unit = Config.units; unit; unit = unit->next) { |
328 // if (unit->mode != UNITMODE_OFF) { |
367 #ifdef HAVE_WIRINGPI_H |
329 lcd_buf_write(row++, "Unit %s ", unit->name); |
368 lcd_buf_write(row++, "Unit %s ", unit->name); |
330 lcd_buf_write(row++, "Mode %s ", UNITMODE[unit->mode]); |
369 lcd_buf_write(row++, "Mode %s ", UNITMODE[unit->mode]); |
331 if (unit->air_address) { |
370 if (unit->air_address) { |
332 lcd_buf_write(row++, " Air %.3f %cC ", unit->air_temperature / 1000.0, 0xdf); |
371 lcd_buf_write(row++, " Air %.3f %cC ", unit->air_temperature / 1000.0, 0xdf); |
333 } |
372 } |
334 if (unit->beer_address) { |
373 if (unit->beer_address) { |
335 lcd_buf_write(row++, "Beer %.3f %cC ", unit->beer_temperature / 1000.0, 0xdf); |
374 lcd_buf_write(row++, "Beer %.3f %cC ", unit->beer_temperature / 1000.0, 0xdf); |
336 } |
375 } |
337 // } |
376 #endif |
|
377 |
|
378 if (unit->air_address) { |
|
379 rc = read_w1_28(unit->air_address, &temp); |
|
380 if (rc == DEVPRESENT_YES) { |
|
381 /* |
|
382 * It is possible to have read errors or extreme values. |
|
383 * This can happen with bad connections so we compare the |
|
384 * value with the previous one. If the difference is too |
|
385 * much, we don't send that value. That also means that if |
|
386 * the next value is ok again, it will be marked invalid too. |
|
387 * Maximum error is 40 degrees for now. |
|
388 */ |
|
389 deviation = 40000; |
|
390 if ((unit->air_temperature == 0) || |
|
391 (unit->air_temperature && (temp > (int)unit->air_temperature - deviation) && (temp < ((int)unit->air_temperature + deviation)))) { |
|
392 unit->air_temperature = temp; |
|
393 unit->air_state = 0; |
|
394 } else { |
|
395 syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, unit->air_temperature, temp); |
|
396 if (debug) { |
|
397 fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, unit->air_temperature, temp); |
|
398 } |
|
399 } |
|
400 } else if (rc == DEVPRESENT_ERROR) { |
|
401 unit->air_state = 1; |
|
402 } else { |
|
403 unit->air_state = 2; |
|
404 } |
|
405 } |
|
406 |
|
407 if (unit->beer_address) { |
|
408 rc = read_w1_28(unit->beer_address, &temp); |
|
409 if (rc == DEVPRESENT_YES) { |
|
410 deviation = 40000; |
|
411 if ((unit->beer_temperature == 0) || |
|
412 (unit->beer_temperature && (temp > (int)unit->beer_temperature - deviation) && (temp < ((int)unit->beer_temperature + deviation)))) { |
|
413 unit->beer_temperature = temp; |
|
414 unit->beer_state = 0; |
|
415 } else { |
|
416 syslog(LOG_NOTICE, "deviation error deviation=%d, old=%d new=%d", deviation, unit->beer_temperature, temp); |
|
417 if (debug) { |
|
418 fprintf(stdout, "deviation error deviation=%d, old=%d new=%d\n", deviation, unit->beer_temperature, temp); |
|
419 } |
|
420 } |
|
421 } else if (rc == DEVPRESENT_ERROR) { |
|
422 unit->beer_state = 1; |
|
423 } else { |
|
424 unit->beer_state = 2; |
|
425 } |
|
426 } |
338 } |
427 } |
339 |
428 |
|
429 #ifdef HAVE_WIRINGPI_H |
340 lcd_buf_show(); |
430 lcd_buf_show(); |
341 #endif |
431 #endif |
342 |
432 |
343 if (seconds == 60) { |
433 piddelay++; |
344 seconds = 0; |
434 if (piddelay == 15) { |
|
435 piddelay = 0; |
345 |
436 |
346 for (unit = Config.units; unit; unit = unit->next) { |
437 for (unit = Config.units; unit; unit = unit->next) { |
347 if (unit->mode != UNITMODE_OFF) { |
438 if (unit->mode != UNITMODE_OFF) { |
348 |
439 |
349 if (unit->mode != UNITMODE_NONE) { |
440 if (unit->mode != UNITMODE_NONE) { |
368 D_err = err - unit->PID_err_old; |
459 D_err = err - unit->PID_err_old; |
369 |
460 |
370 /* |
461 /* |
371 * A postive value means heating, a negative value cooling. |
462 * A postive value means heating, a negative value cooling. |
372 */ |
463 */ |
373 Out = (5.0*P_err) + (0.25*I_err) + (-1.5*D_err); |
464 Out = (5.0*P_err) + (0.25*I_err) + (1.5*D_err); |
374 // Kp 0.1 Ki 0.3 Kd 0.02 |
465 // Kp 0.1 Ki 0.3 Kd 0.02 |
375 if (debug) |
466 if (debug) |
376 fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f err=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f\n", |
467 fprintf(stdout, "sp=%.2f pv=%.2f err_old=%.2f err=%.2f P_err=%.2f I_err=%.2f D_err=%.2f Out=%.2f\n", |
377 sp, pv, unit->PID_err_old, err, P_err, I_err, D_err, Out); |
468 sp, pv, unit->PID_err_old, err, P_err, I_err, D_err, Out); |
378 if (unit->heater_address) { |
469 if (unit->heater_address) { |
388 else |
479 else |
389 unit->cooler_state = 0; |
480 unit->cooler_state = 0; |
390 device_out(unit->cooler_address, unit->cooler_state); |
481 device_out(unit->cooler_address, unit->cooler_state); |
391 } |
482 } |
392 } |
483 } |
|
484 } |
|
485 } |
|
486 } |
|
487 |
|
488 if (seconds == 60) { |
|
489 seconds = 0; |
|
490 |
|
491 /* |
|
492 * Log temperature and status every minute if unit is active. |
|
493 */ |
|
494 for (unit = Config.units; unit; unit = unit->next) { |
|
495 if (unit->mode != UNITMODE_OFF) { |
393 |
496 |
394 snprintf(target, 39, "NA"); |
497 snprintf(target, 39, "NA"); |
395 snprintf(heater, 39, "NA"); |
498 snprintf(heater, 39, "NA"); |
396 snprintf(cooler, 39, "NA"); |
499 snprintf(cooler, 39, "NA"); |
397 snprintf(fan, 39, "NA"); |
500 snprintf(fan, 39, "NA"); |