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 2353570..80ff332 100755 Binary files a/F0-nolib/Chiller/chiller.bin and b/F0-nolib/Chiller/chiller.bin differ 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