|
Переходные процессы в цифровых фильтрах, вопрос |
|
|
|
Mar 24 2011, 07:46
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 11-10-10
Из: Москва
Пользователь №: 60 055

|
Цитата(Zelepuk @ Mar 24 2011, 10:26)  Но как найти глубину этих буферов? Есть критерии? Буфер должен содержать данные, необходимые для расчета следующего выходного отсчета КИХ-фильтра, следовательно его размер должен быть никак не меньше порядка КИХ-фильтра, плюс к тому необходим некоторый запас - ведь в буфер с одной стороны поступают данные от АЦП - например по прерываниям от АЦП, и надо чтобы данные от АЦП не наползали на данные , которые Вы считываете при выполнении КИХ - фильтрации. Какой запас - зависит от скоростей обработки и входного потока. Если Вы обрабатываете данные - вычисляете следующий отсчет - в той же процедуре обработки прерывания, которая считывает данные из АЦП, то никакого запаса не надо, лишь бы процедура успевала закончиться до прихода следующего прерывания от АЦП. В Вашем случае Вам целесообразно в процедуре обработки прерывания выполнять сразу и децимацию - например при дцеимации в 8 раз просто пропускать 7 отсчетов и вычислять восьмой с помощью КИХ-фильтра, сохраняя выходные отсчеты в выходном кольцевом буфере - там поток будет в 8 раз меньше чем входной поток данных.
|
|
|
|
|
Mar 24 2011, 09:21
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 11-10-10
Из: Москва
Пользователь №: 60 055

|
Цитата(Zelepuk @ Mar 24 2011, 11:52)  а как же скорочть оработки? Думаю тут ещё важно за сколько процессор MAC делает... Допустим у Вас выборки поступают раз в 10 мкс, для децимации необходим фильтр с 50 коэффициентами, для которого надо 30 мкс времени. Также допустим что необходима децимация в 8 раз. Тогда Вы каждые 10 мкс сохраняете выборки в кольцевом буфере(входном) по прерыванию от АЦП, и каждый 8-й отсчет - т.е. 1 раз в 80 мкс запускаете фильтр. (не забудьте разрешить прерывания от АЦП в процедуре фильтра.) Тогда пока выполняется фильтр поступят еще 3 отсчета, которые затрут самые старые данные в буфере. Поэтому Вам надо или организовать процесс фильтрации так, чтобы к моменту прихода нового отсчета старые данные были бы уже не нужны - делать MAC-и от ранних отсчетов к поздним, или добавить 3 ячейки к кольцевому буферу и сделать его размером 53 ячейки. Так поступают если организация счета от ранних отсчетов к поздним занимает больше тактов(на переинициализацию указателей) чем счет от поздних к ранним отсчетам, а памяти не жалко.
Сообщение отредактировал Pavel_SSS - Mar 24 2011, 09:22
|
|
|
|
|
Mar 24 2011, 10:51
|

Местный
  
Группа: Участник
Сообщений: 240
Регистрация: 20-09-08
Пользователь №: 40 347

|
Код #include < stdio.h > #include < stdlib.h > #include < windows.h > #define _USE_MATH_DEFINES #include < math.h >
// фильтрация с буфером (функция не оптимальна, но принцип работы правильный) double filter(double xn, double* b, double* a, double* B, int N){ B[0] = xn; for(int i = 1; i<N; i++) B[0]-=a[i]*B[i]; double y = 0.0; for(int i = 0; i<N; i++) y+=b[i]*B[i]; memmove(B+1,B,(N-1)*sizeof(double)); return y; }
int main(){ // к-ты нерекурсивной части double b[4] = { 1.495242110818999600e-002, 3.165778089032666300e-002, 3.165778089032666300e-002, 1.495242110818999600e-002}; // к-ты рекурсивной части double a[4] = { 1.000000000000000000e+000, -2.137206690461268100e+000, 1.770779554588140800e+000, -5.403524601298397300e-001};
double x[100]; // исходный сигнал double y[1000]; // фильтрованный сигнал double B[4]; // кольцевой буфер memset(B,0,4*sizeof(double)); // обнуляю при старте
for (int n = 0; n<10; n++){ for(int i = 0; i<100; i++){ x[i]=(double)(rand()%1000) / 1000.0; // заполняю очередной кусок y[i+n*100] = filter(x[i],b,a,B,4); //и фильтрую очредной кусок } } return 0; } Вот пример фильтрации с буфером. Фильтрует куски без разрывов, принцип понять можно, хотя программа не оптимальна.
|
|
|
|
|
Mar 24 2011, 11:26
|
Знающий
   
Группа: Участник
Сообщений: 634
Регистрация: 27-10-10
Пользователь №: 60 464

|
Цитата(bahurin @ Mar 24 2011, 13:51)  Код #include < stdio.h > #include < stdlib.h > #include < windows.h > #define _USE_MATH_DEFINES #include < math.h >
// фильтрация с буфером (функция не оптимальна, но принцип работы правильный) double filter(double xn, double* b, double* a, double* B, int N){ B[0] = xn; for(int i = 1; i<N; i++) B[0]-=a[i]*B[i]; double y = 0.0; for(int i = 0; i<N; i++) y+=b[i]*B[i]; memmove(B+1,B,(N-1)*sizeof(double)); return y; }
int main(){ // к-ты нерекурсивной части double b[4] = { 1.495242110818999600e-002, 3.165778089032666300e-002, 3.165778089032666300e-002, 1.495242110818999600e-002}; // к-ты рекурсивной части double a[4] = { 1.000000000000000000e+000, -2.137206690461268100e+000, 1.770779554588140800e+000, -5.403524601298397300e-001};
double x[100]; // исходный сигнал double y[1000]; // фильтрованный сигнал double B[4]; // кольцевой буфер memset(B,0,4*sizeof(double)); // обнуляю при старте
for (int n = 0; n<10; n++){ for(int i = 0; i<100; i++){ x[i]=(double)(rand()%1000) / 1000.0; // заполняю очередной кусок y[i+n*100] = filter(x[i],b,a,B,4); //и фильтрую очредной кусок } } return 0; } Вот пример фильтрации с буфером. Фильтрует куски без разрывов, принцип понять можно, хотя программа не оптимальна. Благодарю за код.Как я понимаю здесь БИХ фильтр, так как присутствует рекурсивная часть?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|