Added code to detect primary fermentation

Sat, 25 Oct 2014 21:08:47 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 25 Oct 2014 21:08:47 +0200
changeset 289
d810df0df36a
parent 288
8b99ab77262b
child 290
edb0b4da491a

Added code to detect primary fermentation

thermferm/rdconfig.c file | annotate | diff | comparison | revisions
thermferm/server.c file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
thermferm/thermferm.h file | annotate | diff | comparison | revisions
--- a/thermferm/rdconfig.c	Wed Oct 22 12:42:20 2014 +0200
+++ b/thermferm/rdconfig.c	Sat Oct 25 21:08:47 2014 +0200
@@ -442,6 +442,18 @@
 		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
 		    return 1;
 		}
+		if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PROF_PEAK_ABS", "%.3f", tmp3->prof_peak_abs)) < 0) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
+		if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PROF_PEAK_REL", "%.3f", tmp3->prof_peak_rel)) < 0) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
+		if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PROF_PRIMARY_DONE", "%d", (unsigned int)tmp3->prof_primary_done)) < 0) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
 	    }
 	    if ((rc = xmlTextWriterEndElement(writer)) < 0) {
 		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement");
@@ -849,7 +861,7 @@
     unit->version = 1;
     unit->uuid = unit->name = unit->air_address = unit->beer_address = unit->heater_address = \
 		 unit->cooler_address = unit->fan_address = unit->door_address = unit->profile = NULL;
-    unit->volume = 0.0;
+    unit->volume = unit->prof_peak_abs = unit->prof_peak_rel = 0.0;
     unit->air_temperature = unit->beer_temperature = unit->beer_set = unit->fridge_set = 20.0;
     unit->air_state = unit->beer_state = 1; // missing
     unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = unit->prof_state = 0;
@@ -859,7 +871,7 @@
     unit->temp_set_max = 30.0;
     unit->idle_rangeH = 1.0;
     unit->idle_rangeL = -1.0;
-    unit->prof_started = unit->prof_paused = (time_t)0;
+    unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0;
     unit->prof_percent = 0;
     unit->PID_err_old = unit->PID_I_err = 0.0;
 
@@ -1017,6 +1029,24 @@
 	    }
 	    xmlFree(key);
 	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROF_PEAK_ABS"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%f", &val) == 1)
+		unit->prof_peak_abs = val;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROF_PEAK_REL"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%f", &val) == 1)
+		unit->prof_peak_rel = val;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROF_PRIMARY_DONE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->prof_primary_done = ival;
+	    xmlFree(key);
+	}
 	cur = cur->next;
     }
 
--- a/thermferm/server.c	Wed Oct 22 12:42:20 2014 +0200
+++ b/thermferm/server.c	Sat Oct 25 21:08:47 2014 +0200
@@ -1447,7 +1447,7 @@
 	unit->name = xstrcpy(param);
 	unit->air_address = unit->beer_address = unit->heater_address = unit->cooler_address = \
 			    unit->fan_address = unit->door_address = unit->profile = NULL;
-	unit->volume = 0.0;
+	unit->volume = unit->prof_peak_abs = unit->prof_peak_rel = 0.0;
 	unit->air_state = unit->beer_state = 1;
 	unit->air_temperature = unit->beer_temperature = 20000;
 	unit->beer_set = unit->fridge_set = 20.0;
@@ -1458,7 +1458,7 @@
 	unit->temp_set_max = 30.0;
 	unit->idle_rangeH = 1.0;
 	unit->idle_rangeL = -1.0;
-	unit->prof_started = unit->prof_paused = (time_t)0;
+	unit->prof_started = unit->prof_paused = unit->prof_primary_done = (time_t)0;
 	unit->prof_percent = 0;
 	unit->PID_err_old = unit->PID_I_err = 0.0;
 
@@ -1554,6 +1554,9 @@
 		    srv_send((char *)"PROF_STATE,%s", PROFSTATE[unit->prof_state]);
 		}
 		srv_send((char *)"PROF_TARGET,%.3f", unit->prof_target);
