Re: mereni frekvence s stm32

Vojtěch Petrucha petrucha na volny.cz
Čtvrtek Prosinec 5 14:23:54 CET 2019


zdravim,
 
chtel jsem s tim merenim nejdrive zaukolovat studenta, ktery zrovna neco s merenim frekvence dela, ale projevil se jako malo akcni, tak jsem to zkusil napsat sam a mam tu takovou zahadu...
 
- vzal jsem 32f469 discovery, ktery byl zrovna po ruce a umi citac na 180MHz.. 
- pomoci 16-bit TIM8 a Input capture 1 na nabeznou a Input capture 2 na sestupnou hranu plnim v preruseni dve pole temi capture hodnotami
- po skonceni mericiho intervalu to prepocitam - ze dvou sousednich capture vypocitam interval mezi nimi..  (pro pozadovanou frekvenci cca 2000Hz to je uz pres periodu citace.., ale to neva, staci jeden if a dva ruzne vypocty..)
- sectu vsechny intervaly a vydelim poctem a spocitam z toho frekvenci.. tohle funguje fajn..  rozliseni na mHz sedi s generatorem.. (ted to mam uz pres komparator, z generatoru jde sinus...)
 
ted jsem jeste chtel pridat preruseni od preteceni citace, kde se bude jen inkrementovat promenna, abych mohl porovnat co se nameri pokud vezmu jen prvni a posledni hranu a to mezi nimi spocitam jako n*delka citace..
no nicmene po pridani toho preruseni zaclo blbnout mereni frekvence, uz to nebylo 2000.003 Hz (s generatorem nastavenym na 2k), ale zacly se tam objevovat cisla jako 1988 apod.. 
to se asi vyresilo zmenou preempt. priority toho preruseni HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 1,0);    coz uplne nechapu proc..  (capture preruseni je 0,0)
myslel jsem, ze se se proste nejdriv vykona jedno a pak druhe, nic moc dlouheho se tam nedela, aby to tech radove 250us co je mezi hranami nestihalo..  zkousel jsem i "odstranit" defaultni HAL_TIM_IRQHandler(&htim8); (jen vynulovat dany flag, ale to take nepomohlo..)
takze ted funguje mereni frekvence, ale ten citac preteceni dava na muj vkus prilis rozdilne vysledky.. 3280-3287 , cekal bych maximalne rozdil o 1-2.. zacatek a konec mericiho intervalu 
 
merici interval je dany  HAL_Delay(1200);  coz asi sedi dobre, protoze pocet capture udalosti za tento interval se lisi max. o jednicku..
 
tak kdyby prosim nekdo tusil co delam spatne tak budu rad, chtel jsem to zitra jet omerit do Pruhonic s tou protonovou elektronikou...
 
diky
v.p.
 
 
 
prumer f, stdev, min, max, pocet capture udalosti,  to same pro sestupnou hranu, pocet overflow udalosti timeru..
zhruba po pulce jsem zvysil o 1mHz frekvenci generatoru
 
2000.0036 000.25283 1999.0775 2000.8330 02403 2000.0040 000.25277 1999.1441 2000.8108 02403 03280
2000.0037 000.25213 1999.0775 2000.7663 02403 2000.0037 000.25873 1999.0997 2001.1000 02403 03287
2000.0038 000.25065 1998.8999 2000.9442 02403 2000.0035 000.25082 1999.1663 2000.8330 02403 03284
2000.0036 000.25054 1999.1219 2000.9665 02403 2000.0037 000.26431 1999.1663 2000.7663 02403 03284
2000.0036 000.25113 1999.1441 2000.9220 02403 2000.0038 000.25522 1998.9887 2000.8553 02403 03284
2000.0038 000.25457 1999.2107 2000.8330 02403 2000.0037 000.25393 1999.0997 2000.8108 02403 03285
2000.0039 000.25858 1998.9887 2000.8108 02403 2000.0039 000.25096 1999.1663 2000.8775 02403 03284
2000.0047 000.24779 1999.2107 2000.8553 02403 2000.0047 000.24856 1999.1441 2000.8330 02403 03285
2000.0048 000.25248 1999.0775 2000.8998 02404 2000.0045 000.24580 1999.1885 2000.8330 02403 03282
2000.0047 000.24880 1999.1441 2001.0555 02403 2000.0048 000.25746 1999.1441 2000.8998 02403 03282
2000.0048 000.25074 1999.2107 2000.8330 02403 2000.0047 000.25710 1999.1441 2000.8108 02403 03283
 
 
 
