thermferm/thermferm.c

changeset 182
dd69ccba8fa8
parent 179
417ee898fb02
child 184
db997a04fde3
equal deleted inserted replaced
181:4099412fca09 182:dd69ccba8fa8
27 #include "server.h" 27 #include "server.h"
28 #include "thermferm.h" 28 #include "thermferm.h"
29 #include "lcd-pcf8574.h" 29 #include "lcd-pcf8574.h"
30 #include "lcd-buffer.h" 30 #include "lcd-buffer.h"
31 #include "futil.h" 31 #include "futil.h"
32 #include "units.h"
33 #include "xutil.h" 32 #include "xutil.h"
34 33
35 34
36 char *current_unit = NULL; 35 char *current_unit = NULL;
37 int tempA = 80; 36 int tempA = 80;
99 { 98 {
100 mb_lcdClear(lcdHandle); 99 mb_lcdClear(lcdHandle);
101 setBacklight(0); 100 setBacklight(0);
102 } 101 }
103 #endif 102 #endif
103
104
105
106 int read_w1_28(char *address, int *val)
107 {
108 devices_list *device;
109 int tmp;
110
111 for (device = Config.devices; device; device = device->next) {
112 if (strcmp(address, device->uuid) == 0) {
113 tmp = device->value;
114 *val = tmp;
115 return device->present;
116 }
117 }
118
119 return DEVPRESENT_NO;
120 }
104 121
105 122
106 123
107 int main(int argc, char *argv[]) 124 int main(int argc, char *argv[])
108 { 125 {
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");
440 } 543 }
441 usleep(100000); 544 usleep(100000);
442 545
443 } while (run); 546 } while (run);
444 547
548 /*
549 * Stop units processing in a neat way
550 */
551 for (unit = Config.units; unit; unit = unit->next) {
552 /*
553 * Turn everything off
554 */
555 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = 0;
556 device_out(unit->heater_address, unit->heater_state);
557 device_out(unit->cooler_address, unit->cooler_state);
558 device_out(unit->fan_address, unit->fan_state);
559 syslog(LOG_NOTICE, "Stopped unit %s mode %s", unit->name, UNITMODE[unit->mode]);
560 }
561
445 if (debug) 562 if (debug)
446 fprintf(stdout, (char *)"Out of loop\n"); 563 fprintf(stdout, (char *)"Out of loop\n");
447 564
448 /* 565 /*
449 * Give threads time to cleanup 566 * Give threads time to cleanup

mercurial