+		srv_send((char *)"PROF_PEAK_ABS,%.3f", unit->prof_peak_abs);
+		srv_send((char *)"PROF_PEAK_REL,%.3f", unit->prof_peak_rel);
+		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,%.1f", unit->idle_rangeL);
@@ -1827,7 +1830,8 @@
 						case PROFILE_RUN:	if (unit->prof_state == PROFILE_OFF) {
 									    unit->prof_state = PROFILE_RUN;
 									    unit->prof_started = time(NULL);
-									    unit->prof_paused = 0;
+									    unit->prof_paused = unit->prof_primary_done = 0;
+									    unit->prof_peak_abs = unit->prof_peak_rel = 0.0;
 									    syslog(LOG_NOTICE, "Fermenter unit %s profile to RUN", unit->uuid);
 									}
 									break;
--- a/thermferm/thermferm.c	Wed Oct 22 12:42:20 2014 +0200
+++ b/thermferm/thermferm.c	Sat Oct 25 21:08:47 2014 +0200
@@ -605,7 +605,8 @@
 			if (key == KEY_ENTER) {
 			    current_unit->prof_state = PROFILE_RUN;
 			    current_unit->prof_started = time(NULL);
-			    current_unit->prof_paused = 0;
+			    current_unit->prof_paused = current_unit->prof_primary_done = 0;
+			    current_unit->prof_peak_abs = current_unit->prof_peak_rel = 0.0;
 			    syslog(LOG_NOTICE, "Profile started from the panel");
 			    go_menu(MENU_MODE_PROFILE);
 			}
@@ -1105,6 +1106,9 @@
 		     * unit->prof_state		- PROFILE_OFF|PROFILE_PAUSE|PROFILE_RUN|PROFILE_DONE
 		     * unit->prof_target	- Calculated target temperature.
 		     * unit->prof_paused	- Internal pause counter.
+		     * unit->prof_peak_abs	- Peak temperature of the beer.
+		     * unit->prof_peak_rel	- Peak temperature between beer and fridge.
+		     * unit->prof_primary_done	- time when primary fermentation was over the peak.
 		     */
 		    for (profile = Config.profiles; profile; profile = profile->next) {
 			if (strcmp(unit->profile, profile->uuid) == 0) {
@@ -1134,6 +1138,35 @@
 						    fprintf(stdout, "run_HMS=%d,%d,%d ", run_hours, run_minutes, run_seconds);
 
 						/*
+						 * Primary fermentation tests
+						 */
+						if ((unit->beer_temperature / 1000.0) > unit->prof_peak_abs)
+						    unit->prof_peak_abs = unit->beer_temperature / 1000.0;
+						if (((unit->beer_temperature - unit->air_temperature) / 1000.0) > unit->prof_peak_rel)
+						    unit->prof_peak_rel = (unit->beer_temperature - unit->air_temperature) / 1000.0;
+						if (unit->prof_primary_done == 0) {
+						    if (unit->cooler_address) {
+							/*
+							 * There is a cooler. If the difference between the beer and air temperature
+							 * drops we assume the primary fermentation is done.
+							 */
+							if (((unit->beer_temperature - unit->air_temperature) / 1000.0) < (unit->prof_peak_rel - 0.5)) {
+							    unit->prof_primary_done = time(NULL);
+							    syslog(LOG_NOTICE, "Profile `%s' primary fermentation is ready (cooler mode)", profile->name);
+							}
+						    } else {
+						    	/*
+						    	 * This method works if the unit has no cooling or if the profile allowd the
+						    	 * beer temperature to rise freely.
+						    	 */
+						    	if ((unit->beer_temperature / 1000.0) <  (unit->prof_peak_abs - 0.5)) {
+							    unit->prof_primary_done = time(NULL);
+							    syslog(LOG_NOTICE, "Profile `%s' primary fermentation is ready (free rise mode)", profile->name);
+						    	}
+						    }
+						}
+
+						/*
 						 * See how long this profile will take
 						 */
 						tot_minutes = 0;
--- a/thermferm/thermferm.h	Wed Oct 22 12:42:20 2014 +0200
+++ b/thermferm/thermferm.h	Sat Oct 25 21:08:47 2014 +0200
@@ -139,6 +139,9 @@
     float		prof_target;		/* Profile current target temp	*/
     time_t		prof_paused;		/* Profile total pause time	*/
     int			prof_percent;		/* Profile percentage done	*/
+    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	*/
     float		PID_I_err;		/* PID Intergal error		*/
     float		PID_err_old;		/* PID old error value		*/
 } units_list;

mercurial