main:
 
MX_GPIO_Init();
  MX_TIM1_Init();
  MX_USART3_UART_Init();
  MX_USART6_UART_Init();
  MX_TIM2_Init();
  MX_TIM8_Init();
  /* USER CODE BEGIN 2 */
 
  HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, SET);
  HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, SET);
  HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, SET);
  HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, SET);
 
  HAL_TIM_IC_Start_IT(&htim8, TIM_CHANNEL_1); //enable capture interrupt
  HAL_TIM_IC_Start_IT(&htim8, TIM_CHANNEL_2);
  HAL_Delay(20);
  TIM8->DIER &= 0xFFF8;   //disable IC1, IC2, Overflow
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
 //  HAL_UART_Transmit_IT(&huart3, (uint8_t*)aTxStartMessage, 10);
   HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, RESET);
 
   if(trigger_flag>0){
 
   trigger_flag = 0;
 
   periodcount = 0;
 
   index1 = 0;
   index2 = 0;
 
   freq1 = 0;
   freq2 = 0;
 
   stdev1 = 0;
   stdev2 = 0;
 
   suma1 = 0;
   suma2 = 0;
 
   freq1_min = 0;
   freq1_max = 0;
   freq2_min = 0;
   freq2_max = 0;
 
   HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, RESET);
 
   //HAL_TIM_IC_Start_IT(&htim8, TIM_CHANNEL_1); //enable capture interrupt
   //HAL_TIM_IC_Start_IT(&htim8, TIM_CHANNEL_2);
 
   TIM8->SR &= 0xFFFFFFF8;   //clear flags?
   HAL_Delay(2);
 
   TIM8->DIER |= 0x07;   //enable IC1, IC2, Overflow
 
   HAL_Delay(1200); //measure for 1.2 sec
 
   //HAL_TIM_IC_Stop_IT(&htim8, TIM_CHANNEL_1); //disable
   //HAL_TIM_IC_Stop_IT(&htim8, TIM_CHANNEL_2);
 
   TIM8->DIER &= 0xFFFFFFF8;   //disable IC1, IC2, Overflow
 
   HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, SET);
   HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, RESET);
 
   if(index1>10){
 
   for(unsigned int il=0; il<(index1-1);il++){ //rising edge
   if(incap1[il]<incap1[il+1]){
   rescap1[il]=65536-incap1[il]+incap1[il+1];
   }else{
   rescap1[il]=131072-incap1[il]+incap1[il+1];
   };
   };
 
   for(unsigned int ik=0; ik<(index1-1);ik++){
   suma1 += rescap1[ik];
   };
 
   freq1 = index1-1;
   freq1 /= suma1;
   freq1 *= f_constant;
 
   er_sum = 0;
 
   freq1_min = freq1; //initialize the min-max freq values...
   freq1_max = freq1;
 
   for(unsigned int im=0; im<(index1-1);im++){
   temp_f = f_constant;
   temp_f /= rescap1[im];
 
   if(temp_f < freq1_min) {freq1_min = temp_f;};
   if(temp_f > freq1_max) {freq1_max = temp_f;};
 
   er_f = freq1;
   er_f -= temp_f;
   pow_f = er_f;
   pow_f *=er_f;
   er_sum +=pow_f;
   };
 
   stdev1 = er_sum;
   stdev1 /= (index1-2); //std.dev. suma(diff^2)/(n-1)
   stdev1 = sqrt(stdev1);
   };
 
   if(index2 > 10){
 
 stejne jako pro rising edge, akorat index2...
   };
 
   HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, SET);
 
   HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, RESET);
 
   sprintf(buffers,"%09.4f %09.5f %09.4f %09.4f %05u ",freq1,stdev1,freq1_min,freq1_max,index1);
   strl = strlen(buffers);
   HAL_UART_Transmit_IT(&huart3, buffers, strl);
   HAL_Delay(10);
   HAL_UART_Transmit_IT(&huart6, buffers, strl);
   HAL_Delay(10);
 
   sprintf(buffers,"%09.4f %09.5f %09.4f %09.4f %05u %05u\r\n",freq2,stdev2,freq2_min,freq2_max,index2, periodcount);
   strl = strlen(buffers);
   HAL_UART_Transmit_IT(&huart3, buffers, strl);
   HAL_Delay(10);
   HAL_UART_Transmit_IT(&huart6, buffers, strl);
   HAL_Delay(10);
 
   HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, SET);
   }else{
   HAL_Delay(1);
   };
  };
 
 
 
 
 
 
 
