Отговори на тема  [ 19 мнения ]  Отиди на страница Предишна  1, 2
Averaging (и малко линеаризация) 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Надявам се няма да е много нахално, ако поискам мнение относно още една функция. Става вьпрос за реализация на moving average, за което пише по-горе. Тук вече масива не ми мьрда, но предполагам има и по-интересни решения от това, което ми хрумна.
Пьрвия вариант сортира масива наново след всяко измерване. Голямо разхищени на ресурси:
Код:
/**********************
*   moving  average     *
*   ===========   *
**********************/
#define N 128       //average window size
#define BITS 7       //BITS = ld(N)

void moving_average(void)
{   unsigned int Array[N];
   unsigned int new_value;
   unsigned int result = 0;    
   unsigned int i;

   for(i=0; i<N; i++)             //fill the first N values
   {   ADST = 1;                         //start convertion
      while(!ADCIR);         //wait until ready
      Array[i] = ADDAT & 0x03FF;
   }

   while(!flag)                  //escape by Polling
   {   ADST = 1;   
      while(!ADCIR);         
      new_value = ADDAT & 0x03FF;     

      for(i=0; i<N-1; i++)
      Array[i] = Array[i+1];

      Array[N-1] = new_value;
      
      for(result=0, i=0; i<N; i++)
      result += Array[i];

      result >>= BITS;
   }
}



Вторият вариант е малко по-добьр. Използвам циркулярен буфер, като презаписвам наново елементите на масива. При препьлване на прозореца се почва от елемент 0 и т.н. 8кByte по-малко код и един спестен for.

Код:
/*******************************
*   optimized moving  average   *
*   =================   *
*******************************/
#define N 128       //average window size
#define BITS 7       //BITS = ld(N)

void moving_average2(void)
{   unsigned int Array[N];
   unsigned int new_value;
   unsigned int result = 0;    
   unsigned int i;
   unsigned int s = 0;

   for(i=0; i<N; i++)                           //fill the Array
   {   ADST = 1;                       
      while(!ADCIR);         
      Array[i] = ADDAT & 0x03FF;
   }


   while(!flag)                                //escape by Polling
   {   ADST = 1;   
      while(!ADCIR);         
      new_value = ADDAT & 0x03FF;     

      Array[s] = new_value;
      s++;
   
      if(i == N-1) i = 0;                    //end of the Array
      
      for(result=0, i=0; i<N; i++)      //do average
      result += Array[i];

      result >>= BITS;
   }
}



Вто Апр 03, 2007 9:33 pm
Профил WWW
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Вто Ное 16, 2004 4:43 pm
Мнения: 85
Местоположение: София
Мнение 
това не е верно:
Код:
if(i == N-1) i = 0;                    //end of the Array


Освен това бих го направил така:
Код:
#define N 128       //average window size
#define BITS 7       //BITS = ld(N)

void moving_average2(void)
{   unsigned int Array[N];
   unsigned int new_value;
   unsigned int result = 0;   
   unsigned int i;

   for(i=0; i<N; i++)                           //fill the Array
   {   ADST = 1;                       
      while(!ADCIR);         
      Array[i] = ADDAT & 0x03FF;
      result += Array[i];
   }

   i = 0;
   while(!flag)                                //escape by Polling
   { 
      ADST = 1;   
      while(!ADCIR);         
      new_value = ADDAT & 0x03FF;     

      result -= Array[i];
      result += new_value;
      Array[i] = new_value;
      i++;
      if (i == N) i = 0;                    //end of the Array
      result >>= BITS;
   }
}


Вто Апр 03, 2007 10:56 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Да бе вярно, правописна грешка :)
Така е правилно

Код:
if(s == N-1) s = 0;                    //end of the Array


Супер елегантно решение! Само последният ред трябва да се промени от:


Код:
     result >>= BITS;

нa
Код:
print_lcd(result >> BITS);


или чрез нова променлива
Код:
result2 = result >> BITS;


понеже в сегашния си вид презаписва некоректно result.
Мда, и result трябва да е unsigned long, защото 16bit-а може и да не стигнат в някои ситуации.


Вто Апр 03, 2007 11:51 pm
Профил WWW
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Вто Дек 14, 2004 1:31 pm
Мнения: 3849
Мнение 
Преди време бях писал един код за софтуерно пoвишаване разделителната способност на 10bit-ово ADC. Изваршват се 16 измервания, резултатьт се сумира и шифтва 2 пьти в дясно. Допьлнително вьрви усредняването на 128 имервания за подобряване на SNR. Иначе казано oversampling плюс averaging. Темата е обширно дискутирана тук
http://www.mcu-bg.com/mcu_site/viewtopi ... ersampling

Код:
#define OVER 16      // measurements for oversampling
#define OVER_DIV 2      // OVER_DIV = ld(OVER) / 2
#define AVERAGE 128      // measurements for averaging
#define AVERAGE_BITS 7   // AVERAGE_BITS = ld(AVERAGE)

while(i != AVERAGE)         // do 128 measurements for averaging
   {   for (a=0; a<OVER; a++)    // do 4^2 measurements for oversampling
      {   ADST = 1;                           
         while(ADCIR==0);         
         dl_second += ADDAT & 0x03FF;
      }   
      
      dl_second >>= OVER_DIV;   //oversampling division
      dl += dl_second;
      dl_second = 0;
      i++;
   }

   dl >>= AVERAGE_BITS;         //averaging division



Сега като се замисля, нищо не ми пречи да извьршвам измерванията на вьднъж. Така си спестявам един цикьл и едно делене. На хартия всичко изглежда наред. Само дето не се сещам, като сьм го писал това, дали не сьм имал нещо в предвид, което в момента не мога да сьобразя. A и кода не е коментиран особено добре. Някой сеща ли се за вьзможен проблем при тази реализация?

Код:
#define OVER 2048
#define AVERAGE_BITS 9

for (dl=0, a=0; a<OVER; a++)    // do 2048 measurements for oversampling and averaging
{   ADST = 1;                           
   while(ADCIR==0);         
   dl += ADDAT & 0x03FF;
}   
      
   dl >>= AVERAGE_BITS;   


П.П. Глупости пиша, разбира се, че няма проблем. Пьрвият вариант е дори излишно разточителен.


Сря Апр 04, 2007 1:33 pm
Профил WWW
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 19 мнения ]  Отиди на страница Предишна  1, 2

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 2 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни