Sat, 16 May 2015 17:39:30 +0200
Made the client-server protocol more robust. When a change to a unit is made using the web interface, the main process is stopped during the update. Splitted the PID in two PID's, one for heating and one for cooling. Adjusted the web edit scrreen for this, but there are still rough edges. Replaced the PID code, maybe this one works better for our purpose. The simulator air temperature changes on the simulator heater and cooler, but it is not realistic at all. This is a development version, do not use in production. The version is 0.3.0
configure | file | annotate | diff | comparison | revisions | |
configure.ac | file | annotate | diff | comparison | revisions | |
thermferm/devices.c | file | annotate | diff | comparison | revisions | |
thermferm/pid.c | file | annotate | diff | comparison | revisions | |
thermferm/pid.h | file | annotate | diff | comparison | revisions | |
thermferm/rdconfig.c | file | annotate | diff | comparison | revisions | |
thermferm/server.c | file | annotate | diff | comparison | revisions | |
thermferm/simulator.c | file | annotate | diff | comparison | revisions | |
thermferm/thermferm.c | file | annotate | diff | comparison | revisions | |
thermferm/thermferm.h | file | annotate | diff | comparison | revisions | |
www-thermferm/devices.php | file | annotate | diff | comparison | revisions | |
www-thermferm/units.php | file | annotate | diff | comparison | revisions | |
www-thermferm/utilities.php | file | annotate | diff | comparison | revisions |
--- a/configure Thu May 14 22:03:35 2015 +0200 +++ b/configure Sat May 16 17:39:30 2015 +0200 @@ -2034,7 +2034,7 @@ PACKAGE="mbsePi-apps" -VERSION="0.2.13" +VERSION="0.3.0" COPYRIGHT="Copyright (C) 2014-2015 Michiel Broek, All Rights Reserved" CYEARS="2014-2015"
--- a/configure.ac Thu May 14 22:03:35 2015 +0200 +++ b/configure.ac Sat May 16 17:39:30 2015 +0200 @@ -8,7 +8,7 @@ dnl General settings dnl After changeing the version number, run autoconf! PACKAGE="mbsePi-apps" -VERSION="0.2.13" +VERSION="0.3.0" COPYRIGHT="Copyright (C) 2014-2015 Michiel Broek, All Rights Reserved" CYEARS="2014-2015" AC_SUBST(PACKAGE)
--- a/thermferm/devices.c Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/devices.c Sat May 16 17:39:30 2015 +0200 @@ -31,6 +31,12 @@ extern sys_config Config; extern int my_shutdown; +#ifdef USE_SIMULATOR + +extern int SIMcooling; +extern int SIMheating; + +#endif #ifdef HAVE_WIRINGPI_H @@ -351,7 +357,19 @@ #ifdef USE_SIMULATOR if ((device->type == DEVTYPE_SIM) && (device->direction == DEVDIR_OUT_BIN) && (device->present == DEVPRESENT_YES)) { - + if ((strcmp((char *)"SimCooler", device->address) == 0) || (strcmp((char *)"SimHeater", device->address) == 0)) { + if (value != device->value) { + syslog(LOG_NOTICE, "SIM %s value=%d", device->address, value); + if (debug) + fprintf(stdout, "SIM %s value=%d\n", device->address, value); + } + device->value = value; + device->timestamp = time(NULL); + if (strcmp((char *)"SimCooler", device->address) == 0) + SIMcooling = value; + if (strcmp((char *)"SimHeater", device->address) == 0) + SIMheating = value; + } } #endif } else {
--- a/thermferm/pid.c Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/pid.c Sat May 16 17:39:30 2015 +0200 @@ -24,27 +24,63 @@ #include "pid.h" -double UpdatePID(pid_var *pid, double error, double position) +void InitPID(pid_var *pid, int type) { - double pTerm, dTerm, iTerm; - - pTerm = pid->pGain * error; - - /* - * Calculate the integral state with appopriate limiting - */ - pid->iState += error; - if (pid->iState > pid->iMax) - pid->iState = pid->iMax; - else if (pid->iState < pid->iMin) - pid->iState = pid->iMin; - - iTerm = pid->iGain * pid->iState; - - dTerm = pid->dGain * (pid->dState - position); - pid->dState = position; - - return pTerm + dTerm + iTerm; + pid->Err = pid->ErrLast = pid->ErrLastLast = 0.0; + pid->Input = pid->InputD = pid->OutP = pid->InputLast = pid->SetP = 0.0; + pid->pGain = pid->iGain = pid->dGain = 0.0; + pid->idleRange = 0.4; + pid->Mode = PID_MODE_NONE; + pid->Type = type; + pid->iMax = 100.0; } + +void UpdatePID(pid_var *pid) +{ + if (pid->Mode == PID_MODE_AUTO) { + + pid->InputD = pid->Input + (pid->Input - pid->InputLast) * pid->dGain * PID_TIMES; + pid->InputLast = pid->Input; + if (pid->Type == PID_TYPE_HEAT) + pid->Err = pid->InputD - pid->SetP; + else + pid->Err = pid->SetP - pid->InputD; + + pid->OutP = pid->OutP + pid->pGain * (pid->Err - pid->ErrLast + pid->iGain * pid->Err + pid->dGain * (pid->Err - pid->ErrLast * 2 + pid->ErrLastLast)); + pid->ErrLastLast = pid->ErrLast; + pid->ErrLast = pid->Err; + + } if (pid->Mode == PID_MODE_BOO) { + /* + * Mode Bang On Off + */ + pid->InputLast = pid->Input; + if (pid->Type == PID_TYPE_HEAT) + pid->ErrLastLast = pid->ErrLast = pid->Err = pid->SetP - pid->Input; + else + pid->ErrLastLast = pid->ErrLast = pid->Err = pid->Input - pid->SetP; + + if (pid->Err > 0.0) + pid->OutP = pid->iMax; + else + pid->OutP = 0.0; + + } else { + /* + * While in manual mode, stay ready for bumpless switch to + * auto. + */ + pid->InputLast = pid->Input; + pid->ErrLastLast = pid->ErrLast = pid->Err; + } + + if (pid->OutP > pid->iMax) + pid->OutP = pid->iMax; + if (pid->OutP < 0.0) + pid->OutP = 0.0; + +} + +
--- a/thermferm/pid.h Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/pid.h Sat May 16 17:39:30 2015 +0200 @@ -1,17 +1,37 @@ #ifndef PID_H #define PID_H +#define PID_MODE_NONE 0 /* Process control off */ +#define PID_MODE_AUTO 1 /* Process control auto */ +#define PID_MODE_BOO 2 /* Process control Bang On/Off */ + +#define PID_TYPE_HEAT 0 /* PID is used for heating */ +#define PID_TYPE_COOL 1 /* PID is used for cooling */ + +#define PID_TIMES 60 /* 60 calculations per minute */ + + typedef struct _pid_var { - double iState; /* Integrator state */ - double dState; /* Last measured value input */ - double iMax; /* Maximum allowable integrator state */ - double iMin; /* Minimum allowable integrator state */ - double iGain; /* Integral gain */ - double pGain; /* Proportional gain */ - double dGain; /* Derivative gain */ + double iMax; /* Maximum allowable integrator state */ + double iGain; /* Integral gain */ + double pGain; /* Proportional gain */ + double dGain; /* Derivative gain */ + double idleRange; /* Idle range */ + + double Input; /* Input value */ + double InputD; /* Process input plus derivative */ + double InputLast; /* Process input from last pass */ + double Err; /* Error, diff between input and set point */ + double ErrLast; /* Error from last pass */ + double ErrLastLast; /* Error from next last pass */ + double SetP; /* Set point */ + double OutP; /* Output of PID algorithm */ + int Mode; /* Value is 'PID_AUTO' if loop is automatic */ + int Type; /* Value is 'HEAT' or 'COOL' */ } pid_var; -double UpdatePID( pid_var *, double, double); +void InitPID( pid_var *, int); +void UpdatePID( pid_var *); #endif
--- a/thermferm/rdconfig.c Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/rdconfig.c Sat May 16 17:39:30 2015 +0200 @@ -37,7 +37,7 @@ const char DEVTYPE[8][6] = { "NA", "W1", "GPIO", "RC433", "DHT", "I2C", "SPI", "SIM" }; const char DEVPRESENT[4][6] = { "UNDEF", "NO", "YES", "ERROR" }; const char DEVDIR[7][11] = { "UNDEF", "IN_BIN", "OUT_BIN", "IN_ANALOG", "OUT_ANALOG", "OUT_PWM", "INTERN" }; - +const char PIDMODE[3][5] = { "NONE", "AUTO", "BOO" }; void killconfig(void) @@ -461,26 +461,6 @@ syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IDLE_RANGE_L", "%.2f", tmp3->idle_rangeL)) < 0) { - syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); - return 1; - } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IDLE_RANGE_H", "%.2f", tmp3->idle_rangeH)) < 0) { - syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); - return 1; - } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_KP", "%.2f", tmp3->PID_Kp)) < 0) { - syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); - return 1; - } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_KD", "%.2f", tmp3->PID_Kd)) < 0) { - syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); - return 1; - } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_KI", "%.2f", tmp3->PID_Ki)) < 0) { - syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); - return 1; - } if (tmp3->profile) { if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PROFILE", "%s", tmp3->profile)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); @@ -511,6 +491,130 @@ return 1; } } + if (tmp3->PID_cool) { + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_IMAX", "%.2f", tmp3->PID_cool->iMax)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_IGAIN", "%.2f", tmp3->PID_cool->iGain)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_PGAIN", "%.2f", tmp3->PID_cool->pGain)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_DGAIN", "%.2f", tmp3->PID_cool->dGain)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_IDLERANGE", "%.2f", tmp3->PID_cool->idleRange)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_INPUT", "%.2f", tmp3->PID_cool->Input)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_INPUTD", "%.2f", tmp3->PID_cool->InputD)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_INPUTLAST", "%.2f", tmp3->PID_cool->InputLast)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_ERR", "%.2f", tmp3->PID_cool->Err)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_ERRLAST", "%.2f", tmp3->PID_cool->ErrLast)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_ERRLASTLAST", "%.2f", tmp3->PID_cool->ErrLastLast)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_SETP", "%.2f", tmp3->PID_cool->SetP)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_OUTP", "%.2f", tmp3->PID_cool->OutP)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_MODE", "%s", PIDMODE[tmp3->PID_cool->Mode])) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDC_TYPE", "COOL")) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + } + if (tmp3->PID_heat) { + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_IMAX", "%.2f", tmp3->PID_heat->iMax)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_IDLERANGE", "%.2f", tmp3->PID_heat->idleRange)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_IGAIN", "%.2f", tmp3->PID_heat->iGain)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_PGAIN", "%.2f", tmp3->PID_heat->pGain)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_DGAIN", "%.2f", tmp3->PID_heat->dGain)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_INPUT", "%.2f", tmp3->PID_heat->Input)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_INPUTD", "%.2f", tmp3->PID_heat->InputD)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_INPUTLAST", "%.2f", tmp3->PID_heat->InputLast)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_ERR", "%.2f", tmp3->PID_heat->Err)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_ERRLAST", "%.2f", tmp3->PID_heat->ErrLast)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_ERRLASTLAST", "%.2f", tmp3->PID_heat->ErrLastLast)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_SETP", "%.2f", tmp3->PID_heat->SetP)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_OUTP", "%.2f", tmp3->PID_heat->OutP)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_MODE", "%s", PIDMODE[tmp3->PID_heat->Mode])) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PIDH_TYPE", "HEAT")) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + } if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; @@ -929,11 +1033,12 @@ unit->heater_usage = unit->cooler_usage = unit->fan_usage = unit->light_usage = 0; unit->temp_set_min = 1.0; unit->temp_set_max = 30.0; - unit->idle_rangeH = 1.0; - unit->idle_rangeL = -1.0; unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0; unit->prof_percent = 0; - unit->PID_dState = unit->PID_iState = unit->PID_Kp = unit->PID_Kd = unit->PID_Ki = 0.0; + unit->PID_cool = (pid_var *)malloc(sizeof(pid_var)); + unit->PID_heat = (pid_var *)malloc(sizeof(pid_var)); + InitPID(unit->PID_cool, PID_TYPE_COOL); + InitPID(unit->PID_heat, PID_TYPE_HEAT); cur = cur->xmlChildrenNode; while (cur != NULL) { @@ -1088,34 +1193,198 @@ unit->temp_set_max = val; xmlFree(key); } - if ((!xmlStrcmp(cur->name, (const xmlChar *)"IDLE_RANGE_L"))) { - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (sscanf((const char *)key, "%f", &val) == 1) - unit->idle_rangeL = val; - xmlFree(key); - } - if ((!xmlStrcmp(cur->name, (const xmlChar *)"IDLE_RANGE_H"))) { - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (sscanf((const char *)key, "%f", &val) == 1) - unit->idle_rangeH = val; - xmlFree(key); - } if ((!xmlStrcmp(cur->name, (const xmlChar *)"PID_KP"))) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if (sscanf((const char *)key, "%f", &val) == 1) - unit->PID_Kp = val; + unit->PID_cool->pGain = unit->PID_heat->pGain = val; /* Upgrade config */ xmlFree(key); } if ((!xmlStrcmp(cur->name, (const xmlChar *)"PID_KD"))) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if (sscanf((const char *)key, "%f", &val) == 1) - unit->PID_Kd = val; + unit->PID_cool->dGain = unit->PID_heat->dGain = val; /* Upgrade config */ xmlFree(key); } if ((!xmlStrcmp(cur->name, (const xmlChar *)"PID_KI"))) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if (sscanf((const char *)key, "%f", &val) == 1) - unit->PID_Ki = val; + unit->PID_cool->iGain = unit->PID_heat->iGain = val; /* Upgrade config */ + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_IMAX"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->iMax = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_IDLERANGE"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->idleRange = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_IGAIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->iGain = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_PGAIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->pGain = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_DGAIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->dGain = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_INPUT"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->Input = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_INPUTD"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->InputD = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_INPUTLAST"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->InputLast = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_ERR"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->Err = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_ERRLAST"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->ErrLast = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_ERRLASTLAST"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->ErrLastLast = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_SETP"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->SetP = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_OUTP"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_cool->OutP = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDC_MODE"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + for (i = 0; i < 3; i++) { + if (! xmlStrcmp(key, (const xmlChar *)PIDMODE[i])) { + unit->PID_cool->Mode = i; + break; + } + } + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_IMAX"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->iMax = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_IDLERANGE"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->idleRange = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_IGAIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->iGain = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_PGAIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->pGain = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_DGAIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->dGain = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_INPUT"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->Input = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_INPUTD"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->InputD = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_INPUTLAST"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->InputLast = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_ERR"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->Err = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_ERRLAST"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->ErrLast = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_ERRLASTLAST"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->ErrLastLast = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_SETP"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->SetP = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_OUTP"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->PID_heat->OutP = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PIDH_MODE"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + for (i = 0; i < 3; i++) { + if (! xmlStrcmp(key, (const xmlChar *)PIDMODE[i])) { + unit->PID_heat->Mode = i; + break; + } + } xmlFree(key); } if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROFILE"))) {
--- a/thermferm/server.c Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/server.c Sat May 16 17:39:30 2015 +0200 @@ -112,6 +112,50 @@ /* + * Argument is a buffer of size SS_BUFSIZE. + * Return -1 if error, else the number of received + * character. \n is line end, ignore \r. + */ +int srv_recv(char *buffer) +{ + int bytesloaded = 0; + ssize_t ret; + unsigned char buf; + socklen_t fromlen; + + memset(buffer, 0, SS_BUFSIZE); + + while(1) { + /* + * read a single byte + */ + fromlen = sizeof(peeraddr_in); + ret = recvfrom(s, &buf, 1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + if (ret < 1) { + syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); + srv_send((char *)"518 recfrom(): %s", strerror(errno)); + return -1; /* error */ + } + + if (buf == '\n') + break; + + if (buf != '\r') { + buffer[bytesloaded] = buf; + bytesloaded++; + } + } + + if (debug) { + syslog(LOG_NOTICE, "recv: %d `%s'", bytesloaded, buffer); + fprintf(stdout, "recv: %d `%s'\n", bytesloaded, buffer); + } + return bytesloaded; +} + + + +/* * Update the device inuse counter. */ void device_count(int plus, char *uuid) @@ -578,7 +622,6 @@ { char *opt, *param, *kwd, *val, ibuf[SS_BUFSIZE]; devices_list *device, *tmpd; - socklen_t fromlen; int i, rc, rlen, ival; uuid_t uu; @@ -711,31 +754,11 @@ for (device = Config.devices; device; device = device->next) { if (strcmp(device->uuid, param) == 0) { while (1) { - memset((char *)&ibuf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); - if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - srv_send((char *)"518 recfrom(): %s", strerror(errno)); + rlen = srv_recv(ibuf); + if (rlen == -1) { return 1; } - for (i = 0; i < strlen(ibuf); i++) { - if (ibuf[i] == '\n') - ibuf[i] = '\0'; - if (ibuf[i] == '\r') - ibuf[i] = '\0'; - } - for (i = strlen(ibuf) -1; i > 0; i--) { - if (ibuf[i] == ' ') - ibuf[i] = '\0'; - else - break; - } if (strlen(ibuf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); - fprintf(stdout, "recv: \"%s\"\n", ibuf); - } if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Device record"); return 0; @@ -908,8 +931,7 @@ int cmd_global(char *buf) { char *opt, *kwd, *val, ibuf[SS_BUFSIZE]; - int ival, i, rlen; - socklen_t fromlen; + int ival, rlen; opt = strtok(buf, " \0"); opt = strtok(NULL, "\0"); @@ -941,31 +963,11 @@ if (strcmp(opt, (char *)"PUT") == 0) { while (1) { - memset((char *)&ibuf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + rlen = srv_recv(ibuf); if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - srv_send((char *)"518 recfrom(): %s", strerror(errno)); return 1; } - for (i = 0; i < strlen(ibuf); i++) { - if (ibuf[i] == '\n') - ibuf[i] = '\0'; - if (ibuf[i] == '\r') - ibuf[i] = '\0'; - } - for (i = strlen(ibuf) -1; i > 0; i--) { - if (ibuf[i] == ' ') - ibuf[i] = '\0'; - else - break; - } if (strlen(ibuf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); - fprintf(stdout, "recv: \"%s\"\n", ibuf); - } if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Global record"); return 0; @@ -1206,9 +1208,8 @@ int cmd_profile(char *buf) { char ibuf[SS_BUFSIZE], *sstep, *rest, *targ, *param, *kwd, *val; - int i, j, rlen, istep, irest; + int j, rlen, istep, irest; float ftarg, fval; - socklen_t fromlen; char *opt; profiles_list *profile, *tmpp; prof_step *step, *olds; @@ -1298,31 +1299,11 @@ for (profile = Config.profiles; profile; profile = profile->next) { if (strcmp(profile->uuid, param) == 0) { while (1) { - memset((char *)&ibuf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + rlen = srv_recv(ibuf); if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - srv_send((char *)"518 recfrom(): %s", strerror(errno)); return 1; } - for (i = 0; i < strlen(ibuf); i++) { - if (ibuf[i] == '\n') - ibuf[i] = '\0'; - if (ibuf[i] == '\r') - ibuf[i] = '\0'; - } - for (i = strlen(ibuf) -1; i > 0; i--) { - if (ibuf[i] == ' ') - ibuf[i] = '\0'; - else - break; - } if (strlen(ibuf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); - fprintf(stdout, "recv: \"%s\"\n", ibuf); - } if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Profile record"); return 0; @@ -1384,31 +1365,11 @@ j = 0; while (1) { - memset((char *)&ibuf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + rlen = srv_recv(ibuf); if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - srv_send((char *)"518 recfrom(): %s", strerror(errno)); return 1; } else { - for (i = 0; i < strlen(ibuf); i++) { - if (ibuf[i] == '\n') - ibuf[i] = '\0'; - if (ibuf[i] == '\r') - ibuf[i] = '\0'; - } - for (i = strlen(ibuf) -1; i > 0; i--) { - if (ibuf[i] == ' ') - ibuf[i] = '\0'; - else - break; - } if (strlen(ibuf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); - fprintf(stdout, "recv: \"%s\"\n", ibuf); - } if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Profile steps"); @@ -1506,8 +1467,7 @@ { char *opt, *param, *kwd, *val, ibuf[SS_BUFSIZE]; simulator_list *simulator, *tmps; - socklen_t fromlen; - int i, rc, rlen, ival; + int rc, rlen, ival; float fval; uuid_t uu; @@ -1624,31 +1584,11 @@ for (simulator = Config.simulators; simulator; simulator = simulator->next) { if (strcmp(simulator->uuid, param) == 0) { while (1) { - memset((char *)&ibuf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + rlen = srv_recv(ibuf); if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - srv_send((char *)"518 recfrom(): %s", strerror(errno)); return 1; } - for (i = 0; i < strlen(ibuf); i++) { - if (ibuf[i] == '\n') - ibuf[i] = '\0'; - if (ibuf[i] == '\r') - ibuf[i] = '\0'; - } - for (i = strlen(ibuf) -1; i > 0; i--) { - if (ibuf[i] == ' ') - ibuf[i] = '\0'; - else - break; - } if (strlen(ibuf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); - fprintf(stdout, "recv: \"%s\"\n", ibuf); - } if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Simulator record"); return 0; @@ -1820,6 +1760,12 @@ if (current->profile) free(current->profile); current->profile = NULL; + if (current->PID_cool) + free(current->PID_cool); + current->PID_cool = NULL; + if (current->PID_heat) + free(current->PID_heat); + current->PID_heat = NULL; free(current); return 1; } else { @@ -1854,6 +1800,12 @@ if (current->profile) free(current->profile); current->profile = NULL; + if (current->PID_cool) + free(current->PID_cool); + current->PID_cool = NULL; + if (current->PID_heat) + free(current->PID_heat); + current->PID_heat = NULL; previous->next = current->next; free(current); current = previous->next; @@ -1881,7 +1833,6 @@ char *opt, *param = NULL, *kwd, *val, ibuf[SS_BUFSIZE]; units_list *unit, *tmpu; uuid_t uu; - socklen_t fromlen; int ival, i, rc, rlen; float fval; @@ -1931,11 +1882,12 @@ unit->heater_usage = unit->cooler_usage = unit->fan_usage = unit->light_usage = 0; unit->temp_set_min = 1.0; unit->temp_set_max = 30.0; - unit->idle_rangeH = 1.0; - unit->idle_rangeL = -1.0; unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0; unit->prof_percent = 0; - unit->PID_dState = unit->PID_iState = unit->PID_Kp = unit->PID_Kd = unit->PID_Ki = 0.0; + unit->PID_cool = (pid_var *)malloc(sizeof(pid_var)); + unit->PID_heat = (pid_var *)malloc(sizeof(pid_var)); + InitPID(unit->PID_cool, PID_TYPE_COOL); + InitPID(unit->PID_heat, PID_TYPE_HEAT); /* * Block main process @@ -2011,10 +1963,24 @@ srv_send((char *)"HEATER_STATE,%d", unit->heater_state); srv_send((char *)"HEATER_DELAY,%d", unit->heater_delay); srv_send((char *)"HEATER_USAGE,%d", unit->heater_usage); + if (unit->PID_heat) { + srv_send((char *)"PIDH_IMAX,%.1f", unit->PID_heat->iMax); + srv_send((char *)"PIDH_PGAIN,%.2f", unit->PID_heat->pGain); + srv_send((char *)"PIDH_IGAIN,%.2f", unit->PID_heat->iGain); + srv_send((char *)"PIDH_DGAIN,%.2f", unit->PID_heat->dGain); + srv_send((char *)"PIDH_IDLERANGE,%.2f", unit->PID_heat->idleRange); + } srv_send((char *)"COOLER_ADDRESS,%s", unit->cooler_address); srv_send((char *)"COOLER_STATE,%d", unit->cooler_state); srv_send((char *)"COOLER_DELAY,%d", unit->cooler_delay); srv_send((char *)"COOLER_USAGE,%d", unit->cooler_usage); + if (unit->PID_cool) { + srv_send((char *)"PIDC_IMAX,%.1f", unit->PID_cool->iMax); + srv_send((char *)"PIDC_PGAIN,%.2f", unit->PID_cool->pGain); + srv_send((char *)"PIDC_IGAIN,%.2f", unit->PID_cool->iGain); + srv_send((char *)"PIDC_DGAIN,%.2f", unit->PID_cool->dGain); + srv_send((char *)"PIDC_IDLERANGE,%.2f", unit->PID_cool->idleRange); + } srv_send((char *)"FAN_ADDRESS,%s", unit->fan_address); srv_send((char *)"FAN_STATE,%d", unit->fan_state); srv_send((char *)"FAN_DELAY,%d", unit->fan_delay); @@ -2043,11 +2009,6 @@ srv_send((char *)"PROF_PRIMARY_DONE,%d", (int)unit->prof_primary_done); srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min); srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max); - srv_send((char *)"IDLE_RANGE_L,%.2f", unit->idle_rangeL); - srv_send((char *)"IDLE_RANGE_H,%.2f", unit->idle_rangeH); - srv_send((char *)"PID_KP,%.2f", unit->PID_Kp); - srv_send((char *)"PID_KI,%.2f", unit->PID_Ki); - srv_send((char *)"PID_KD,%.2f", unit->PID_Kd); srv_send((char *)"."); return 1; } @@ -2057,36 +2018,28 @@ } if (strcmp(opt, (char *)"PUT") == 0) { + /* + * Block main process + */ + run_pause = TRUE; + for (;;) { + usleep(100000); + if (run_hold) + break; + } + for (unit = Config.units ; unit; unit = unit->next) { if (strcmp(unit->uuid, param) == 0) { while (1) { - memset((char *)&ibuf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + rlen = srv_recv(ibuf); if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - srv_send((char *)"518 recfrom(): %s", strerror(errno)); + run_pause = FALSE; return 1; } - for (i = 0; i < strlen(ibuf); i++) { - if (ibuf[i] == '\n') - ibuf[i] = '\0'; - if (ibuf[i] == '\r') - ibuf[i] = '\0'; - } - for (i = strlen(ibuf) -1; i > 0; i--) { - if (ibuf[i] == ' ') - ibuf[i] = '\0'; - else - break; - } if (strlen(ibuf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); - fprintf(stdout, "recv: \"%s\"\n", ibuf); - } if (strcmp(ibuf, (char *)".") == 0) { srv_send((char *)"219 Accepted Unit record"); + run_pause = FALSE; return 0; } kwd = strtok(ibuf, ",\0"); @@ -2281,7 +2234,8 @@ syslog(LOG_NOTICE, "Fermenter unit %s mode %s to %s", unit->uuid, UNITMODE[unit->mode], UNITMODE[i]); unit->mode = i; /* Allways turn everything off after a mode change */ - unit->PID_iState = unit->PID_dState = 0.0; + unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = 0; unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; device_out(unit->heater_address, unit->heater_state); @@ -2313,25 +2267,74 @@ unit->beer_set = fval; } - } else if (val && (strcmp(kwd, (char *)"PID_KP") == 0)) { + } else if (val && (strcmp(kwd, (char *)"PIDC_IMAX") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_cool->iMax != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_cool iGain %.1f to %.1f", unit->uuid, unit->PID_cool->iMax, fval); + unit->PID_cool->iMax = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDC_PGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { - if (unit->PID_Kp != fval) - syslog(LOG_NOTICE, "Fermenter unit %s PID Kp %.2f to %.2f", unit->uuid, unit->PID_Kp, fval); - unit->PID_Kp = fval; + if (unit->PID_cool->pGain != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_cool pGain %.2f to %.2f", unit->uuid, unit->PID_cool->pGain, fval); + unit->PID_cool->pGain = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDC_DGAIN") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_cool->dGain != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_cool dGain %.2f to %.2f", unit->uuid, unit->PID_cool->dGain, fval); + unit->PID_cool->dGain = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDC_IGAIN") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_cool->iGain != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_cool iGain %.2f to %.2f", unit->uuid, unit->PID_cool->iGain, fval); + unit->PID_cool->iGain = fval; } - } else if (val && (strcmp(kwd, (char *)"PID_KD") == 0)) { + } else if (val && (strcmp(kwd, (char *)"PIDC_IDLERANGE") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_cool->idleRange != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_cool idleRange %.2f to %.2f", unit->uuid, unit->PID_cool->idleRange, fval); + unit->PID_cool->idleRange = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDH_IMAX") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { - if (unit->PID_Kd != fval) - syslog(LOG_NOTICE, "Fermenter unit %s PID Kd %.2f to %.2f", unit->uuid, unit->PID_Kd, fval); - unit->PID_Kd = fval; + if (unit->PID_heat->iMax != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_heat iGain %.1f to %.1f", unit->uuid, unit->PID_heat->iMax, fval); + unit->PID_heat->iMax = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDH_PGAIN") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_heat->pGain != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_heat pGain %.2f to %.2f", unit->uuid, unit->PID_heat->pGain, fval); + unit->PID_heat->pGain = fval; } - - } else if (val && (strcmp(kwd, (char *)"PID_KI") == 0)) { + + } else if (val && (strcmp(kwd, (char *)"PIDH_DGAIN") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_heat->dGain != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_heat dGain %.2f to %.2f", unit->uuid, unit->PID_heat->dGain, fval); + unit->PID_heat->dGain = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDH_IGAIN") == 0)) { if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { - if (unit->PID_Ki != fval) - syslog(LOG_NOTICE, "Fermenter unit %s PID Ki %.2f to %.2f", unit->uuid, unit->PID_Ki, fval); - unit->PID_Ki = fval; + if (unit->PID_heat->iGain != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PIH_heat iGain %.2f to %.2f", unit->uuid, unit->PID_heat->iGain, fval); + unit->PID_heat->iGain = fval; + } + + } else if (val && (strcmp(kwd, (char *)"PIDH_IDLERANGE") == 0)) { + if ((sscanf(val, "%f", &fval) == 1) && (fval >= 0.0)) { + if (unit->PID_heat->idleRange != fval) + syslog(LOG_NOTICE, "Fermenter unit %s PID_heat idleRange %.2f to %.2f", unit->uuid, unit->PID_heat->idleRange, fval); + unit->PID_heat->idleRange = fval; } } else if (strcmp(kwd, (char *)"PROFILE") == 0) { @@ -2351,7 +2354,8 @@ /* * Reset all output devices */ - unit->PID_iState = unit->PID_dState = 0.0; + unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = 0; unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; device_out(unit->heater_address, unit->heater_state); @@ -2411,20 +2415,6 @@ unit->temp_set_max = fval; } - } else if (val && (strcmp(kwd, (char *)"IDLE_RANGE_L") == 0)) { - if (sscanf(val, "%f", &fval) == 1) { - if (unit->idle_rangeL != fval) - syslog(LOG_NOTICE, "Fermenter unit %s idle range low %.2f to %.2f", unit->uuid, unit->idle_rangeL, fval); - unit->idle_rangeL = fval; - } - - } else if (val && (strcmp(kwd, (char *)"IDLE_RANGE_H") == 0)) { - if (sscanf(val, "%f", &fval) == 1) { - if (unit->idle_rangeH != fval) - syslog(LOG_NOTICE, "Fermenter unit %s idle range high %.2f to %.2f", unit->uuid, unit->idle_rangeH, fval); - unit->idle_rangeH = fval; - } - } } } @@ -2432,6 +2422,7 @@ } } srv_send((char *)"440 No such unit"); + run_pause = FALSE; return 1; } @@ -2444,33 +2435,11 @@ void cmd_server(void) { char buf[SS_BUFSIZE]; - int i, rlen; - socklen_t fromlen; + int rlen; - memset((char *)&buf, 0, SS_BUFSIZE); - fromlen = sizeof(peeraddr_in); - rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); - if (rlen == -1) { - syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); - } else { - for (i = 0; i < strlen(buf); i++) { - if (buf[i] == '\n') - buf[i] = '\0'; - if (buf[i] == '\r') - buf[i] = '\0'; - } - for (i = strlen(buf) -1; i > 0; i--) { - if (buf[i] == ' ') - buf[i] = '\0'; - else - break; - } + rlen = srv_recv(buf); + if (rlen != -1) { if (strlen(buf)) { - if (debug) { - syslog(LOG_NOTICE, "recv: \"%s\"", buf); - fprintf(stdout, "recv: \"%s\"\n", buf); - } - /* * Process commands from the client */
--- a/thermferm/simulator.c Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/simulator.c Sat May 16 17:39:30 2015 +0200 @@ -29,6 +29,8 @@ extern int debug; extern sys_config Config; +int SIMcooling = 0; +int SIMheating = 0; #ifdef HAVE_WIRINGPI_H @@ -78,12 +80,18 @@ * the plate is warmer then the air, calculate the cooling down temperature. * Finally, calculate the new air and plate temperature. */ + if (SIMheating) { + simulator->air_temperature += 0.01; + } /* * If cooling, calculate temperature of the cooling plate. If cooling is off but * the plate is colder then the air, calculate the warming up temperature. * Finsally, calculate the new air and plate temperature. */ + if (SIMcooling) { + simulator->air_temperature -= 0.01; + } /* * Calculate the extra beer temperatur rise to simulate the heat produced by the
--- a/thermferm/thermferm.c Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/thermferm.c Sat May 16 17:39:30 2015 +0200 @@ -841,7 +841,6 @@ prof_step *step; int rc, run = 1, seconds = 0, minutes = 0, temp, deviation; int run_seconds, run_minutes, run_hours, tot_minutes; - float sp, pv, P_err = 0.0, Out; #ifdef HAVE_WIRINGPI_H struct tm *tm; int row, key; @@ -850,7 +849,6 @@ #endif int current_step, valid_step, time_until_now; float previous_target; - pid_var *pid; if (lockprog((char *)"thermferm")) { @@ -926,17 +924,17 @@ unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; if (unit->mode == UNITMODE_PROFILE) { if (!unit->profile) - syslog(LOG_NOTICE, "Starting unit %s in profile mode, no profile defined.", unit->name); + syslog(LOG_NOTICE, "Starting unit `%s' in profile mode, no profile defined.", unit->name); else - syslog(LOG_NOTICE, "Starting unit %s in profile state %s.", unit->name, PROFSTATE[unit->prof_state]); + syslog(LOG_NOTICE, "Starting unit `%s' in profile state %s.", unit->name, PROFSTATE[unit->prof_state]); } else if (unit->mode == UNITMODE_BEER) { - syslog(LOG_NOTICE, "Starting unit %s beer cooler at %.1f degrees", unit->name, unit->beer_set); + syslog(LOG_NOTICE, "Starting unit `%s' beer cooler at %.1f degrees", unit->name, unit->beer_set); } else if (unit->mode == UNITMODE_FRIDGE) { - syslog(LOG_NOTICE, "Starting unit %s as refridgerator at %.1f degrees", unit->name, unit->fridge_set); + syslog(LOG_NOTICE, "Starting unit `%s' as refridgerator at %.1f degrees", unit->name, unit->fridge_set); } else if (unit->mode == UNITMODE_NONE) { - syslog(LOG_NOTICE, "Starting unit %s in inactive state", unit->name); + syslog(LOG_NOTICE, "Starting unit `%s' in inactive state", unit->name); } else { - syslog(LOG_NOTICE, "Starting unit %s in off state", unit->name); + syslog(LOG_NOTICE, "Starting unit `%s' in off state", unit->name); } } @@ -1379,80 +1377,63 @@ * Temperature control in this unit */ if ((unit->mode == UNITMODE_FRIDGE) || (unit->mode == UNITMODE_BEER) || (unit->mode == UNITMODE_PROFILE)) { - int usePid = TRUE; - sp = unit->beer_set; - pv = unit->beer_temperature / 1000.0; + /* + * Set both PID's to their input values. + */ + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; if (unit->mode == UNITMODE_FRIDGE) { - sp = unit->fridge_set; - pv = unit->air_temperature / 1000.0; - usePid = FALSE; + unit->PID_cool->SetP = unit->PID_heat->SetP = unit->fridge_set; + unit->PID_cool->Input = unit->PID_heat->Input = unit->air_temperature / 1000.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_BOO; + } else if (unit->mode == UNITMODE_BEER) { + unit->PID_cool->SetP = unit->PID_heat->SetP = unit->beer_set; + unit->PID_cool->Input = unit->PID_heat->Input = unit->beer_temperature / 1000.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_AUTO; } else if (unit->mode == UNITMODE_PROFILE) { - sp = unit->prof_target; - } - - P_err = sp - pv; - if (P_err < unit->idle_rangeH && P_err > unit->idle_rangeL && usePid == FALSE) { - P_err = 0.0; + unit->PID_cool->SetP = unit->PID_heat->SetP = unit->prof_target; + unit->PID_cool->Input = unit->PID_heat->Input = unit->beer_temperature / 1000.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_AUTO; } - if (usePid) { - /* - * PID controller compute - */ - pid = (pid_var *)malloc(sizeof(pid_var)); - pid->dState = unit->PID_dState; - pid->iState = unit->PID_iState; - pid->iMax = 100.0; - pid->iMin = -100.0; - pid->pGain = unit->PID_Kp; - pid->iGain = unit->PID_Ki; - pid->dGain = unit->PID_Kd; + /* + * PID controller compute + */ + if (unit->heater_address) { + UpdatePID(unit->PID_heat); - Out = UpdatePID(pid, P_err, pv); - - if (Out > 100.0) - Out = 100.0; - if (Out < -100.0) - Out = -100.0; + if (debug) + fprintf(stdout, "Heat: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f\n", + unit->PID_heat->SetP, unit->PID_heat->Input, unit->PID_heat->InputD, unit->PID_heat->Err, unit->PID_heat->OutP); + if (((unit->PID_heat->OutP >= 1) && unit->heater_address) || (seconds == 60) || unit->heater_state) { + syslog(LOG_NOTICE, "Heat: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f", + unit->PID_heat->SetP, unit->PID_heat->Input, unit->PID_heat->InputD, unit->PID_heat->Err, unit->PID_heat->OutP); + } + } + if (unit->cooler_address) { + UpdatePID(unit->PID_cool); if (debug) - fprintf(stdout, "sp=%.2f pv=%.2f dState=%.2f P_err=%.2f iState=%.2f Out=%.2f\n", - sp, pv, unit->PID_dState, P_err, unit->PID_iState, Out); - if (((Out >= 1) && unit->heater_address) || ((Out <= -1) && unit->cooler_address) || - (seconds == 60) || unit->heater_state || unit->cooler_state) { - syslog(LOG_NOTICE, "sp=%.2f pv=%.2f P_err=%.2f dState=%.2f iState=%.2f Out=%.2f", - sp, pv, P_err, unit->PID_dState, unit->PID_iState, Out); + fprintf(stdout, "Cool: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f\n", + unit->PID_cool->SetP, unit->PID_cool->Input, unit->PID_cool->InputD, unit->PID_cool->Err, unit->PID_cool->OutP); + if (((unit->PID_cool->OutP >= 1) && unit->cooler_address) || (seconds == 60) || unit->cooler_state) { + syslog(LOG_NOTICE, "Cool: sp=%.2f Input=%.2f InputD=%.2f Err=%.2f Out=%.2f", + unit->PID_cool->SetP, unit->PID_cool->Input, unit->PID_cool->InputD, unit->PID_cool->Err, unit->PID_cool->OutP); } + } - unit->PID_iState = pid->iState; - unit->PID_dState = pid->dState; - free(pid); - pid = NULL; - } else { - /* - * Simple temperature control - */ - if (P_err > 0) { - Out = 100.0; - } else if (P_err < 0) { - Out = -100.0; - } else { - Out = 0.0; - } -// if (((Out >= 1) && unit->heater_address) || ((Out <= -1) && unit->cooler_address) || -// (seconds == 60) || unit->heater_state || unit->cooler_state) { -// syslog(LOG_NOTICE, "sp=%.2f pv=%.2f P_err=%.2f Out=%.2f", sp, pv, P_err, Out); -// } + if (unit->PID_cool->OutP && unit->PID_heat->OutP) { + syslog(LOG_NOTICE, "Heat and Cool lockdown"); + unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; } if (unit->heater_address && ! unit->cooler_state) { - if (Out >= 1) { + if (unit->PID_heat->OutP >= 1) { if (unit->heater_wait < unit->heater_delay) { unit->heater_wait++; // syslog(LOG_NOTICE, "heater_wait + %d/%d", unit->heater_wait, unit->heater_delay); } else { - int power = round(Out); + int power = round(unit->PID_heat->OutP); if (unit->heater_state != power) { syslog(LOG_NOTICE, "Unit `%s' heater %d%% => %d%%", unit->name, unit->heater_state, power); unit->heater_state = power; @@ -1476,12 +1457,12 @@ } if (unit->cooler_address && ! unit->heater_state) { - if (Out <= -1) { + if (unit->PID_cool->OutP >= 1) { if (unit->cooler_wait < unit->cooler_delay) { unit->cooler_wait++; // syslog(LOG_NOTICE, "cooler_wait + %d/%d", unit->cooler_wait, unit->cooler_delay); } else { - int power = round(0 - Out); + int power = round(unit->PID_cool->OutP); if (unit->cooler_state != power) { syslog(LOG_NOTICE, "Unit `%s' cooler %d%% => %d%%", unit->name, unit->cooler_state, power); unit->cooler_state = power; @@ -1533,11 +1514,8 @@ else device_out(unit->fan_address, 0); } - } else { - P_err = 0.0; - unit->PID_iState = 0.0; - unit->PID_dState = 0.0; + unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; } /* fridge beer or profile mode */ } /* for units */
--- a/thermferm/thermferm.h Thu May 14 22:03:35 2015 +0200 +++ b/thermferm/thermferm.h Sat May 16 17:39:30 2015 +0200 @@ -6,6 +6,7 @@ #define FALSE 0 #include "../config.h" +#include "pid.h" #include <stdlib.h> #include <stdio.h> @@ -160,8 +161,6 @@ float fridge_set; /* Fridge temperature setting */ float temp_set_min; /* Minimum temperature */ float temp_set_max; /* Maximum temperature */ - float idle_rangeL; /* Idle temperature low */ - float idle_rangeH; /* Idle temperature high */ char *profile; /* Active profile uuid */ time_t prof_started; /* Profile start time */ int prof_state; /* Profile OFF|PAUSE|RUN|DONE */ @@ -171,11 +170,8 @@ float prof_peak_abs; /* Profile absolute peak temp */ float prof_peak_rel; /* Profile relative peak temp */ time_t prof_primary_done; /* Profile primary is done */ - double PID_iState; /* PID Integral state */ - double PID_dState; /* PID last measured value */ - float PID_Kp; /* PID Kp setting */ - float PID_Kd; /* PID Kd setting */ - float PID_Ki; /* PID Ki setting */ + pid_var *PID_cool; /* PID cooler */ + pid_var *PID_heat; /* PID heater */ } units_list; #define UNITMODE_OFF 0 /* Unit turned off */
--- a/www-thermferm/devices.php Thu May 14 22:03:35 2015 +0200 +++ b/www-thermferm/devices.php Sat May 16 17:39:30 2015 +0200 @@ -345,6 +345,14 @@ if ($type == "SIM") { $se = ($f[1] == "UNDEF")?" selected":""; $outstr .= ' <option value="UNDEF"'.$se.'>Undefined</option>'.PHP_EOL; + $se = ($f[1] == "IN_BIN")?" selected":""; + $outstr .= ' <option value="IN_BIN"'.$se.'>Binary input</option>'.PHP_EOL; + $se = ($f[1] == "IN_ANALOG")?" selected":""; + $outstr .= ' <option value="IN_ANALOG"'.$se.'>Analog input</option>'.PHP_EOL; + $se = ($f[1] == "OUT_BIN")?" selected":""; + $outstr .= ' <option value="OUT_BIN"'.$se.'>Binary output</option>'.PHP_EOL; + $se = ($f[1] == "OUT_ANALOG")?" selected":""; + $outstr .= ' <option value="OUT_ANALOG"'.$se.'>Analog output</option>'.PHP_EOL; } $outstr .= ' </select></td>'.PHP_EOL; }
--- a/www-thermferm/units.php Thu May 14 22:03:35 2015 +0200 +++ b/www-thermferm/units.php Sat May 16 17:39:30 2015 +0200 @@ -106,11 +106,16 @@ $cmd[] = "PSU_ADDRESS,".$_POST['PSUAddress']; $cmd[] = "TEMP_SET_MIN,".$_POST['TempSetMin']; $cmd[] = "TEMP_SET_MAX,".$_POST['TempSetMax']; - $cmd[] = "IDLE_RANGE_L,".$_POST['IdleRangeL']; - $cmd[] = "IDLE_RANGE_H,".$_POST['IdleRangeH']; - $cmd[] = "PID_KP,".$_POST['PID_Kp']; - $cmd[] = "PID_KD,".$_POST['PID_Kd']; - $cmd[] = "PID_KI,".$_POST['PID_Ki']; + $cmd[] = "PIDC_IMAX,".$_POST['PIDC_iMax']; + $cmd[] = "PIDC_PGAIN,".$_POST['PIDC_pGain']; + $cmd[] = "PIDC_DGAIN,".$_POST['PIDC_dGain']; + $cmd[] = "PIDC_IGAIN,".$_POST['PIDC_iGain']; + $cmd[] = "PIDC_IDLERANGE,".$_POST['PIDC_idleRange']; + $cmd[] = "PIDH_IMAX,".$_POST['PIDC_iMax']; + $cmd[] = "PIDH_PGAIN,".$_POST['PIDH_pGain']; + $cmd[] = "PIDH_DGAIN,".$_POST['PIDH_dGain']; + $cmd[] = "PIDH_IGAIN,".$_POST['PIDH_iGain']; + $cmd[] = "PIDH_IDLERANGE,".$_POST['PIDH_idleRange']; $cmd[] = "."; send_array($cmd); } @@ -134,11 +139,16 @@ unset($_POST['PSUAddress']); unset($_POST['TempSetMin']); unset($_POST['TempSetMax']); - unset($_POST['IdleRangeL']); - unset($_POST['IdleRangeH']); - unset($_POST['PID_Kp']); - unset($_POST['PID_Kd']); - unset($_POST['PID_Ki']); + unset($_POST['PIDC_iMax']); + unset($_POST['PIDC_pGain']); + unset($_POST['PIDC_dGain']); + unset($_POST['PIDC_iGain']); + unset($_POST['PIDC_idleRange']); + unset($_POST['PIDH_iMax']); + unset($_POST['PIDH_pGain']); + unset($_POST['PIDH_dGain']); + unset($_POST['PIDH_iGain']); + unset($_POST['PIDH_idleRange']); load('units.php'); } @@ -161,8 +171,8 @@ * 6 = TempSetMin < -5 or > 15 * 7 = HeaterDelay out of range * 8 = CoolerDelay out of range - * 9 = IdleRangeL out of range - * 10 = IdleRangeH out of range + * 9 = PIDC idleRange out of range + * 10 = PIDH idleRange out of range * 11 = LightDelay out of range * 12 = FanDelay out of range * 99 = Cancel key @@ -175,8 +185,10 @@ isset($_POST['BeerAddress']) && isset($_POST['HeaterAddress']) && isset($_POST['CoolerAddress']) && isset($_POST['LightAddress']) && isset($_POST['HeaterDelay']) && isset($_POST['CoolerDelay']) && isset($_POST['LightDelay']) && isset($_POST['PSUAddress']) && isset($_POST['FanAddress']) && isset($_POST['DoorAddress']) && isset($_POST['TempSetMin']) && isset($_POST['TempSetMax']) && - isset($_POST['PID_Kp']) && isset($_POST['PID_Kd']) && isset($_POST['PID_Ki']) && isset($_POST['FanDelay']) && - isset($_POST['IdleRangeL']) && isset($_POST['IdleRangeH']) && isset($_POST['key']) && isset($_POST['command'])) { + isset($_POST['PIDC_pGain']) && isset($_POST['PIDC_iGain']) && isset($_POST['PIDC_dGain']) && isset($_POST['PIDC_idleRange']) && + isset($_POST['PIDH_pGain']) && isset($_POST['PIDH_iGain']) && isset($_POST['PIDH_dGain']) && isset($_POST['PIDH_idleRange']) && + isset($_POST['PIDC_iMax']) && isset($_POST['PIDH_iMax']) && + isset($_POST['FanDelay']) && isset($_POST['key']) && isset($_POST['command'])) { if ($_POST['key'] == 'Cancel') return 99; @@ -212,10 +224,10 @@ if (($_POST['CoolerDelay'] < 0) || ($_POST['CoolerDelay'] > 720)) return 8; - if (($_POST['IdleRangeL'] > 0) || ($_POST['IdleRangeL'] < -5)) + if (($_POST['PIDC_idleRange'] < 0) || ($_POST['PIDC_idleRange'] > 5)) return 9; - if (($_POST['IdleRangeH'] < 0) || ($_POST['IdleRangeH'] > 5)) + if (($_POST['PIDH_idleRange'] < 0) || ($_POST['PIDH_idleRange'] > 5)) return 10; if (($_POST['LightDelay'] < 0) || ($_POST['LightDelay'] > 720)) @@ -266,9 +278,9 @@ break; case 8: $error = 'Cooler Delay must be bewteen 0 and 720 seconds'; break; - case 9: $error = 'Idle Range Low must be between -5 en 0'; + case 9: $error = 'PID cool Idle Range must be between 0 en 5'; break; - case 10: $error = 'Idle Range High must be between 0 and 5'; + case 10: $error = 'PID heat Idle Range must be between 0 and 5'; break; case 11: $error = 'Light Delay must be bewteen 0 and 720 seconds'; break; @@ -408,6 +420,36 @@ $outstr .= ' <td class="editfield"><input type="text" name="HeaterDelay" size="5" value="'.$f[1].'"> seconds (0..720)</td>'.PHP_EOL; $outstr .= ' </tr>'.PHP_EOL; } + if ($f[0] == "PIDH_IMAX") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Heat Maximum</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDH_iMax" size="6" value="'.$f[1].'"> % (1..100)</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDH_PGAIN") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Heat pGain</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDH_pGain" size="6" value="'.$f[1].'"> Proportional</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDH_IGAIN") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Heat iGain</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDH_iGain" size="6" value="'.$f[1].'"> Intergral</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDH_DGAIN") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Heat dGain</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDH_dGain" size="6" value="'.$f[1].'"> Derivative</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDH_IDLERANGE") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Heat Idle Range</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDH_idleRange" size="6" value="'.$f[1].'"> °C (Heater margin)</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } if ($f[0] == "COOLER_ADDRESS") { $outstr .= ' <tr class="editor">'.PHP_EOL; $outstr .= ' <td class="editname">Cooler Switch Address</td>'.PHP_EOL; @@ -435,6 +477,36 @@ $outstr .= ' <td class="editfield"><input type="text" name="CoolerDelay" size="5" value="'.$f[1].'"> seconds (0..720)</td>'.PHP_EOL; $outstr .= ' </tr>'.PHP_EOL; } + if ($f[0] == "PIDC_IMAX") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Cool Maximum</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDC_iMax" size="6" value="'.$f[1].'"> % (1..100)</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDC_PGAIN") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Cool pGain</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDC_pGain" size="6" value="'.$f[1].'"> Proportional</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDC_IGAIN") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Cool iGain</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDC_iGain" size="6" value="'.$f[1].'"> Intergral</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDC_DGAIN") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Cool dGain</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDC_dGain" size="6" value="'.$f[1].'"> Derivative</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } + if ($f[0] == "PIDC_IDLERANGE") { + $outstr .= ' <tr class="editor">'.PHP_EOL; + $outstr .= ' <td class="editname">PID Cool Idle Range</td>'.PHP_EOL; + $outstr .= ' <td class="editfield"><input type="text" name="PIDC_idleRange" size="6" value="'.$f[1].'"> °C (Cooler margin)</td>'.PHP_EOL; + $outstr .= ' </tr>'.PHP_EOL; + } if ($f[0] == "FAN_ADDRESS") { $outstr .= ' <tr class="editor">'.PHP_EOL; $outstr .= ' <td class="editname">Fan Switch Address</td>'.PHP_EOL; @@ -543,36 +615,6 @@ $outstr .= ' <td class="editfield"><input type="text" name="TempSetMax" size="5" value="'.$f[1].'"> °C</td>'.PHP_EOL; $outstr .= ' </tr>'.PHP_EOL; } - if ($f[0] == "IDLE_RANGE_L") { - $outstr .= ' <tr class="editor">'.PHP_EOL; - $outstr .= ' <td class="editname">Idle Range Low</td>'.PHP_EOL; - $outstr .= ' <td class="editfield"><input type="text" name="IdleRangeL" size="6" value="'.$f[1].'"> °C (Cooler margin)</td>'.PHP_EOL; - $outstr .= ' </tr>'.PHP_EOL; - } - if ($f[0] == "IDLE_RANGE_H") { - $outstr .= ' <tr class="editor">'.PHP_EOL; - $outstr .= ' <td class="editname">Idle Range High</td>'.PHP_EOL; - $outstr .= ' <td class="editfield"><input type="text" name="IdleRangeH" size="6" value="'.$f[1].'"> °C (Heater margin)</td>'.PHP_EOL; - $outstr .= ' </tr>'.PHP_EOL; - } - if ($f[0] == "PID_KP") { - $outstr .= ' <tr class="editor">'.PHP_EOL; - $outstr .= ' <td class="editname">PID Kp</td>'.PHP_EOL; - $outstr .= ' <td class="editfield"><input type="text" name="PID_Kp" size="6" value="'.$f[1].'"> Proportional</td>'.PHP_EOL; - $outstr .= ' </tr>'.PHP_EOL; - } - if ($f[0] == "PID_KI") { - $outstr .= ' <tr class="editor">'.PHP_EOL; - $outstr .= ' <td class="editname">PID Ki</td>'.PHP_EOL; - $outstr .= ' <td class="editfield"><input type="text" name="PID_Ki" size="6" value="'.$f[1].'"> Intergral</td>'.PHP_EOL; - $outstr .= ' </tr>'.PHP_EOL; - } - if ($f[0] == "PID_KD") { - $outstr .= ' <tr class="editor">'.PHP_EOL; - $outstr .= ' <td class="editname">PID Kd</td>'.PHP_EOL; - $outstr .= ' <td class="editfield"><input type="text" name="PID_Kd" size="6" value="'.$f[1].'"> Derivative</td>'.PHP_EOL; - $outstr .= ' </tr>'.PHP_EOL; - } $i++; } } @@ -675,11 +717,16 @@ $outstr .= '<input type="hidden" value="" name="PSUAdress">'; $outstr .= '<input type="hidden" value="1.0" name="TempSetMin">'; $outstr .= '<input type="hidden" value="30.0" name="TempSetMax">'; - $outstr .= '<input type="hidden" value="-1.0" name="IdleRangeL">'; - $outstr .= '<input type="hidden" value="1.0" name="IdleRangeH">'; - $outstr .= '<input type="hidden" value="4.0" name="PID_Kp">'; - $outstr .= '<input type="hidden" value="0.2" name="PID_Kd">'; - $outstr .= '<input type="hidden" value="1.0" name="PID_Ki">'; + $outstr .= '<input type="hidden" value="100" name="PIDC_iMax">'; + $outstr .= '<input type="hidden" value="4.0" name="PIDC_pGain">'; + $outstr .= '<input type="hidden" value="0.2" name="PIDC_dGain">'; + $outstr .= '<input type="hidden" value="1.0" name="PIDC_iGain">'; + $outstr .= '<input type="hidden" value="1.0" name="PIDC_idleRange">'; + $outstr .= '<input type="hidden" value="100" name="PIDH_iMax">'; + $outstr .= '<input type="hidden" value="4.0" name="PIDH_pGain">'; + $outstr .= '<input type="hidden" value="0.2" name="PIDH_dGain">'; + $outstr .= '<input type="hidden" value="1.0" name="PIDH_iGain">'; + $outstr .= '<input type="hidden" value="1.0" name="PIDH_idleRange">'; $outstr .= '<input type="hidden" value="testdata" name="action">'; $outstr .= '<input type="hidden" value="add" name="command">'; $outstr .= '<input type="hidden" value="00000000-0000-0000-0000-000000000000" name="UUID">';
--- a/www-thermferm/utilities.php Thu May 14 22:03:35 2015 +0200 +++ b/www-thermferm/utilities.php Sat May 16 17:39:30 2015 +0200 @@ -1,6 +1,6 @@ <?php /***************************************************************************** - * Copyright (C) 2014 + * Copyright (C) 2014-2015 * * Michiel Broek <mbroek at mbse dot eu> * @@ -49,7 +49,7 @@ if ($sock == false) { return ""; } - socket_write($sock, $command, 4096); + socket_write($sock, $command . "\r\n", 4096); $answer = ""; while (1) { @@ -78,8 +78,8 @@ } foreach($command as $cmd) { - socket_write($sock, $cmd, 4096); - usleep(20000); /* Give server time to recognize lines */ + socket_write($sock, $cmd . "\r\n", 4096); +// usleep(20000); /* Give server time to recognize lines */ } $answer = "";