preruseni:
 
 
void TIM8_UP_TIM13_IRQHandler(void)
{
  /* USER CODE BEGIN TIM8_UP_TIM13_IRQn 0 */
 if(TIM8->SR & 0x01){ //timer overflow
       periodcount++;
//       TIM8->SR &= 0xFFFFFFFE;
 };
  /* USER CODE END TIM8_UP_TIM13_IRQn 0 */
  HAL_TIM_IRQHandler(&htim8);
  /* USER CODE BEGIN TIM8_UP_TIM13_IRQn 1 */
 
  /* USER CODE END TIM8_UP_TIM13_IRQn 1 */
}
 
/**
  * @brief This function handles TIM8 capture compare interrupt.
  */
void TIM8_CC_IRQHandler(void)
{
  /* USER CODE BEGIN TIM8_CC_IRQn 0 */
  if(TIM8->SR & 0x02){ //Input capture channel 1
     incap1[index1]= TIM8->CCR1;
      index1++;
    //  TIM8->SR &= 0xFFFFFFFD;
  };
  if(TIM8->SR & 0x04){ //Input capture channel 2
     incap2[index2]= TIM8->CCR2;
     index2++;
   //  TIM8->SR &= 0xFFFFFFFB;
  };
  /* USER CODE END TIM8_CC_IRQn 0 */
  HAL_TIM_IRQHandler(&htim8);
  /* USER CODE BEGIN TIM8_CC_IRQn 1 */
  /* USER CODE END TIM8_CC_IRQn 1 */
}
 
 
 
 
 
volatile unsigned int incap1[5000];
volatile unsigned int incap2[5000];
 
volatile unsigned int index1 = 0;
volatile unsigned int index2 = 0;
 
volatile unsigned int periodcount = 0;
 
volatile unsigned char trigger_flag = 0;
 
unsigned long int rescap1[5000];
unsigned long int rescap2[5000];
unsigned long int suma1=0;
unsigned long int suma2=0;
 
unsigned long int avg1=0;
unsigned long int avg2=0;
 
unsigned long int esum1=0;
unsigned long int esum2=0;
 
unsigned int diff1 = 0;
unsigned int diff2 = 0;
 
unsigned long int power1 = 0;
unsigned long int power2 = 0;
 
unsigned char strl = 0;
 
char buffers[200];
 
double freq1 = 0;
double freq2 = 0;
 
double freq1_min = 0;
double freq1_max = 0;
double freq2_min = 0;
double freq2_max = 0;
 
double temp_f = 0;
double er_f = 0;
double pow_f = 0;
double er_sum = 0;
 
