# HG changeset patch # User Michiel Broek # Date 1431790770 -7200 # Node ID c92651a5496968dea0c7907b93c61134d9e470b0 # Parent 308f6a436779582c1fe058096a21792955d1cc71 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 diff -r 308f6a436779 -r c92651a54969 configure --- 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" diff -r 308f6a436779 -r c92651a54969 configure.ac --- 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) diff -r 308f6a436779 -r c92651a54969 thermferm/devices.c --- 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 { diff -r 308f6a436779 -r c92651a54969 thermferm/pid.c --- 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; + +} + + diff -r 308f6a436779 -r c92651a54969 thermferm/pid.h --- 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 diff -r 308f6a436779 -r c92651a54969 thermferm/rdconfig.c --- 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"))) { diff -r 308f6a436779 -r c92651a54969 thermferm/server.c --- 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 */ diff -r 308f6a436779 -r c92651a54969 thermferm/simulator.c --- 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 diff -r 308f6a436779 -r c92651a54969 thermferm/thermferm.c --- 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 */ diff -r 308f6a436779 -r c92651a54969 thermferm/thermferm.h --- 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 #include @@ -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 */ diff -r 308f6a436779 -r c92651a54969 www-thermferm/devices.php --- 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 .= ' '.PHP_EOL; + $se = ($f[1] == "IN_BIN")?" selected":""; + $outstr .= ' '.PHP_EOL; + $se = ($f[1] == "IN_ANALOG")?" selected":""; + $outstr .= ' '.PHP_EOL; + $se = ($f[1] == "OUT_BIN")?" selected":""; + $outstr .= ' '.PHP_EOL; + $se = ($f[1] == "OUT_ANALOG")?" selected":""; + $outstr .= ' '.PHP_EOL; } $outstr .= ' '.PHP_EOL; } diff -r 308f6a436779 -r c92651a54969 www-thermferm/units.php --- 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 .= ' seconds (0..720)'.PHP_EOL; $outstr .= ' '.PHP_EOL; } + if ($f[0] == "PIDH_IMAX") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Heat Maximum'.PHP_EOL; + $outstr .= ' % (1..100)'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDH_PGAIN") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Heat pGain'.PHP_EOL; + $outstr .= ' Proportional'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDH_IGAIN") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Heat iGain'.PHP_EOL; + $outstr .= ' Intergral'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDH_DGAIN") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Heat dGain'.PHP_EOL; + $outstr .= ' Derivative'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDH_IDLERANGE") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Heat Idle Range'.PHP_EOL; + $outstr .= ' °C (Heater margin)'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } if ($f[0] == "COOLER_ADDRESS") { $outstr .= ' '.PHP_EOL; $outstr .= ' Cooler Switch Address'.PHP_EOL; @@ -435,6 +477,36 @@ $outstr .= ' seconds (0..720)'.PHP_EOL; $outstr .= ' '.PHP_EOL; } + if ($f[0] == "PIDC_IMAX") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Cool Maximum'.PHP_EOL; + $outstr .= ' % (1..100)'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDC_PGAIN") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Cool pGain'.PHP_EOL; + $outstr .= ' Proportional'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDC_IGAIN") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Cool iGain'.PHP_EOL; + $outstr .= ' Intergral'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDC_DGAIN") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Cool dGain'.PHP_EOL; + $outstr .= ' Derivative'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } + if ($f[0] == "PIDC_IDLERANGE") { + $outstr .= ' '.PHP_EOL; + $outstr .= ' PID Cool Idle Range'.PHP_EOL; + $outstr .= ' °C (Cooler margin)'.PHP_EOL; + $outstr .= ' '.PHP_EOL; + } if ($f[0] == "FAN_ADDRESS") { $outstr .= ' '.PHP_EOL; $outstr .= ' Fan Switch Address'.PHP_EOL; @@ -543,36 +615,6 @@ $outstr .= ' °C'.PHP_EOL; $outstr .= ' '.PHP_EOL; } - if ($f[0] == "IDLE_RANGE_L") { - $outstr .= ' '.PHP_EOL; - $outstr .= ' Idle Range Low'.PHP_EOL; - $outstr .= ' °C (Cooler margin)'.PHP_EOL; - $outstr .= ' '.PHP_EOL; - } - if ($f[0] == "IDLE_RANGE_H") { - $outstr .= ' '.PHP_EOL; - $outstr .= ' Idle Range High'.PHP_EOL; - $outstr .= ' °C (Heater margin)'.PHP_EOL; - $outstr .= ' '.PHP_EOL; - } - if ($f[0] == "PID_KP") { - $outstr .= ' '.PHP_EOL; - $outstr .= ' PID Kp'.PHP_EOL; - $outstr .= ' Proportional'.PHP_EOL; - $outstr .= ' '.PHP_EOL; - } - if ($f[0] == "PID_KI") { - $outstr .= ' '.PHP_EOL; - $outstr .= ' PID Ki'.PHP_EOL; - $outstr .= ' Intergral'.PHP_EOL; - $outstr .= ' '.PHP_EOL; - } - if ($f[0] == "PID_KD") { - $outstr .= ' '.PHP_EOL; - $outstr .= ' PID Kd'.PHP_EOL; - $outstr .= ' Derivative'.PHP_EOL; - $outstr .= ' '.PHP_EOL; - } $i++; } } @@ -675,11 +717,16 @@ $outstr .= ''; $outstr .= ''; $outstr .= ''; - $outstr .= ''; - $outstr .= ''; - $outstr .= ''; - $outstr .= ''; - $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; + $outstr .= ''; $outstr .= ''; $outstr .= ''; $outstr .= ''; diff -r 308f6a436779 -r c92651a54969 www-thermferm/utilities.php --- 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 @@ * @@ -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 = "";