thermferm/simulator.c

changeset 715
f5d85af156ab
parent 714
24749c296a50
child 716
5c30c8ef83a8
equal deleted inserted replaced
714:24749c296a50 715:f5d85af156ab
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with ThermFerm; see the file COPYING. If not, write to the Free 19 * along with ThermFerm; see the file COPYING. If not, write to the Free
20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *****************************************************************************/ 21 *****************************************************************************/
22 22
23 extern int debug;
24
23 #include "thermferm.h" 25 #include "thermferm.h"
26 #include "statetbl.h"
24 #include "delay.h" 27 #include "delay.h"
25 #include "xutil.h" 28 #include "xutil.h"
26 #include "websocket.h" 29 #include "websocket.h"
27 #include "simulator.h" 30 #include "simulator.h"
28 31
32 35
33 extern sys_config Config; 36 extern sys_config Config;
34 extern const char DEVPRESENT[4][6]; 37 extern const char DEVPRESENT[4][6];
35 38
36 int my_simulator_shutdown = 0; 39 int my_simulator_shutdown = 0;
37 int SIMcooling = 0; 40
38 int SIMheating = 0; 41
39 int SIMfan = 0; 42 static int simulate(void);
40 int SIMlight = 0;
41 43
42 44
43 /* 45 /*
44 * Return json data for one simulator 46 * Return json data for one simulator
45 */ 47 */
191 193
192 194
193 195
194 void *my_simulator_loop(void *threadid) 196 void *my_simulator_loop(void *threadid)
195 { 197 {
198 my_simulator_state = 1;
199 syslog(LOG_NOTICE, "Thread my_simulator_loop started");
200
201 /*
202 * Run the state machine
203 */
204 simulate();
205
206 syslog(LOG_NOTICE, "Thread my_simulator_loop stopped");
207 my_simulator_state = 0;
208 return 0;
209 }
210
211
212 SM_DECL(simulate, (char *)"simulator")
213 SM_STATES
214 Init,
215 Waiting,
216 Run,
217 Websocket
218 SM_NAMES
219 (char *)"Init",
220 (char *)"Waiting",
221 (char *)"run",
222 (char *)"Websocket"
223 SM_EDECL
196 simulator_list *simulator; 224 simulator_list *simulator;
197 time_t now, last = (time_t)0; 225 time_t now, last = (time_t)0;
198 int seconds = 0; 226 int seconds = 0;
199 double k_room_air, sqm_room_air, thick_room_air, air_heat_transfer; 227 double k_room_air, sqm_room_air, thick_room_air, air_heat_transfer;
200 double air_change, vhc_air = 0.00121; 228 double air_change, vhc_air = 0.00121;
201 229 double air_temp, beer_temp, chiller_temp;
202 my_simulator_state = 1; 230 bool changed = false;
203 syslog(LOG_NOTICE, "Thread my_simulator_loop started"); 231
232 SM_START(Init)
233
234 SM_STATE(Init)
204 235
205 for (simulator = Config.simulators; simulator; simulator = simulator->next) { 236 for (simulator = Config.simulators; simulator; simulator = simulator->next) {
206 /* 237 /*
207 * Heater and cooler have the air temperature 238 * Heater and cooler have the air temperature
208 */ 239 */
209 simulator->s_heat_temp = simulator->s_cool_temp = simulator->room_temperature; 240 simulator->s_heat_temp = simulator->s_cool_temp = simulator->room_temperature;
210 } 241 }
211 242 SM_PROCEED(Waiting);
212 for (;;) { 243
213 if (my_simulator_shutdown) 244 SM_STATE(Waiting)
214 break; 245
215 246 if (my_simulator_shutdown) {
216 now = time(NULL); 247 SM_SUCCESS;
217 if (now != last) { 248 }
218 last = now; 249 now = time(NULL);
250 if (now != last) {
251 last = now;
252 seconds++;
253 SM_PROCEED(Run);
254 }
255 mDelay(50L);
256
257 SM_STATE(Run)
258
259 changed = false;
260 for (simulator = Config.simulators; simulator; simulator = simulator->next) {
261 if (my_simulator_shutdown) {
262 SM_SUCCESS;
263 }
264
265 /*
266 * Copy to duplicates
267 */
268 air_temp = simulator->air_temperature;
269 beer_temp = simulator->beer_temperature;
270 chiller_temp = simulator->chiller_temperature;
271
272 /*
273 * First, calculate temperature difference between the room and the air in the
274 * fridge. We use the volume air to roughly calculate the total area between
275 * the in and outside. Calculate the effect and shift the air temperature towards
276 * the room temperature.
277 */
278 sqm_room_air = (cbrtl(simulator->volume_air) * cbrtl(simulator->volume_air) * 6) / 100; /* square meters all fridge sides */
279 thick_room_air = 0.04; /* 4 cm walls */
280 k_room_air = 0.03; /* Polystrene */
281 air_heat_transfer=(k_room_air * sqm_room_air * (simulator->room_temperature - air_temp)) / thick_room_air;
282 air_change = (air_heat_transfer / (vhc_air * ((simulator->volume_air - simulator->volume_beer) * 1000))) / 60.0;
283 air_temp += air_change;
284
285 /*
286 * If heating, calculate temperature of the heating plate. If heating is off but
287 * the plate is warmer then the air, calculate the cooling down temperature.
288 * Finally, calculate the new air and plate temperature.
289 */
290 if (simulator->heater_present == DEVPRESENT_YES && simulator->heater_power >= 50) {
291 if (simulator->s_heat_temp < simulator->heater_temp) {
292 simulator->s_heat_temp += 0.05;
293 if (simulator->s_heat_temp > simulator->air_temperature)
294 air_temp += ((simulator->s_heat_temp - air_temp) / 100.0);
295 }
296 } else {
219 /* 297 /*
220 * Each second 298 * Follow the air temperature
221 */ 299 */
222 seconds++; 300 simulator->s_heat_temp -= (simulator->s_heat_temp - air_temp) / 25.0;
223 301 }
224 for (simulator = Config.simulators; simulator; simulator = simulator->next) { 302
225 if (my_simulator_shutdown) 303 /*
226 break; 304 * If cooling, calculate temperature of the cooling plate. If cooling is off but
227 305 * the plate is colder then the air, calculate the warming up temperature.
228 /* 306 * Finsally, calculate the new air and plate temperature.
229 * First, calculate temperature difference between the room and the air in the 307 */
230 * fridge. We use the volume air to roughly calculate the total area between 308 if (simulator->cooler_present == DEVPRESENT_YES && simulator->cooler_power >= 50) {
231 * the in and outside. Calculate the effect and shift the air temperature towards 309 if (simulator->s_cool_temp > simulator->cooler_temp) {
232 * the room temperature. 310 simulator->s_cool_temp -= 0.05;
233 */ 311 if (simulator->s_cool_temp < air_temp)
234 sqm_room_air = (cbrtl(simulator->volume_air) * cbrtl(simulator->volume_air) * 6) / 100; /* square meters all fridge sides */ 312 air_temp -= ((air_temp - simulator->s_cool_temp) / 100.0);
235 thick_room_air = 0.04; /* 4 cm walls */
236 k_room_air = 0.03; /* Polystrene */
237 air_heat_transfer=(k_room_air * sqm_room_air * (simulator->room_temperature - simulator->air_temperature)) / thick_room_air;
238 air_change = (air_heat_transfer / (vhc_air * ((simulator->volume_air - simulator->volume_beer) * 1000))) / 60.0;
239 simulator->air_temperature += air_change;
240
241 /*
242 * If heating, calculate temperature of the heating plate. If heating is off but
243 * the plate is warmer then the air, calculate the cooling down temperature.
244 * Finally, calculate the new air and plate temperature.
245 */
246 if (SIMheating) {
247 if (simulator->s_heat_temp < simulator->heater_temp) {
248 simulator->s_heat_temp += 0.05;
249 if (simulator->s_heat_temp > simulator->air_temperature)
250 simulator->air_temperature += ((simulator->s_heat_temp - simulator->air_temperature) / 100.0);
251 }
252 } else {
253 /*
254 * Follow the air temperature
255 */
256 simulator->s_heat_temp -= (simulator->s_heat_temp - simulator->air_temperature) / 25.0;
257 }
258
259 /*
260 * If cooling, calculate temperature of the cooling plate. If cooling is off but
261 * the plate is colder then the air, calculate the warming up temperature.
262 * Finsally, calculate the new air and plate temperature.
263 */
264 if (SIMcooling) {
265 if (simulator->s_cool_temp > simulator->cooler_temp) {
266 simulator->s_cool_temp -= 0.05;
267 if (simulator->s_cool_temp < simulator->air_temperature)
268 simulator->air_temperature -= ((simulator->air_temperature - simulator->s_cool_temp) / 100.0);
269 }
270 } else {
271 simulator->s_cool_temp -= (simulator->s_cool_temp - simulator->air_temperature) / 25.0;
272 }
273
274 /*
275 * Calculate final temperature of the beer and the air.
276 */
277 // Cheap trick, just follow slowly the air temp.
278 simulator->beer_temperature += ((simulator->air_temperature - simulator->beer_temperature) / 500.0);
279 simulator->air_temperature += ((simulator->beer_temperature - simulator->air_temperature) / 2500.0);
280 simulator->chiller_temperature = simulator->cooler_temp; // Libk these
281 } 313 }
282 mDelay(100L); 314 } else {
283 } 315 simulator->s_cool_temp -= (simulator->s_cool_temp - air_temp) / 25.0;
284 mDelay(50L); 316 }
285 } 317
286 318 /*
287 syslog(LOG_NOTICE, "Thread my_simulator_loop stopped"); 319 * Calculate final temperature of the beer and the air.
288 my_simulator_state = 0; 320 */
289 return 0; 321 // Cheap trick, just follow slowly the air temp.
290 } 322 beer_temp += ((air_temp - beer_temp) / 500.0);
323 air_temp += ((beer_temp - air_temp) / 2500.0);
324 chiller_temp = simulator->cooler_temp; // Link these
325
326 /*
327 * Finally update simulated sensors with the new values.
328 * The devices_loop will pickup the values and sets the resolution.
329 */
330 if (air_temp != simulator->air_temperature) {
331 // syslog(LOG_NOTICE, "SIM %d: air %f to %f", simulator->simno, simulator->air_temperature, air_temp);
332 simulator->air_temperature = air_temp;
333 changed = true;
334 }
335 if (beer_temp != simulator->beer_temperature) {
336 // syslog(LOG_NOTICE, "SIM %d: beer %f to %f", simulator->simno, simulator->beer_temperature, beer_temp);
337 simulator->beer_temperature = beer_temp;
338 changed = true;
339 }
340 if (chiller_temp != simulator->chiller_temperature) {
341 // syslog(LOG_NOTICE, "SIM %d: chiller %f to %f", simulator->simno, simulator->chiller_temperature, chiller_temp);
342 simulator->chiller_temperature = chiller_temp;
343 changed = true;
344 }
345 }
346 SM_PROCEED(Websocket);
347
348 SM_STATE(Websocket)
349
350 if (my_simulator_shutdown) {
351 SM_SUCCESS;
352 }
353 if (changed) {
354 simulator_ws();
355 changed = false;
356 }
357 SM_PROCEED(Waiting);
358
359 SM_END
360 SM_RETURN
291 361
292 362
293 #endif 363 #endif

mercurial