double stdev1 = 0;
double stdev2 = 0;
 
 
 
 
 
 
 
 
 
 
______________________________________________________________
> Od: "Jan Waclawek" <konfera na efton.sk>
> Komu: "HW-news" <hw-list na list.hw.cz>
> Datum: 23.10.2019 12:36
> Předmět: Re: mereni frekvence s stm32
>
No dobre, ale aj v tom PLL je pointa v tom filtri.
 
 Ak sa urobi ten filter dobre, tak ten capture/DMA na hrany bude fungovat
 dobre, a potom sa moze pouzit aj fourierka ako pan kolega Mrazik bol
 spomenul.
 
 Ale ak je toho sumu vela, tak z toho to capture/DMA "povybera" niektore
 hrany, a z toho podla mna uz nic rozumneho nepojde vytiahnut.
 
 Z cite technickej stranky, ak by mal pan kolega Petrucha problem rozchodit
 to capture/DMA, myslim, ze mu tu viaceri vieme s tym poradit/pomoct, je to
 relativne lahke cvicenie s asi tuctom registrov.
 
 wek
 
 
 
 ----- Original Message ---------------
 
 >To bylo kvůli tomu, aby se prostým počítáním period změřil kmitočet s rozlišením lepším než 1Hz, 
 >když je k dispozici měřicí okno do 2s (viz původní příspěvek).
 >Myslím že to tak bylo, měřilo se 1s a pokud by bylo PLL 100x, tak byl výsledek s rozlišením 0,01Hz.
 >Jak jsem psal, bylo to realizované standardní logikou, nebyl tam žádný MCU.
 >
 >Tomáš
 >
 >
 >
 >To ze sa da pomocou PLL a vhodneho filtra lovit zo sumu je jasne.
 >Ako tomu ale pomoze vynasobit frekv. PLL ked sa tym vynasobi aj chyba?
 >Tu by som povedal, ze diablik vysokeho nasobku spocival v niecom inom 
 > 
 >j.
 > 
 >From: Hw-list [mailto:hw-list-bounces na list.hw.cz] On Behalf Of Tomáš Hamouz
 >Sent: 23. októbra 2019 11:53
 >To: HW-news
 >Subject: Re: mereni frekvence s stm32
 > 
 >Kdysi jsem narazil na krásný magnetometr, řešený diskrétní logikou, ale neuložil si ho a už nenašel:-(
 >(kdyby si někdo vzpomněl, prosím pošlete odkaz)
 >
 >Do jaké míry tomu měření můžete pomoct analogovým HW?
 >Princip byl takový, že se podle přijatého signálu pomocí PLL řídil VCO na nějakém vysokém násobku (100x?) a měřil se kmitočet toho VCO.
 >PLL se chytne i na zašuměném signálu a zbytek je už jednoduchý. 
 >
 >Tomáš
 >
 >
 >> Zdravim,
 >>  
 >> kdyz bych chtel pomoci STM32 merit co nejpresneji frekvenci v
 >> rozsahu cca 1000-3000 Hz, jak na to? Signal je k dispozici cca 1-2
 >> s, behem teto doby je potreba udelat co nejpresnejsi mereni.. signal
 >> je pred komparatorem dost zasumeny (SNR cca 10-25dB) - je to pro
 >> hratky s protonovym precesnim magnetometrem, kdyby to nekoho
 >> zajimalo...(pozdeji treba s Overhauserovym magnetometrem)
 >>  
 >> Pokud jsem to spravne pochopil, tak High Resolution Timer  ma sice
 >> nejake "events" priraditelne treba k vystupu komparatoru, ale jinak asi neni pro tento ucel vhodny?
 >>  
 >> Cili pouzit normalni 32-bit general purpose timer, taktovat ho co
 >> nejvyssi frekvenci - 180MHz treba pro STM32F446RE.. a pouzit input
 >> capture.. chteli bychom zkusit jestli ovzorkovani vsech nabeznych a
 >> sestupnych hran oproti prostemu zmereni prvni a posledni hrany treba
 >> z baliku 3000 period signalu 2000Hz (1.5s delka mereni) prinese nejake zlepseni..
 >>  
 >> Diky
 >> V.P.
 >> _______________________________________________
 >> HW-list mailing list  -  sponsored by www.HW.cz
 >> Hw-list na list.hw.cz
 >> http://list.hw.cz/mailman/listinfo/hw-list <http://list.hw.cz/mailman/listinfo/hw-list>
 _______________________________________________
 HW-list mailing list  -  sponsored by www.HW.cz
 Hw-list na list.hw.cz
 http://list.hw.cz/mailman/listinfo/hw-list <http://list.hw.cz/mailman/listinfo/hw-list>

------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20191205/0103e1ae/attachment.html>


Další informace o konferenci Hw-list