Модифицированный алгоритм Герцеля

Heavy
Сообщения: 17
Зарегистрирован: 20 янв 2016, 16:12

Модифицированный алгоритм Герцеля

Сообщение Heavy »

Здравствуйте. Есть несколько вопросов по данной теме. Если точнее, то по реализации с вещественными умножениями.

Начиная с формулы 12 у меня появились вопросы.
В статье пишется:
"Пусть комплексный входной сигнал s(n) равен:
Первый вопрос: входные отсчеты не комплексные, так откуда взять q(n) ? Приравнять их нулю?

Второй вопрос: Допустим, у меня есть массив семплов, размерностью 100. Частота дискретизации 9000гц. Сигнал состоит из двух частот: 600 и 1000 гц. Тогда исходя из формулы 17, N должно быть больше 23. Правильно ли я понял?

Далее, формуле 16 имеем (n-N).
Второй вопрос: правильно ли я понимаю, что , если с АЦП я считал , допустим, всешл 6 семплов, то i(n-N) = 0, как и q(n-N). И правильно ли я понимаю, что q(n-N) всегда равны нулю, ибо входные семплы действительные?

Третий вопрос: Выходит, что нужно иметь один большой массив семплов, разбить его на участки размерностью N? Для первых N семплов i(n-N) принять равными нулю?

Четвертый вопрос: Модуль. Модуль - это корень из суммы квадратов I и Q ?

Аватара пользователя
Бахурин Сергей
Администратор
Сообщения: 1114
Зарегистрирован: 05 окт 2010, 19:55
Контактная информация:

Re: Модифицированный алгоритм Герцеля

Сообщение Бахурин Сергей »

Heavy писал(а): Здравствуйте. Есть несколько вопросов по данной теме. Если точнее, то по реализации с вещественными умножениями.

Начиная с формулы 12 у меня появились вопросы.
В статье пишется:
"Пусть комплексный входной сигнал s(n) равен:
Первый вопрос: входные отсчеты не комплексные, так откуда взять q(n) ? Приравнять их нулю?
Да просто считать равными нулю.
Heavy писал(а): Второй вопрос: Допустим, у меня есть массив семплов, размерностью 100. Частота дискретизации 9000гц. Сигнал состоит из двух частот: 600 и 1000 гц. Тогда исходя из формулы 17, N должно быть больше 23. Правильно ли я понял?
Правильно, но это не означает что надо использовать 23. Можно использовать значение большее чем 23 для того чтобы спектральные отсчеты отстояли друг от друга на бОльшую величину отсчетов.
Heavy писал(а): Далее, формуле 16 имеем (n-N).
Второй вопрос: правильно ли я понимаю, что , если с АЦП я считал , допустим, всешл 6 семплов, то i(n-N) = 0, как и q(n-N). И правильно ли я понимаю, что q(n-N) всегда равны нулю, ибо входные семплы действительные?
Да отсчеты с отрицательными индексами можно принять равными нулю.
Heavy писал(а): Третий вопрос: Выходит, что нужно иметь один большой массив семплов, разбить его на участки размерностью N? Для первых N семплов i(n-N) принять равными нулю?
Не надо ничего разбивать. Это просто фильтр, который обрабатывает ваш массив по одному сэмплу. При этом когда буфер задержек заполнится и все индексы станут положительными, то каждый сэмпл вы будете иметь обновленное значение спектрального отсчета.
Heavy писал(а): Четвертый вопрос: Модуль. Модуль - это корень из суммы квадратов I и Q ?
Да все верно.

Heavy
Сообщения: 17
Зарегистрирован: 20 янв 2016, 16:12

Re: Модифицированный алгоритм Герцеля

Сообщение Heavy »

Бахурин Сергей писал(а): Правильно, но это не означает что надо использовать 23. Можно использовать значение большее чем 23 для того чтобы спектральные отсчеты отстояли друг от друга на бОльшую величину отсчетов.
:?
Может быть на меньшую величину отсчетов? Чем больше N,тем больше разрешение по частоте вроде как, то есть тем меньше расстояние по частоте между бинами.

Аватара пользователя
Бахурин Сергей
Администратор
Сообщения: 1114
Зарегистрирован: 05 окт 2010, 19:55
Контактная информация:

Re: Модифицированный алгоритм Герцеля

Сообщение Бахурин Сергей »

Heavy писал(а): Может быть на меньшую величину отсчетов? Чем больше N,тем больше разрешение по частоте вроде как, то есть тем меньше расстояние по частоте между бинами.
Да расстояние между бинами будет меньше и как результат между двумя гармониками 100 и 600 Гц будет больше спектральных бинов. Это хорошо потому что гармоники отстоят друг от друга на большее количество бинов и легче различимы

Heavy
Сообщения: 17
Зарегистрирован: 20 янв 2016, 16:12

Re: Модифицированный алгоритм Герцеля

Сообщение Heavy »

Написал код на Си:
Изображение
https://pp.vk.me/c630722/v630722756/104 ... rv6xSg.jpg
Модули выдает всегда разные:
Изображение
https://pp.vk.me/c630722/v630722756/104 ... rRTaOI.jpg
Как это понимать? По идее модуль должен быть всегда одинаков, раз частота присутствует постоянно.

