From 7a470da9828e07ab3729c5ba162b86cf88dacc74 Mon Sep 17 00:00:00 2001 From: eddyem Date: Sat, 22 Dec 2018 14:43:10 +0300 Subject: [PATCH] add NTC temperature calculation --- F0-nolib/Chiller/adc.c | 107 ++++++++++++++++++++++++----------- F0-nolib/Chiller/adc.h | 2 + F0-nolib/Chiller/chiller.bin | Bin 3904 -> 4760 bytes F0-nolib/Chiller/hardware.c | 2 +- F0-nolib/Chiller/protocol.c | 39 +++++++++++-- F0-nolib/Chiller/usart.c | 2 +- 6 files changed, 112 insertions(+), 40 deletions(-) diff --git a/F0-nolib/Chiller/adc.c b/F0-nolib/Chiller/adc.c index 423f29e..c10f5fe 100644 --- a/F0-nolib/Chiller/adc.c +++ b/F0-nolib/Chiller/adc.c @@ -18,57 +18,100 @@ #include "adc.h" -extern volatile uint32_t Tms; // time counter for 1-second Vdd measurement -static uint32_t lastVddtime = 0; // Tms value of last Vdd measurement -static uint32_t VddValue = 0; // value of Vdd * 100 (for more precision measurements) -// check time of last Vdd measurement & refresh it value -#define CHKVDDTIME() do{if(!VddValue || Tms < lastVddtime || Tms - lastVddtime > 999) getVdd();}while(0) - /** - * @brief ADC_array - array for ADC channels: + * @brief ADC_array - array for ADC channels with median filtering: * 0..3 - external NTC * 4 - internal Tsens * 5 - Vref */ -uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS]; +uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9]; +/** + * @brief getADCval - calculate median value for `nch` channel + * @param nch - number of channel + * @return + */ +uint16_t getADCval(int nch){ + int i, addr = nch; + register uint16_t temp; +#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); } +#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; } + uint16_t p[9]; + for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed + p[i] = ADC_array[addr]; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ; + PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ; + PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ; + PIX_SORT(p[4], p[2]) ; + return p[4]; +#undef PIX_SORT +#undef PIX_SWAP +} // return MCU temperature (degrees of celsius * 10) int32_t getMCUtemp(){ getVdd(); // make correction on Vdd value - int32_t temperature = (int32_t)ADC_array[4] * VddValue / 330; - temperature = (int32_t) *TEMP30_CAL_ADDR - temperature; +// int32_t temperature = (int32_t)ADC_array[4] * VddValue / 330; + int32_t ADval = getADCval(4); + int32_t temperature = (int32_t) *TEMP30_CAL_ADDR - ADval; temperature *= (int32_t)(1100 - 300); - temperature = temperature / (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR); + temperature /= (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR); temperature += 300; return(temperature); } // return Vdd * 100 (V) uint32_t getVdd(){ -/* #define ARRSZ (10) - static uint16_t arr[ARRSZ] = {0}; - static int arridx = 0; - uint32_t v = ADC_array[5]; - int i; - if(arr[0] == 0){ // first run - fill all with current data - for(i = 0; i < ARRSZ; ++i) arr[i] = (uint16_t) v; - }else{ - arr[arridx++] = v; - v = 0; // now v is mean - if(arridx > ARRSZ-1) arridx = 0; - // calculate mean - for(i = 0; i < ARRSZ; ++i){ - v += arr[i]; - } - v /= ARRSZ; - }*/ uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330; // 3.3V - //vdd /= v; - vdd /= ADC_array[5]; - lastVddtime = Tms; - VddValue = vdd; + vdd /= getADCval(5); return vdd; } +/** + * @brief getNTC - return temperature of NTC (*10 degrC) + * @param nch - NTC channel number (0..3) + * @return + */ +int16_t getNTC(int nch){ +#define NKNOTS (9) + const int16_t ADU[NKNOTS] = {427, 468, 514, 623, 754, 910, 1087, 1295, 1538}; + const int16_t T[NKNOTS] = {-200, -180, -159, -116, -72, -26, 23, 75, 132}; + /* + * coefficients: 0.050477 0.045107 0.039150 0.033639 0.029785 0.027017 0.024996 0.023522 0.022514 + * use + * [N D] = rat(K*10); printf("%d, ", N); printf("%d, ", D); + */ + const int16_t N[NKNOTS] = {1377, 295, 258, 110, 291, 77, 1657, 191, 120}; + const int16_t D[NKNOTS] = {2728, 654, 659, 327, 977, 285, 6629, 812, 533}; + + if(nch < 0 || nch > 3) return -30000; + uint16_t val = getADCval(nch); + // find interval + int idx = (NKNOTS+1)/2; // middle + while(idx > 0 && idx < NKNOTS){ + int16_t left = ADU[idx]; + int half = idx / 2; + if(val < left){ + if(idx == 0) break; + if(val > ADU[idx-1]){ // found + --idx; + break; + } + idx = half; + }else{ + if(idx == NKNOTS - 1) break; // more than max value + if(val < ADU[idx+1]) break; // found + idx += half; + } + } + if(idx < 0) idx = 0; + else if(idx > NKNOTS-1) idx = NKNOTS - 1; + // T = Y0(idx) + K(idx) * (ADU - X0(idx)); + int16_t valT = T[idx] + (N[idx]*(val - ADU[idx]))/D[idx]; +#undef NKNOTS + return valT; +} diff --git a/F0-nolib/Chiller/adc.h b/F0-nolib/Chiller/adc.h index 1990592..a7da2bc 100644 --- a/F0-nolib/Chiller/adc.h +++ b/F0-nolib/Chiller/adc.h @@ -24,5 +24,7 @@ extern uint16_t ADC_array[]; int32_t getMCUtemp(); uint32_t getVdd(); +uint16_t getADCval(int nch); +int16_t getNTC(int nch); #endif // ADC_H diff --git a/F0-nolib/Chiller/chiller.bin b/F0-nolib/Chiller/chiller.bin index 235357034628aa8f2c12562f3e06cbed8775d399..80ff33254702cab41cde3c14da37a1a313b0a512 100755 GIT binary patch delta 1673 zcmb_bZERCz6h7~5yLD~ZZpQ{~cRTLbhIQ?*m5+??amU`l3aB^|U<>OIT!Y|<2+WV9 zL4v;KCt%)KRP)9Et*HhRZqY)Fm$&=@t z^E~I=bKkr-R@hz20trnxVs4G%=tzwrFyoB-%oX8v`^ zmWUQW{#Yq)T`=cTc!txEm{r>Y7gimn6^lW3DIn`dLGDIArU1Vs`c!M3b9Q`(vpT-e z`TM{-t?s!Qu4RKzRE}=X$hD*k*^F)-cFj_*CVj2$idb0VxDrT!JZ@A6rD!0EuNCB9 zQuBC_e@Z!U0l#uC2}P4oD;j~KLS#F#9odS^A?J@olTgB=cm4>-CWTDT!tO6pTGy`w zeb}3ao*Q>!bToPL)?){9y}7j)ed*|K(u~SyDIwj8!{zHKkZY8KNk0qv(`L~Bh=?O% zh)RSX@iL+pkwCyT7}A2GgWMCH#81df=?-Hj`y{L8WZ<|`=&j$_1DbE{FZqUI!~D{{ z+={O~pahF8%kyhzz!MwmwZ^ImOP^d<>La}%KdpcxV}P{Z&l)ki9VgxDaN%9j4vwGW zWQcT6@j(&Do739B)g(IvLoE~W{@^~QT-=LgGAkVzOwX0pYRj0c5vff()2>@WCL8?= zoZ8E4ID=198?S@OENrPMA;5npMYS*GJTv0MAbyp;wVe?_X%MM&w1QQbHVc}p^8 zZ4SthPboyIU~k{N#pK-yB{7Q;HZ5XAliL<#rX3Pe14~6w+#@gv4e-E0ZO9nvqLM%o zhv;}X8_I4Aqc#I3KpBh^U%~hh&_M-!B{o+xiGJElPt#E7IMzk#0ZNYv%!Rk93##d1 ztn~-zB&ebt_hd5&G)R5baDIqZ(qK49_1yac3|4T#@SE6X1{)Y*A?-tlhua?}Tra8* zbD=QLbqR2u<#wSD1}*5{DHzTl$C?K;oG4@^y2BZL+K<|)9NjCV2KC^9n@J;gD;bDU z2Obt1(emo>i)yCVDjIFw5VPz?=)9GrKs;juIhrbWt8O;hKdeqVg~;@>5u2#vCFrp< z5YDO&H>m3Y2jRW5r`YHR=#e8e^c)RFUhCUTr+Ul43h^`XQzn0&FC=yZbw@g=4VDCG z-lOre@lW#nCSRx67Bn1b$MQnz7^~*Im#)v9))t%%D?VRw%IY`!dPFIxad;By@MKk2 ztREtC8o=4OTbOvs2x|&6%W@J8P}aDb-6h<(taqB?Yq%9~WbH0Nd%50{)~^pXfZhq; zvL((&SIkyL3mR8d&1wYMoAT0v`j`d6`F$oltb=%5Wby6fBD{F%=5W6VBy_UgZVx%?j&x`_SK}&%JR77?_EZkC>iBYgtG{Ij|6J1!zK-ACv}xOhtpLmGs-zFIch(&x zUlWFDVQw<}H4C&kIwk|4LS3phsjsU2>JREf@WLMa^_z4L5r#Yq#bg=0kZ}@PvDRzY V&qz!S8PM3t_g0rCp8+5Q;14O12MhoJ delta 838 zcmah{T}TvB6h3!%c3a2Qow30E37tV))<$E4iU_N%1u;i3g{+Kdstp$-OwiisVJRO{ z3NogLMd?8(=*b6dBP4Ojmn6bnqR4(=v0x$!rh0H@*0giAo`f3s&N<)Q?|jTTb5qrs z3Jy3Bidb+t5Cn0X4Eu6^y03jT*t*Z(#D_DF*3gLAzJmu3L;YgSdFT?%G> z^D)Vt?UkIlsz%Vio1n`}pr5cn@3BDOrp_exOM&bq$;g4Y85K)~Ov5j2pCsgb$mUHN zUz=WxFU?O{Ip#U^ID#IFN%OsSFA=VH)^2)Jh6gidnH+7OmP zO5~EJw+gM6H4uwYJ6p(TPfEd+MI1sT5H}Ie5C$SdK!9(MXTWmgkrVNpd?D?RcQvw6 zztR!6MLLvmTN|l#iml2+k&Dj)iSh~`uffQO!*Mn`tbl$+?XgdbqgI7{ylVvPuhwR~ zZuybFTjg}Vq}s~(n%gZ1Idf#FS|JZWZ$V~cNor-WX_*W`=xdhbNh+v-xVpWNk^87| zdB}H{cOkP*&+hwT95jO*>SB^j?rJ~bGDKpgbX#(lAB@E{zGg1%s|vTvZ+PgVU0 zmmDF1fmuK3C(XL>N|>9PTwJN7yTdCWJjVJdV#BKUUuTC*eHr=KAn20@HoM`eebKH)_~1qsVnW?sp|iWUTZo-K-PgIBRWI{f P85UQg&hS?mLI8dPo1*m( diff --git a/F0-nolib/Chiller/hardware.c b/F0-nolib/Chiller/hardware.c index e161eb6..9237ae9 100644 --- a/F0-nolib/Chiller/hardware.c +++ b/F0-nolib/Chiller/hardware.c @@ -91,7 +91,7 @@ static inline void adc_setup(){ ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG; /* (2) */ DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR)); /* (3) */ DMA1_Channel1->CMAR = (uint32_t)(ADC_array); /* (4) */ - DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS; /* (5) */ + DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS * 9; /* (5) */ DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC; /* (6) */ DMA1_Channel1->CCR |= DMA_CCR_EN; /* (7) */ ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversions */ diff --git a/F0-nolib/Chiller/protocol.c b/F0-nolib/Chiller/protocol.c index c010b5f..637bc4d 100644 --- a/F0-nolib/Chiller/protocol.c +++ b/F0-nolib/Chiller/protocol.c @@ -39,7 +39,14 @@ static void debugging_proc(const char *command){ return; } put_string("ADC value: "); - put_uint(ADC_array[i]); + put_uint(getADCval(i)); + usart1_sendbuf(); + break; + case 'T': // all raw T values + for(i = 0; i < 4; ++i){ + put_uint(getADCval(i)); + put_char('\t'); + } usart1_sendbuf(); break; default: @@ -48,6 +55,22 @@ static void debugging_proc(const char *command){ } #endif +/** + * @brief get_ntc - show value of ith NTC temperature + * @param str (i) - user string, first char should be '0'..'3' + */ +static void get_ntc(const char *str){ + uint8_t N = *str - '0'; + if(N > 3) return; + int16_t NTC = getNTC(N); + put_string("NTC"); + put_char(*str); + put_char('='); + put_int(NTC); +} + +#define SEND(x) usart1_send_blocking(x, 0) + /** * @brief process_command - command parser * @param command - command text (all inside [] without spaces) @@ -58,16 +81,20 @@ char *process_command(const char *command){ char *ret = NULL; usart1_sendbuf(); // send buffer (if it is already filled) switch(*ptr++){ - case '?': // help - put_string("R - reset\nt - get MCU temp\nV - get Vdd\n"); + case '?': // help + SEND("R - reset\nTx - get NTC temp\nt - get MCU temp\nV - get Vdd"); #ifdef EBUG - put_string("d -> goto debug:\n"); - put_string("\tw - test watchdog\n\tAx - get raw ADCx value\n"); + SEND("d -> goto debug:"); + SEND("\tw - test watchdog\n\tAx - get raw ADCx value"); + SEND("\tT - show raw T values"); #endif - break; + break; case 'R': // reset MCU NVIC_SystemReset(); break; + case 'T': // get temperature of NTC(x) + get_ntc(ptr); + break; case 't': // get mcu T put_string("MCUTEMP10="); put_int(getMCUtemp()); diff --git a/F0-nolib/Chiller/usart.c b/F0-nolib/Chiller/usart.c index 7e88b77..0584a6a 100644 --- a/F0-nolib/Chiller/usart.c +++ b/F0-nolib/Chiller/usart.c @@ -50,7 +50,7 @@ int put_string(const char *str){ while(trbufidx < UARTBUFSZ - 1 && *str){ trbuf[trbufidx++] = *str++; } - error! shouldn't be!!! + //error! shouldn't be!!! if(*str) return 1; // buffer overfull trbuf[trbufidx] = 0; return 0; // all OK