heat control  r71
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
hc.c
Go to the documentation of this file.
1 
2 #include <math.h>
3 #include "types.h"
4 #include "hc.h"
5 #include "init.h"
6 #include "adc.h"
7 #include "lcdisp.h"
8 #include "timer.h"
9 #include "comm.h"
10 #include "setup.h"
11 
13 // * nominal temperature in eeprom
14 // */
15 
23 UCHAR EEMEM ge_hcrCnt = 0;
27 UCHAR EEMEM e_dummy[3] = "..";
31 extern MEASSET EEMEM ge_msRec[NUM_MSR];
39 extern volatile CTRL_MODE g_ctm;
43 extern ENG_TIMER volatile g_et;
44 
45 //remeber previous minute for period of time evaluation
47 
52 int main(void) {
53 // /**
54 // * nominal temperature from setup
55 // */
56 // UINT tNom = gNit();
60  UINT innerTemp = INVALID_VAL_U16;
64  UINT outerTemp = INVALID_VAL_U16;
68  UINT supVolt = INVALID_VAL_U16;
72  UINT forTemp = INVALID_VAL_U16;
76  UCHAR firstTime = TRUE;
80 // UCHAR btnOffFct = OFF_NEAR;
84  UCHAR recCnt = 0;
88  UCHAR idx=0;
92  OP_MODE opm = OM_SHMEAS;
96  BTN_CODE bc = BC_NONE;
100  UCHAR old_sec=0;
104  UCHAR old5sec=0;
108  CHAR dSec=0;
112  UINT time = 0;
113 // /**
114 // * running tenth of a second
115 // */
116 // extern UCHAR volatile g_s100;
120  extern UCHAR volatile g_sec;
124  extern UINT volatile g_min;
128  MEASSET* set = NULL;
132  CTRL_MODE oldCm = CM_DENY;
136  UCHAR cmName[5];
137  //record counter for MEASSETs
138  UCHAR msrCnt = -1;
139  //keep recent inner temp
140  UINT pInTemp = 0;
141  //keep calculated forerun from heating curve
142  UINT cFor = 0;
143 
144 
145  Init();
146  recCnt = eeprom_read_byte(&ge_hcrCnt);
147  //prepare old_min to be in sync for doing control
148  old_min = -gIvMeas();
149  // Global enable interrupts
150  sei();
151 
152  while(TRUE) {
153  //button decoding
154  bc = DecodeButton(/*&btnOffFct*/);
155  //temperature capturing
156  forTemp = CalcAdcTemp(ADC_TMP_INNER_ID);
157 // outerTemp = CalcAdcTemp(ADC_TMP_OUTER_ID);
158  GetSenderValues(&innerTemp, &outerTemp/*, &supVolt*/);
159  //respect inner temperature offset
160  innerTemp += gOit();
161  //override supply voltage by local measurement
163  //second changed
164  if(old_sec != g_sec || firstTime) {
165  time = g_min * 100 + g_sec;
166  old_sec = g_sec;
167  if(!(opm == OM_SETUP || opm == OM_SHMEAS)) {
168  PrintValue(DT_TIME, 0, 1, NM_TIME, &time);
169  if((forTemp != INVALID_VAL_U16) && (recCnt >= NUM_HR)) {
170  PrintValue(DT_UINT, 8, 1, NM_TFOR, &forTemp);
171  }
172  }
173  }
174  if(opm == OM_CONTI || opm == OM_SENDER) {
175  //serial communication (testing)
176 // if(g_comDataReady) {
177 // g_comDataReady = FALSE;
178 // rcvBuf = ~FlipByte(USIBR); //received byte from USI buffer
179 // if(rcvBuf != oldRcvBuf) {
180 // PrintValue(DT_UCHAR, 8, 1, 'S', &rcvBuf);
181 // oldRcvBuf = rcvBuf;
182 // }
183 // }
184  //supply voltage printing
185  if(opm == OM_SENDER && supVolt != INVALID_VAL_U16)
186  PrintValue(DT_UINT, 8, 1, NM_VOLT, &supVolt);
187 
188  //temperature value printing
189  if((innerTemp != INVALID_VAL_U16) && (outerTemp != INVALID_VAL_U16)) {
190  pInTemp = innerTemp;
191  PrintValue(DT_INT, 8, 0, NM_TOUT, &outerTemp);
192 // if(opm == OM_SENDER)
193 // //print all values from temperature sender
194 // PrintValue(DT_UINT, 8, 1, NM_VOLT, &supVolt);
195 // else
196 // if(opm == OM_CONTI)
197 // PrintValue(DT_UINT, 8, 1, NM_TFOR, &forTemp);
198  }
199 
200  //alternating print inner temp and calculated forerun temp
201  if((g_sec & 0x02) == 0)
202  PrintValue(DT_INT, 0, 0, NM_TIN, &pInTemp);
203  else
204  PrintValue(DT_UINT, 0, 0, NM_TFOR, &cFor);
205  }
206  //temperature controlling and recording
207  if(opm != OM_ENGTEST) {
208  if((set = DoControl(innerTemp, outerTemp, forTemp, recCnt < NUM_HR, g_min, g_sec)) != NULL) {
209 // DoRecord(&recCnt, set);
210 // PrintMeasValues(set, opm, msrCnt >= NUM_MSR);
211  cFor = set->forTemp;
212  if((gMov() >= OVM_MSR) && ((msrCnt < NUM_MSR) || (msrCnt == (UCHAR)-1))) {
213  if((++msrCnt) < NUM_MSR) {
214  eeprom_write_block(set, &ge_msRec[msrCnt], sizeof(MEASSET));
215  sMov(0);
216  }
217  }
218  }
219  }
220  //print control mode
221  if(opm == OM_TMPCTRL) {
222  if(oldCm != g_ctm) {
224  oldCm = g_ctm;
225  }
226  }
227  //change operation mode when both buttons pressed
228  if((opm != OM_SETUP) && (bc == BC_DNUP || firstTime)) {
229  old5sec = g_sec;
230  opm = SetLimitValue(opm, DT_UCHAR, DIR_UP, OM_TMPCTRL, OP_MODES - 2);
231  PrintValue(DT_UCHAR, 8, 1, NM_OPMODE, &opm);
232  if(opm == OM_TMPCTRL)
234  }
235  //engine test
236  if(opm == OM_ENGTEST) {
237  DoEngineTest(bc);
238  }
239  //meas value visualization
240  else if(opm == OM_SHMEAS) {
241  //write previous meas sets every n seconds
242  //skip invalid data on current idx
243  if(g_sets[idx].inTemp == INVALID_VAL_I16) {
244 // idx = (UCHAR)SetLimitValue(idx, (CHAR)-1, 0, (INT)(NUM_MS - 1));
245  if(--idx == (UCHAR)-1)
246  idx = NUM_MS - 1;
247  }
248  dSec = g_sec - old5sec;
249  if(g_sec == 0 && old5sec != 0)
250  old5sec = gSmi();
251  if(dSec == (CHAR)(gSmi()-(UCHAR)60) || (CHAR)gSmi() == dSec || firstTime) {
252  old5sec = g_sec;
253  PrintMeasValues(&(g_sets[idx]), opm, msrCnt < NUM_MSR);
254  time = idx * gIvMeas() * 100;
255  PrintValue(DT_TIME, 0, 1, NM_TIME, &time);
256 // idx = (UCHAR)SetLimitValue(idx, (CHAR)-1, 0, (INT)(NUM_MS - 1));
257  if(--idx == (UCHAR)-1)
258  idx = NUM_MS - 1;
259  }
260  }
261  DoSetup(bc, &opm);
262 // TestButton(bc);
263  firstTime = FALSE;
264  }
265 }
266 
279 MEASSET* DoControl(INT inTemp, INT outTemp, UINT forTemp, UCHAR learning, UINT min, UCHAR sec) {
280  static UINT oldShdMin = 1;
281  static UCHAR old_sec = -1,
282  balDur=0, //balance counter (multiple of IV_MEAS)
283  shtDn=0; //shut down counter (multiple of IV_MEAS)
284  INT dMin = 0;
285  UCHAR i=0/*, prevIdx=0*/;
286  MEASSET* ret = NULL;
287 
288  dMin = min - old_min;
289  dMin = dMin < 0 ? gIvMeas() : dMin;
290  i = min/gIvMeas();
291  //too warm outside?
292  if(g_sets[i].outTemp >= (INT)(gSdt() + gDelTemp())) {
293  g_ctm = CM_SHDN;
294  g_et.em = EM_CW;
295  if(oldShdMin != min) {
296  ++shtDn;
297  oldShdMin = min;
298  }
299  }
300  else {
301  //conditionally initiate new measurement and controlling cycle
302  if((dMin >= gIvMeas()) && (g_ctm == CM_MEAS) && (inTemp != INVALID_VAL_U16) && (outTemp != INVALID_VAL_U16) && (forTemp != INVALID_VAL_U16)) {
303  g_ctm = CM_DENY;
304  old_min = min;
305  g_sets[i].inTemp = inTemp;
306  g_sets[i].outTemp = outTemp;
307  g_sets[i].forTemp = forTemp;
308 // oldNomTemp = gNit();
309  old_sec = -1;
310  ret = &g_sets[i];
311  }
312  else if(old_sec == (UCHAR)-1 && g_sets[i].outTemp <= (INT)(gSdt() - gDelTemp())) {
313  g_et.allow = TRUE;
314  g_et.cnt = 0;
315  shtDn = 0;
316  oldShdMin = 0;
317  old_sec = sec;
318  if(learning) {
319  //too warm inside? inner temp deviation to nom greater than 0.2°C?
320  if(gdInNom(g_sets[i].inTemp) > gDelTemp()) {
321  g_et.em = EM_CW;
322 // //did the nominal temperature change?
323 // if(oldNomTemp != gNit()) {
324 // //control down
325 // g_et.em = EM_CW;
326 // }
327 // else {
328 // //did the inner temp rise?
329 // prevIdx = CalcPrevIndex(i, 1);
330 // if((g_sets[prevIdx].inTemp != INVALID_VAL_I16) && (g_sets[prevIdx].inTemp >= (INT)MIN_ABS_INNER_TEMP)
331 // && ((g_sets[i].inTemp - g_sets[prevIdx].inTemp) >= (INT)gDelTemp())) {
332 // //valid previous data set? did the outer temp rise around a specific deviation in a specific time?
333 // prevIdx = CalcPrevIndex(i, gTrd() / gIvMeas());
334 // if((g_sets[prevIdx].outTemp != INVALID_VAL_I16) && ((g_sets[i].outTemp - g_sets[prevIdx].outTemp) >= (INT)(gTdm() * gDelTemp())))
335 // //control down
336 // g_et.em = EM_CW;
337 // }
338 // }
339  }
340  else if(gdInNom(g_sets[i].inTemp) < -gDelTemp()) {
341  //too cold?
342  g_et.em = EM_CCW;
343  }
344  else {
345  //allow recording of heating curve if long enough in balance
346  if(balDur >= gHci()) {
347  balDur = 0;
348  g_ctm = CM_REC;
349  }
350  else
351  ++balDur;
352  ret = &g_sets[i];
353  }
354  }
355  //leading the forerun temp
356  else if(g_sets[i].forTemp > MIN_FOR_TEMP && g_sets[i].forTemp < MAX_FOR_TEMP) {
357  g_ctm = CM_FOR;
358  if((forTemp = FindForeRun(&g_sets[i].outTemp, NUM_HR, MAX_DEL_OUTER_TEMP)) != INVALID_VAL_U16) {
359  if(g_sets[i].forTemp < forTemp - DEL_FOR_TEMP)
360  //too cold?
361  g_et.em = EM_CCW;
362  else if(g_sets[i].forTemp > forTemp + DEL_FOR_TEMP)
363  //control down
364  g_et.em = EM_CW;
365  g_sets[i].forTemp = forTemp;
366  ret = &g_sets[i];
367  }
368  }
369  }
370  }
371  if(shtDn > gSdd()) {
372  g_et.em = EM_STOP;
373  shtDn = gSdd() + 1;
374  }
375  ControlEngine(g_et.em);
376  return ret;
377 }
378 
387 UINT FindForeRun(INT* outTemp, const UCHAR range, UINT const delLim) {
388  UCHAR i=0;
389  HCREC rec;
390  INT dOut = 0;
391 
392  for(i=0;i<range;++i) {
393  eeprom_read_block(&rec, &ge_hcRec[i], sizeof(HCREC));
394  dOut = *outTemp - rec.outTemp;
395 // if(dOut >= 0 ? (dOut <= delLim/*MAX_DEL_OUTER_TEMP*/) : (dOut >= -delLim/*-MAX_DEL_OUTER_TEMP*/)) {
396  if(abs(dOut) <= delLim) {
397  *outTemp = rec.outTemp;
398  return rec.forTemp;
399  }
400  }
401  return INVALID_VAL_U16;
402 }
403 
410 //void DoRecord(UCHAR* recCnt, MEASSET* set) {
411 // HCREC hcr;
412 //
413 // if(set == NULL) return;
414 // if(g_ctm == CM_REC) {
415 // g_ctm = CM_DENY;
416 // *recCnt = eeprom_read_byte(&ge_hcrCnt);
417 // //still some space in eep and set of values does not exist?
418 // if(*recCnt < NUM_HR && FindForeRun(&set->outTemp, *recCnt, MAX_DEL_OUTER_TEMP) == INVALID_VAL_U16) {
419 // hcr.outTemp = set->outTemp;
420 // hcr.forTemp = set->forTemp;
421 // eeprom_write_block(&hcr, &ge_hcRec[*recCnt], sizeof(HCREC));
422 // eeprom_write_byte(&ge_hcrCnt, ++(*recCnt));
423 // }
424 // }
425 //}
426 
433  switch(em)
434  {
435  case EM_STOP:
436  ENG_STOP_CW;
437  ENG_STOP_CCW;
438  break;
439  case EM_CW:
440  ENG_RUN_CW;
441  ENG_STOP_CCW;
442  break;
443  case EM_CCW:
444  ENG_STOP_CW;
445  ENG_RUN_CCW;
446  break;
447  }
448 }
449 
455 void PrintMeasValues(MEASSET* ms, OP_MODE opm, UCHAR msrFull) {
456 // static UCHAR oldRecCnt = -1;
457 // INT dInNom = 0;
458 
459  if(opm == OM_SETUP) return;
460  PrintValue(DT_INT, 0, 0, msrFull ? NM_MSRFULL : NM_TIN, &ms->inTemp);
461  PrintValue(DT_INT, 8, 0, msrFull ? NM_MSRFULL : NM_TOUT, &ms->outTemp);
462  if(opm == OM_SHMEAS)
463  PrintValue(DT_UINT, 8, 1, msrFull ? NM_MSRFULL : NM_TFOR, &ms->forTemp);
464 // else {
465 // dInNom = gdInNom(ms->inTemp);
466 // PrintValue(DT_INT, 0, 1, NM_TDINNOM, &dInNom/*ms->dInNom*/);
467 // if(g_ctm == CM_FOR)
468 // PrintValue(DT_UINT, 0, 0, NM_TFOR, &ms->forTemp);
469 // }
470 }
471 
480 void PrintValue(DATTYPE dt, UCHAR col, UCHAR row, UCHAR name, void* value) {
481  MEASVAL mv;
482 
483  mv.dt = dt;
484  mv.pos.col = col;
485  mv.pos.row = row;
486  mv.name = name;
487  mv.value = value;
488  WriteMeasVal(&mv);
489 }
490 
496  static ENG_MODE engMod = EM_STOP;
497 
498  if((bc != BC_NONE && bc != BC_DNUP)) {
499  if(engMod == EM_CW || engMod == EM_CCW)
500  engMod = EM_STOP;
501  else {
502  switch(bc) {
503  case BC_DN:
504  engMod = EM_CW;
505  break;
506  case BC_UP:
507  engMod = EM_CCW;
508  break;
509  default:
510  break;
511  }
512  }
513  ControlEngine(engMod);
514  }
515 }
516 
517 UCHAR CalcPrevIndex(UCHAR curIdx, UCHAR delIdx) {
518  CHAR prevIdx=0;
519 
520  prevIdx = (CHAR)(curIdx - delIdx);
521  if(prevIdx < 0)
522  prevIdx += NUM_MS;
523  return (UCHAR)prevIdx;
524 }
525 
526 
527 
528 
Definition: lcdisp.h:59
MEASSET * DoControl(INT inTemp, INT outTemp, UINT forTemp, UCHAR learning, UINT min, UCHAR sec)
realizes the main heater controlling algorithm the value of inner temperature distinguishes between ...
Definition: hc.c:279
Definition: types.h:311
BTN_CODE
Definition: types.h:299
#define IV_MEAS
Definition: types.h:228
Definition: types.h:141
Definition: types.h:257
ENG_MODE em
Definition: types.h:336
#define NUM_MSR
Definition: setup.h:175
void Init(void)
Definition: init.c:11
UINT forTemp
Definition: types.h:244
#define NM_VOLT
Definition: hc.h:80
UCHAR col
Definition: lcdisp.h:52
UINT volatile g_min
Definition: timer.c:19
OP_MODE
Definition: types.h:146
Definition: types.h:303
UINT FindForeRun(INT *outTemp, const UCHAR range, UINT const delLim)
gets the forerun temperature of the closest outer temperature which was recorded in learning phase a...
Definition: hc.c:387
void PrintMeasValues(MEASSET *ms, OP_MODE opm, UCHAR msrFull)
puts the measurement values on screen
Definition: hc.c:455
#define NM_TIN
Definition: hc.h:48
void sMov(UCHAR mov)
set minute overflow counter
Definition: timer.c:208
#define MIN_FOR_TEMP
Definition: hc.h:96
void * value
Definition: lcdisp.h:71
#define INVALID_VAL_I16
Definition: types.h:109
UCHAR CalcPrevIndex(UCHAR curIdx, UCHAR delIdx)
Definition: hc.c:517
#define MAX_DEL_OUTER_TEMP
Definition: comm.h:90
UINT CalcSupplyVoltage(UCHAR id)
Definition: adc.c:126
volatile CTRL_MODE g_ctm
Definition: timer.c:27
#define NM_MSRFULL
Definition: hc.h:88
#define DEL_FOR_TEMP
Definition: hc.h:92
MEASSET g_sets[NUM_MS]
Definition: hc.c:35
#define ENG_STOP_CW
Definition: timer.h:48
UINT SetLimitValue(UINT val, DATTYPE dt, CHAR dir, INT min, INT max)
limiting values to constraints
Definition: types.c:13
UCHAR EEMEM e_dummy[3]
Definition: hc.c:27
UCHAR * GetCtrlMode(CTRL_MODE ctm, UCHAR *buf)
Definition: types.c:65
#define OP_MODES
Definition: types.h:184
UCHAR EEMEM ge_hcrCnt
Definition: hc.c:23
#define FALSE
Definition: types.h:93
UCHAR allow
Definition: types.h:332
#define OVM_MSR
Definition: timer.h:60
#define UCHAR
Definition: types.h:73
void PrintValue(DATTYPE dt, UCHAR col, UCHAR row, UCHAR name, void *value)
put a specific value on screen
Definition: hc.c:480
#define CHAR
Definition: types.h:69
#define ADC_TMP_OUTER_ID
Definition: init.h:19
void WriteCtrlMode(UCHAR name, UCHAR *cmName)
Definition: lcdisp.c:117
UCHAR cnt
Definition: types.h:328
Definition: types.h:307
HCREC EEMEM ge_hcRec[NUM_HR]
Definition: hc.c:19
#define INT
Definition: types.h:77
#define ADC_TMP_INNER_ID
Definition: init.h:15
Definition: types.h:261
void DoEngineTest(BTN_CODE bc)
do engine testing dependent on button request, simply drives the mixer engine unconditionally ...
Definition: hc.c:495
#define NM_OPMODE
Definition: hc.h:68
Definition: types.h:197
Definition: types.h:315
#define NUM_HR
Definition: types.h:249
INT inTemp
Definition: types.h:210
MEASSET EEMEM ge_msRec[NUM_MSR]
Definition: setup.c:20
void WriteMeasVal(MEASVAL *mv)
put a measurement value on lcd source value is being output as fixed decimal point number ...
Definition: lcdisp.c:34
ENG_TIMER volatile g_et
Definition: timer.c:31
LCD_POS pos
Definition: lcdisp.h:63
#define NM_CNT
Definition: hc.h:72
void ControlEngine(ENG_MODE em)
takes care of the heating curve recording in eeprom records only if outer temp value does not exist ...
Definition: hc.c:432
#define ENG_RUN_CCW
Definition: timer.h:52
UINT forTemp
Definition: types.h:218
INT outTemp
Definition: types.h:240
Definition: types.h:193
UINT CalcAdcTemp(UCHAR id)
calculate the temperature from specific ADC value in data array, specified by id
Definition: adc.c:107
UCHAR name
Definition: lcdisp.h:67
#define TRUE
Definition: types.h:97
Definition: types.h:265
Definition: types.h:129
Definition: types.h:269
#define ENG_STOP_CCW
Definition: timer.h:56
int main(void)
main controlling task
Definition: hc.c:52
#define INVALID_VAL_U16
Definition: types.h:105
UCHAR GetSenderValues(UINT *innerTemp, UINT *outerTemp)
establish decimal temperature values form raw stream in sequence
Definition: comm.c:133
CTRL_MODE
Definition: types.h:253
UCHAR row
Definition: lcdisp.h:53
DATTYPE dt
Definition: lcdisp.h:75
Definition: types.h:125
#define MAX_FOR_TEMP
Definition: hc.h:100
#define DIR_UP
Definition: types.h:378
DATTYPE
Definition: types.h:113
Definition: types.h:273
ENG_MODE
Definition: types.h:188
BTN_CODE DecodeButton(void)
identify whether a (and which) button is pressed or not
Definition: timer.c:119
UCHAR volatile g_sec
Definition: timer.c:15
#define NM_TIME
Definition: hc.h:76
UINT old_min
Definition: hc.c:46
#define NUM_MS
Definition: types.h:223
Definition: types.h:201
#define NM_TOUT
Definition: hc.h:52
#define UINT
Definition: types.h:81
Definition: types.h:232
#define NM_TFOR
Definition: hc.h:56
#define ENG_RUN_CW
Definition: timer.h:44
UCHAR gMov()
return minute overflow counter
Definition: timer.c:200
INT outTemp
Definition: types.h:214
void DoSetup(BTN_CODE bc, OP_MODE *opm)
does the setup job, distinguishes data selection and modification dependent on user pressed buttons a...
Definition: setup.c:86
Definition: types.h:206