Аватара пользователя
Бахурин Сергей
Администратор
Сообщения: 1114
Зарегистрирован: 05 окт 2010, 19:55
Контактная информация:

Re: Модифицированный алгоритм Герцеля

Сообщение Бахурин Сергей »

Мой компилятор не поддерживает исходники в виде png картинок. Пожалуйста приведите код в виде текста используя тег code

Heavy
Сообщения: 17
Зарегистрирован: 20 янв 2016, 16:12

Re: Модифицированный алгоритм Герцеля

Сообщение Heavy »

:D

Код: Выделить всё

#define Fd 9000 //частота дискретизации
#define f1 600  //частота тона
#define f_search 600 //искомая алгоритмом частота
#define N 70 //размер массива
int main()
{
unsigned char ADC[350]; //Массив, эмулирующий поток из АЦП
unsigned char buff[N]; //Буфер, в который пишутся данные из АЦП
float I[2]; 
float Q[2];
float a;
float b;
float c = 2* M_PI *f1/Fd; //Заранее рассчитаем то, что не будет меняться
float module; //здесь будет лежать модуль комплексного числа
I[0]=0; I[1]=0; //инициализируем массивы
Q[0]=0; Q[1]=0;
for (int i =0; i<350; i++)
{
    ADC[i] = (unsigned char) 100*sin(c*i)+100; //заполняем "поток" АЦП синусом с амплитудой от 0 до 100

}

a=cos(2*M_PI*f_search/N); //рассчитываем к-ты
b=sin(2*M_PI*f_search/N);

for (int n=0; n<70; n++) //начальное заполнение буфера
{
    I[0]=I[1]; //Готовим предыдущее I
    Q[0]=Q[1]; 
    buff[n]=ADC[n]; // Просто заполняем буфер данными из АЦП
    I[1]=a*(I[0]+buff[n])-b*Q[0]; //Все по формуле 16 из статьи
    Q[1]=a*Q[0]+b*(I[0]+buff[n]);

}
for (int n=70; n<350; n++) //Когда буфер заполнился, то запускаем цикл с выталкиванием
{
    I[0]=I[1];
    Q[0]=Q[1];
    I[1]=a*(I[0]+ADC[n]-buff[0])-b*Q[0]; //В качестве i(n) выступает ADC(n), где n=70. Следовательно buff(n-N)=buff(0)
    Q[1]=a*Q[0]+b*(I[0]+ADC[n]-buff[0]); 
    for (int nn=0; nn<69; nn++) //перемещаем элементы массива на 1 влево
    {
        buff[nn]=buff[nn+1]; 
    }
    buff[69]=ADC[n]; //Заносим полученное значение АЦП на данном цикле работы алгоритма в последний эллемент буфера
    module = sqrt(I[1]*I[1]+Q[1]*Q[1]); //вычисляем модуль комплексного числа
}
//конец работы алгоритма
}

Heavy
Сообщения: 17
Зарегистрирован: 20 янв 2016, 16:12

Re: Модифицированный алгоритм Герцеля

Сообщение Heavy »

Забыл перевести градусы в радианы. Перевел, все равно модуль пляшет

Аватара пользователя
Бахурин Сергей
Администратор
Сообщения: 1114
Зарегистрирован: 05 окт 2010, 19:55
Контактная информация:

Re: Модифицированный алгоритм Герцеля

Сообщение Бахурин Сергей »

несколько ошибок:
1) Fd =9000 f1=600 и N=70 не дают целого номера спектрального отсчета. Я бы взял N = 90
2) Не учтен параметр k0
3) Ошибка в реализации цикла.
Правильный код:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#define Fd 9000 
#define f1 600  
#define f_search 600

#define N 90 

#define K	350


int main()
{
	unsigned char ADC[K]; 

	float I[2]; 
	float Q[2];
	float a;
	float b;
	float c = 2* M_PI *f1/Fd; 
	float module; 
	float k0;
	float u;
	int n;

	I[0]=0; I[1]=0; 
	Q[0]=0; Q[1]=0;
	for (n =0; n<K; n++)
		ADC[n] = (unsigned char) 100*sin(c*n)+100; 


	k0 =	(float)f_search / ((float)Fd/(float)N);

	a=cos(2*M_PI*k0/N); 
	b=sin(2*M_PI*k0/N);

	for (n=0; n<K; n++) 
	{
		I[0]=I[1]; 
		Q[0]=Q[1]; 

		u = I[0] + ADC[n] - ((n>=N) ? ADC[n-N] : 0.0); 
		
		I[1]= u*a  - b*Q[0]; 
		Q[1]= u*b  + a*Q[0];
		
		module = sqrt(I[1]*I[1] + Q[1]*Q[1]);
		
		printf("%.4f\n", module);
	}
	return 0;
}

Heavy
Сообщения: 17
Зарегистрирован: 20 янв 2016, 16:12

Re: Модифицированный алгоритм Герцеля

Сообщение Heavy »

Теперь понял. k0 - это номер спектрального отсчета, а не искомая частота. Перепутал понятия. В ЦОС новичок совсем. Спасибо. Попробую осмыслить и протестировать

Ответить