реклама на сайте
подробности

 
 
> Как реализовать генератор квадратуры, Надо генерировать cos/sin одинаковой чатоты в DSP
Russky
сообщение Dec 10 2014, 15:43
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Всем привет!
Вот есть задача - генерировать квадратурный сигнал для DDC. DDC сам реализован внутри DSP, поэтому надо алгоритм чтобы его можно было-бы реализвать потом на аасемблере.
Используется плавующая точка.
В идеальном случае ф-я должна выглядеть так:
result = GenSinCos(float freq); где result это структура содержащая Cos и Sin, т.е. сигналы сдвинуты на 90 градусов.
freq - 0...1.
Ф-я вызывается для каждого отсчета. Начальная фаза в общем не очень важна. Главное чтобы 90 градусов было. По идее это даже не ф-я а макрос.
Как-то так.
Может кто уже встречал подобное? Или может уже есть готовые решения?

Особенность в том, что наверняка есть решение которое не вызывает ф-ю sin и cos каждый раз. sm.gif

Спасибо!

PS. Табличный метод не предлагать! sm.gif


Сообщение отредактировал Russky - Dec 10 2014, 15:56
Go to the top of the page
 
+Quote Post
4 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 52)
Lmx2315
сообщение Dec 10 2014, 17:00
Сообщение #2


отэц
*****

Группа: Свой
Сообщений: 1 729
Регистрация: 18-09-05
Из: Москва
Пользователь №: 8 684



QUOTE (Russky @ Dec 10 2014, 18:43) *
Особенность в том, что наверняка есть решение которое не вызывает ф-ю sin и cos каждый раз. sm.gif
....
PS. Табличный метод не предлагать! sm.gif

..не понял я что-то, вы считать не хотите и в таблицу смотреть, тогда как же?
з.ы.
другое дело что синус посчитать по разному можно, но считать надо таки.


--------------------
b4edbc0f854dda469460aa1aa a5ba2bd36cbe9d4bc8f92179f 8f3fec5d9da7f0
SHA-256
Go to the top of the page
 
+Quote Post
des00
сообщение Dec 10 2014, 17:43
Сообщение #3


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



Цитата(Russky @ Dec 10 2014, 22:43) *
Особенность в том, что наверняка есть решение которое не вызывает ф-ю sin и cos каждый раз. sm.gif

sin = sqrt(1 - cos^2) ?


--------------------
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 10 2014, 17:54
Сообщение #4


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Это прекрасно!! хороший синус. будет всегда не меньше 1. а иногда и побольше.

Цитата(des00 @ Dec 10 2014, 18:43) *
sin = sqrt(1 + cos^2) ?


Что касается начальной задачи, то решение есть!!! явочным порядком можно вызывть синус и косинус например каждый 10-й раз.. или даже 100-й. можно вообще ни разу не вызывать. всё зависит ведь от необходимой точности описания функций
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 10 2014, 18:17
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



c(n)=cos(2*pi*f0/sf*n)

s(n)=k*c(n)+c(n-1)-k*s(n-1)

k=(sin(2*pi*f0/sf)-1)/(sin(2*pi*f0/sf+pi/2))
Go to the top of the page
 
+Quote Post
blackfin
сообщение Dec 10 2014, 18:29
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(Fat Robot @ Dec 10 2014, 21:54) *
Это прекрасно!! хороший синус. будет всегда не меньше 1. а иногда и побольше.

Это точно! Вот хороший синус: sin(pi/2 - 2.06345i) = 4.0001. biggrin.gif
Go to the top of the page
 
+Quote Post
des00
сообщение Dec 10 2014, 18:53
Сообщение #7


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



Цитата(Fat Robot @ Dec 11 2014, 01:54) *
Это прекрасно!! хороший синус. будет всегда не меньше 1. а иногда и побольше.

большое спасибо за правку, торопился и ошибся



--------------------
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 10 2014, 19:33
Сообщение #8


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Ну, конечно, CORDIC. Какие могут быть сомнения?!
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 10 2014, 20:35
Сообщение #9


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



На вычислительных платформах, на которых цена уножения равна цене сложения, а это любые dsp, смысла в кордике нет.

Цитата(ViKo @ Dec 10 2014, 20:33) *
Ну, конечно, CORDIC. Какие могут быть сомнения?!

Go to the top of the page
 
+Quote Post
Russky
сообщение Dec 11 2014, 11:53
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Поясню. Есть методы генерирования синусоидально сигнала на основе биквада. Т.е. там просто рекурсивно вычисляется каждое следуюшее значение. Генератор в чистом виде.
Там меняя коэффициенты биквада, можно менять частоту. Там фаза не важна, важна только частота.
Я думаю, что должны быть методы, которые позволяют генерировать синус и косинус вместе, подобным образом. Дополнительным условием для данной ф-и есть разница фаз в 90 градусов.
Т.е либо начальные условия для генератора задавать, либо еще что-то. Но в общем это должно быть рекурсивное вычисление, где каждый следующий отсчет зависит от предыдущих. Это не синус и косинус в чистом виде. Нужен именно генератор (так как он более экономичен к вычислениям).



Go to the top of the page
 
+Quote Post
blackfin
сообщение Dec 11 2014, 12:48
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(Russky @ Dec 11 2014, 14:53) *
Но в общем это должно быть рекурсивное вычисление, где каждый следующий отсчет зависит от предыдущих. Это не синус и косинус в чистом виде.

Нужен именно генератор (так как он более экономичен к вычислениям).

Школьная тригонометрия рулит.. rolleyes.gif

sin[2*pi*f*(t+Δt)] = sin[2*pi*f*t] * cos[2*pi*f*Δt] + cos[2*pi*f*t] * sin[2*pi*f*Δt];
cos[2*pi*f*(t+Δt)] = cos[2*pi*f*t] * cos[2*pi*f*Δt] - sin[2*pi*f*t] * sin[2*pi*f*Δt];

Полагая, что t+Δt == (n+1)*Δt, находим формулы рекурсии:

sinn+1 == sin[2*pi*f*(n+1)*Δt] = sin[2*pi*f*n*Δt] * cos[2*pi*f*Δt] + cos[2*pi*f*n*Δt] * sin[2*pi*f*Δt] == sinn * cos[2*pi*f*Δt] + cosn * sin[2*pi*f*Δt];
cosn+1 == cos[2*pi*f*(n+1)*Δt] = cos[2*pi*f*n*Δt] * cos[2*pi*f*Δt] - sin[2*pi*f*n*Δt] * sin[2*pi*f*Δt] == cosn * cos[2*pi*f*Δt] - sinn * sin[2*pi*f*Δt];

Понятно, что sin[2*pi*f*Δt] и cos[2*pi*f*Δt] это константы, зависящие от f и Δt и выбираются так, чтобы 1/(f*Δt) = 2N == nmax+1.

Начальные значения:

sin0 = 0;
cos0 = 1;

Значения после переполнения счетчика n = (nmax+1)%2N == 0, полагаем равными:

sin2N = 0;
cos2N = 1;

Это предотвратит накопление ошибок..
Go to the top of the page
 
+Quote Post
andyp
сообщение Dec 11 2014, 14:06
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 453
Регистрация: 23-07-08
Пользователь №: 39 163



Цитата(Fat Robot @ Dec 10 2014, 20:54) *
Что касается начальной задачи, то решение есть!!! явочным порядком можно вызывть синус и косинус например каждый 10-й раз.. или даже 100-й. можно вообще ни разу не вызывать. всё зависит ведь от необходимой точности описания функций


Соглашусь FatRobot, выбор алгоритма должен определяться тем, сколько надо SFDR и сколько mips можно потратить. Отбрасывать что-то с порога глупо.
Go to the top of the page
 
+Quote Post
Russky
сообщение Dec 11 2014, 18:34
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Цитата(blackfin @ Dec 11 2014, 16:48) *
Школьная тригонометрия рулит.. rolleyes.gif
...
Это предотвратит накопление ошибок..

Спасибо. Надо попробовать.
Как попробую - напишу.
Пока все выглядет очень даже ничего! sm.gif
Go to the top of the page
 
+Quote Post
stealth-coder
сообщение Dec 11 2014, 20:30
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 112
Регистрация: 27-12-08
Пользователь №: 42 786



Цитата(Fat Robot @ Dec 11 2014, 00:35) *
На вычислительных платформах, на которых цена уножения равна цене сложения, а это любые dsp, смысла в кордике нет.

Насчет любых DSP не согласен. Недавно решали задачу, в которой нужно вычислять много арктангенсов, DSP TigerSHARC 101, CORDIC + SIMD дал результат лучше (в смысле вычислительных затрат) чем оптимизированный полиномиальный, хотя отдельно взятый CORDIC проигрывает.

ТС: хочу обратить Ваше внимание, что в DDC с целью подавления спуров при генерации квадратурной гармоники используются некоторые хитрости, например, младшие разряды заменяются на соответствующий отрезок ПСП. Если не ошибаюсь, в Матлабе есть такая модель (или у Xilinx-а в генераторе корок, запамятовал уже).
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 11 2014, 20:53
Сообщение #15


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Тут всё на веру, конечно. Не ставя под сомнение квалификацию. Но вот здесь http://www.opensource.apple.com/source/Lib...ce/Intel/atan.c
за где-то 15 умножений и 15 сложений получается точность double на входе и выходе для atan.

Цитата(stealth-coder @ Dec 11 2014, 21:30) *
Насчет любых DSP не согласен. Недавно решали задачу, в которой нужно вычислять много арктангенсов, DSP TigerSHARC 101, CORDIC + SIMD дал результат лучше (в смысле вычислительных затрат) чем оптимизированный полиномиальный, хотя отдельно взятый CORDIC проигрывает.
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 11 2014, 20:59
Сообщение #16


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(Russky @ Dec 11 2014, 21:34) *
Спасибо. Надо попробовать.
Как попробую - напишу.
Пока все выглядет очень даже ничего! sm.gif



кто/что мешает генерить синус-косинус двумя параллельными биквадратными звеньями?
начальная фаза целиком и прлностью определяется начальными условиями звеньев.
умножений в 2 раза меньше чем в школьнотригонометрическом методе.
Go to the top of the page
 
+Quote Post
stealth-coder
сообщение Dec 11 2014, 21:09
Сообщение #17


Частый гость
**

Группа: Участник
Сообщений: 112
Регистрация: 27-12-08
Пользователь №: 42 786



Цитата(Fat Robot @ Dec 12 2014, 00:53) *
Тут всё на веру, конечно. Не ставя под сомнение квалификацию. Но вот здесь http://www.opensource.apple.com/source/Lib...ce/Intel/atan.c
за где-то 15 умножений и 15 сложений получается точность double для atan.


Там есть страшная вещь - зависимость по данным, которая рушит конвейер, от нее не уйти и сходу просаживается производительность (в случае TigerSHARC) минимум в 2 раза, возможности SIMD при использовании плавающей точки ограничены, использование фиксированной точки для реализации приведенного алгоритма сомнительно, т.к., скорее всего, очень быстро накопится достаточно большая ошибка. Ну и в приведенной реализации нет операции деления Im / Re, что в случае DSP, как правило, делается каким-нибудь Ньютоном-Рафсоном, CORDIC же позволяет не выполнять деление.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Dec 12 2014, 02:22
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(thermit @ Dec 11 2014, 23:59) *
кто/что мешает генерить синус-косинус двумя параллельными биквадратными звеньями?
умножений в 2 раза меньше чем в школьнотригонометрическом методе.

А во сколько раз больше сложений? wink.gif
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 12 2014, 06:32
Сообщение #19


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(blackfin @ Dec 12 2014, 05:22) *
А во сколько раз больше сложений? wink.gif



в 1.
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 12 2014, 10:35
Сообщение #20


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Как вы оцениваете, при таком подходе через сколько сгенерированных отсчетов существенно изменятся амплитуды квадратур (+/- 10% разность или каждая) и/или разность их фаз (pi/20)? За счет округлений.

Все операции, например, соответствуют 754 float.

Я полагаю, что за пару часов при 10 MSPS и при 1 MHz на выходе от квадратур в таком генераторе уже ничего не останется.

Цитата(thermit @ Dec 11 2014, 21:59) *
кто/что мешает генерить синус-косинус двумя параллельными биквадратными звеньями?
начальная фаза целиком и прлностью определяется начальными условиями звеньев.
умножений в 2 раза меньше чем в школьнотригонометрическом методе.
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 12 2014, 11:11
Сообщение #21


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(Fat Robot @ Dec 12 2014, 14:35) *
Как вы оцениваете, при таком подходе через сколько сгенерированных отсчетов существенно изменятся амплитуды квадратур (+/- 10% разность или каждая) и/или разность фаз (pi/20)? За счет округлений.

Все операции, например, соответствуют 754 float.

Я полагаю, что за пару часов при 10 MSPS и при 1 MHz на выходе от квадратур в таком генераторе уже ничего не останется.


Никак не оцениваю, ибо оценка качества таких генераторов и необходимость периодического сброса сводит все их прелести почти к 0.
Это тс фанатеет рекурсиями, которые на конечной разрядности дают рост ошибок.
А для меня полиномы/кордики рулят.
Go to the top of the page
 
+Quote Post
andyp
сообщение Dec 12 2014, 11:39
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 453
Регистрация: 23-07-08
Пользователь №: 39 163



Цитата(thermit @ Dec 12 2014, 14:11) *
А для меня полиномы/кордики рулят.


LUT с линейной интерполяцией - наше все wink.gif Ну и всякие навороты типа noise shaping или phase dithering, если охота шибко умным побыть.
Go to the top of the page
 
+Quote Post
Russky
сообщение Dec 15 2014, 14:07
Сообщение #23


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Цитата(thermit @ Dec 12 2014, 15:11) *
Никак не оцениваю, ибо оценка качества таких генераторов и необходимость периодического сброса сводит все их прелести почти к 0.
Это тс фанатеет рекурсиями, которые на конечной разрядности дают рост ошибок.
А для меня полиномы/кордики рулят.

Тогда у-ж лучще табличным методом генерить. Там вообще никаких ни шумов, ни ошибок, и выполняется за 1 такт. sm.gif

PS. Кстати, а вот и ответ: генератор делается на основе формулы предложенной Blackfinом и таблицей. Т.е. если у меня в потоке обрабатывается по 128 отсчетов, то все что мне нужно это каждый раз инициализировать значение синуса и косинуса, значениями из таблицы, а потом считать рекурсию на 128 отсчетов. И так далее. sm.gif

Сообщение отредактировал Russky - Dec 15 2014, 14:11
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 15 2014, 14:51
Сообщение #24


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



грустный смайлик..

Цитата(Russky @ Dec 15 2014, 15:07) *
Тогда у-ж лучще табличным методом генерить. Там вообще никаких ни шумов, ни ошибок... sm.gif

Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 15 2014, 14:59
Сообщение #25


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(Russky @ Dec 15 2014, 18:07) *
Тогда у-ж лучще табличным методом генерить. Там вообще никаких ни шумов, ни ошибок, и выполняется за 1 такт. sm.gif

PS. Кстати, а вот и ответ: генератор делается на основе формулы предложенной Blackfinом и таблицей. Т.е. если у меня в потоке обрабатывается по 128 отсчетов, то все что мне нужно это каждый раз инициализировать значение синуса и косинуса, значениями из таблицы, а потом считать рекурсию на 128 отсчетов. И так далее. sm.gif


Ну, вам виднее.
Go to the top of the page
 
+Quote Post
blackfin
сообщение Dec 15 2014, 15:12
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(Russky @ Dec 15 2014, 18:07) *
Т.е. если у меня в потоке обрабатывается по 128 отсчетов, то все что мне нужно это каждый раз инициализировать значение синуса и косинуса, значениями из таблицы, а потом считать рекурсию на 128 отсчетов. И так далее. sm.gif

И нужно помнить, что ошибки амплитуды и фазы будут расти примерно как:

sqrt(N)*0.5 [LSB] = sqrt(128)*0.5 [LSB] ~= 5.7 [LSB].

Так что на последних отсчетах три младших разряда в амплитуде и фазе могут быть неверными. wink.gif
Go to the top of the page
 
+Quote Post
Russky
сообщение Dec 15 2014, 16:31
Сообщение #27


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Цитата(blackfin @ Dec 15 2014, 19:12) *
И нужно помнить, что ошибки амплитуды и фазы будут расти примерно как:

sqrt(N)*0.5 [LSB] = sqrt(128)*0.5 [LSB] ~= 5.7 [LSB].

Так что на последних отсчетах три младших разряда в амплитуде и фазе могут быть неверными. wink.gif


У меня плавучка.
Там немного подругому. Но в любом случае 128 отсчетов это не так много даже для 24 бит фиксированной точки. Но при этом есть возможность увеличить разрешающую способность генератора в 128 раз, или 128*K, где K - может быть и больше. В итоге мы получим разрешающую способность - N*M, где N - длина таблицы, а M - количество отсчетов генератора. Круто короче.
В общем надо пробовать реализвать. sm.gif
В любом случае - спасибо! Я как-то сразу сам не додумался до этого.
Это тот редкий случай когда обсуждение на форуме приводит к рождению нового эффективного алгоритма. sm.gif
Go to the top of the page
 
+Quote Post
amaora
сообщение Dec 15 2014, 16:42
Сообщение #28


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



Умножать на матрицу поворота и нормировать на каждом такте. Для низких частот можно упростить считая, что sin(x) ~ x, cos(x) ~ 1. Можно не упрощать, если частота фиксированная то sin/cos считаются один раз.

Код
pm->tA.re += -pm->tA.im * pm->tD.im;
pm->tA.im += pm->tA.re * pm->tD.im;

L = (3.f - pm->tA.re * pm->tA.re - pm->tA.im * pm->tA.im) * .5f;
pm->tA.re *= L;
pm->tA.im *= L;


Сообщение отредактировал amaora - Dec 15 2014, 16:43
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 15 2014, 17:57
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(amaora @ Dec 15 2014, 22:42) *
Умножать на матрицу поворота и нормировать на каждом такте.

так ошибка будет накапливаться.
по сравнению с вариантом от blackfin, можно еще одно умножение сэкономить если Sin[n+1] выразить через Sin[n] и Sin[n-1].
Sin[n+1] = Sin[n]*K - Sin[n-1];
да и со стабильностью вроде будет получше, не?
в целых числах если считать, то вообще ничего никуда не расползается, а с ошибками округления floatов - не знаю.

http://web.archive.org/web/20120308235958/...ors.html#Second Order Oscillator
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 15 2014, 21:45
Сообщение #30


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(_pv @ Dec 15 2014, 20:57) *
так ошибка будет накапливаться.
по сравнению с вариантом от blackfin, можно еще одно умножение сэкономить если Sin[n+1] выразить через Sin[n] и Sin[n-1].
Sin[n+1] = Sin[n]*K - Sin[n-1];
да и со стабильностью вроде будет получше, не?
в целых числах если считать, то вообще ничего никуда не расползается, а с ошибками округления floatов - не знаю.

http://web.archive.org/web/20120308235958/...ors.html#Second Order Oscillator


гы, да ладно...
http://electronix.ru/forum/index.php?s=&am...t&p=1298367

ну и конечно, все расползается.

Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 15 2014, 22:31
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(thermit @ Dec 16 2014, 03:45) *

чукча - не читатель, чукча - писатель.
Цитата(thermit @ Dec 16 2014, 03:45) *
ну и конечно, все расползается.

школьно-тригонометрический - да, а вот осциллятор второго порядка вроде как абсолютно стабильный должен быть с целочисленной арифметикой.
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 15 2014, 22:50
Сообщение #32


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(_pv @ Dec 16 2014, 01:31) *
чукча - не читатель, чукча - писатель.

школьно-тригонометрический - да, а вот осциллятор второго порядка вроде как стабильный должен быть.



угу. всенепременно.

Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 15 2014, 22:53
Сообщение #33


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Вы сами себе противоречите: Чтобы генератор был "абсолютно стабилен", полюсы его передаточной функции должны находиться точно на единичной окружности. А для любой частоты при арифметике с конечной разрядностью это, увы, не выполняется.

Цитата(_pv @ Dec 15 2014, 23:31) *
вроде как
должен быть
с целочисленной арифметикой
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 15 2014, 23:46
Сообщение #34


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(Fat Robot @ Dec 16 2014, 01:53) *
Вы сами себе противоречите: Чтобы генератор был "абсолютно стабилен", полюсы его передаточной функции должны находиться точно на единичной окружности. А для любой частоты при арифметике с конечной разрядностью это, увы, не выполняется.


увы, тока это и выполняется вне зависимости от разрядности.
в случае биквадратного звена только результат после умножения на а1 квантуется. шум квантования есть вход для фильтра с полюсами на единичной окружности. т е неустойчивого фильтра. результат закономерен.
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 08:11
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Fat Robot @ Dec 16 2014, 04:53) *
Вы сами себе противоречите: Чтобы генератор был "абсолютно стабилен", полюсы его передаточной функции должны находиться точно на единичной окружности. А для любой частоты при арифметике с конечной разрядностью это, увы, не выполняется.

с целочисленной арифметикой можно точно в желаемую частоту и амплитуду не попасть, но осциллятор будет стабильным сколь угодно долго.
Цитата(thermit)
в случае биквадратного звена только результат после умножения на а1 квантуется. шум квантования есть вход для фильтра с полюсами на единичной окружности. т е неустойчивого фильтра. результат закономерен.


int a0, a1 = 0, a2 = 100, K=450;
for (int i = 0; i < 1000; i++){
a0 = (K*a1)/256 - a2;
a2 = a1;
a1 = a0;
printf("%d\n",a0);
}
через 765*N шагов, значения a0,a1,a2 опять станут -100, 0, 100, почему же он не развалился раз он не устойчивый?
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 16 2014, 08:31
Сообщение #36


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Я посчитал. Устойчивость действительного генератора определяется только шумами квантования отсчетов,
в отличие от комплексного, где и квантованные отсчеты, и квантованные коэффициенты играют роль.

Цитата(thermit @ Dec 16 2014, 00:46) *
увы, тока это и выполняется вне зависимости от разрядности.


Хороший пример. Много подтверждает (limit cycles при единственном значении коэффициента).

Попробуйте так:
К = 45 * pi * pi;

Цитата(_pv @ Dec 16 2014, 09:11) *
с целочисленной арифметикой можно точно в желаемую частоту и амплитуду не попасть, но осциллятор будет стабильным сколь угодно долго.


int a0, a1 = 0, a2 = 100, K=450;
for (int i = 0; i < 1000; i++){
a0 = (K*a1)/256 - a2;
a2 = a1;
a1 = a0;
printf("%d\n",a0);
}
через 765*N шагов, значения a0,a1,a2 опять станут -100, 0, 100, почему же он не развалился раз он не устойчивый?
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 08:56
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Fat Robot @ Dec 16 2014, 14:31) *
Хороший пример. Много подтверждает (limit cycles при единственном значении коэффициента).
Попробуйте так:
К = 45 * pi * pi;

а как же: "А для любой частоты при арифметике с конечной разрядностью это, увы, не выполняется." ?

45*pi*pi = 444
арифметика-то целая, в частоту немного не попадёт из-за округления, но работать будет стабильно:
0
100
173
200
173
100
0
-100
-173
-200
-173
-100
0
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 16 2014, 09:30
Сообщение #38


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



.
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 09:49
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Fat Robot @ Dec 16 2014, 15:30) *
Вам бы функцией printf научиться пользоваться.
Начните с "Hello world!"
Успехов

давайте поможем друг другу, Вы мне расскажете как правильно printf пользоваться, а я Вам - чем арфиметика с плавающей запятой от целочисленной отличается.
а потом вернёмся к вопросам устойчивости.
Go to the top of the page
 
+Quote Post
amaora
сообщение Dec 16 2014, 10:58
Сообщение #40


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



Если элементы матрицы поворота посчитать как настоящие sin/cos без приближения, то погрешности будут не намного больше чем в лобовом способе с вызовом sin/cos на каждом такте. Ничего не расползется, нормирование для этого есть.

Если же считать sin(x) ~ x, то будет погрешность задания частоты и как следствие уход фазы. Чем крупнее шаг, тем больше погрешность. По амплитуде погрешность постоянная и небольшая, и тоже зависит от шага.

Да и sin/cos всегда согласованы по фазе в отличии от методов раздельной их генерации.
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 11:05
Сообщение #41


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(amaora @ Dec 16 2014, 16:58) *
Если элементы матрицы поворота посчитать как настоящие sin/cos без приближения, то погрешности будут не намного больше чем в лобовом способе с вызовом sin/cos на каждом такте. Ничего не расползется, нормирование для этого есть.
Если же считать sin(x) ~ x, то будет погрешность задания частоты и как следствие уход фазы. Чем крупнее шаг, тем больше погрешность. По амплитуде погрешность постоянная и небольшая, и тоже зависит от шага.
Да и sin/cos всегда согласованы по фазе в отличии от методов раздельной их генерации.

расползётся причем синус от косинуса по фазе тоже, так как ошибка будет копиться на каждом шаге.
при раздельной генерации косинус можно получить просто как производную от синуса.
Go to the top of the page
 
+Quote Post
Russky
сообщение Dec 16 2014, 11:08
Сообщение #42


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Что-то мы скатились на обсуждение ерунды.

Ситуация с ф-й генератора вот какая.
Когда мы описываем те или иные методы, надо всегода смотреть на то, как данная ф-я будет использоваться.
Вот у меня задача достаточно общая:
есть приложение в котором используется DDC. Для этого DDC мне нужен генератор квадратуры с постоянной частотойк. Значение частоты может меняться, но не в реальном времени.
Т.е. получаем вот что. То что считается постоянно в реал-тайме критично ко времени. То что относится к расчету параметров - не критично. В итоге получается, что расчитать один раз sin/cos/step и т.д. это не проблема, но зато потом просто умножать нару раз и выбирать значения из таблицы.
В общем метод Blackfinа самое то. Сам генератор там состоит из вдух сложений и четырех умножений. А инициализация приращения и шаг таблицы расчитываются неспеша как угодно. Причем это "именно то" при условии что значения генератора реинициализируются через фиксированные промежутки (в моем случае 128 отсчетов).

Методы генерирования на основе расчета синуса и косинуса "налету" с помощью полиномов и т.д. имеют свое применение. Например когда у меня частота меняется в реальном времени и я ее должен постоянно подстраивать на основе ФАПЧ или что-то такое. В этом случае конечно надо делать генератор на основе прямого расчета синуса и косинуса.
То-же самое относится когда генератор должен работать на "бесконечном интервале времени". Тут шумы никуда не уйдут, и генератор просто "зазвенит". sm.gif

В общем, побеждает как всегда компромис. sm.gif
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 11:25
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Russky @ Dec 16 2014, 17:08) *
В общем метод Blackfinа самое то. Сам генератор там состоит из вдух сложений и четырех умножений. А инициализация приращения и шаг таблицы расчитываются неспеша как угодно. Причем это "именно то" при условии что значения генератора реинициализируются через фиксированные промежутки (в моем случае 128 отсчетов).

генератор путём умножениея на матрицу поворота нестабилен, а если реинициализировать его каждые 128 шагов, то синус/косинус всё равно придётся честно вычислять для текущего значения фазы при реинициализации.
Go to the top of the page
 
+Quote Post
amaora
сообщение Dec 16 2014, 11:33
Сообщение #44


Местный
***

Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778



Цитата(_pv @ Dec 16 2014, 14:05) *
расползётся причем синус от косинуса по фазе тоже, так как ошибка будет копиться на каждом шаге.
при раздельной генерации косинус можно получить просто как производную от синуса.

Компоненты вектора на единичной окружности дают всегда согласованные sin/cos, как они могут расползтись по фазе между собой? Удержание на единичной окружности обеспечивает нормирование. Итого дрейф может быть только по общей фазе/частоте, ну и амплитуда может стабилизироваться с небольшим смещением нормы от единицы.

Цитата
То-же самое относится когда генератор должен работать на "бесконечном интервале времени". Тут шумы никуда не уйдут, и генератор просто "зазвенит".

У меня не звенит на бесконечном времени. Да и частоту тоже перестраивать пробовал в реальном времени.
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 16 2014, 11:36
Сообщение #45


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(_pv @ Dec 16 2014, 12:11) *
с целочисленной арифметикой можно точно в желаемую частоту и амплитуду не попасть, но осциллятор будет стабильным сколь угодно долго.


int a0, a1 = 0, a2 = 100, K=450;
for (int i = 0; i < 1000; i++){
a0 = (K*a1)/256 - a2;
a2 = a1;
a1 = a0;
printf("%d\n",a0);
}
через 765*N шагов, значения a0,a1,a2 опять станут -100, 0, 100, почему же он не развалился раз он не устойчивый?


а он и развалился. сразу. результат никак не гармоника.
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 11:55
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(thermit @ Dec 16 2014, 17:36) *
а он и развалился. сразу. результат никак не гармоника.

а что же это тогда?
возьмите калькулятор и разницу меджу {0, 100, 173, 200, 173, 100, 0} и 200*sin(2*PI*i/12) посчитайте.

Цитата(amaora @ Dec 16 2014, 17:33) *
Компоненты вектора на единичной окружности дают всегда согласованные sin/cos, как они могут расползтись по фазе между собой? Удержание на единичной окружности обеспечивает нормирование. Итого дрейф может быть только по общей фазе/частоте, ну и амплитуда может стабилизироваться с небольшим смещением нормы от единицы.

ошибки округления при умножении будут разными для синуса и косинуса, и они будут накапливаться, в том числе и в фазе между синусом и косинусом.
нормировка амплитуды это не вылечит.

это я погорячился синус/косинус конечно будет нормальный, но общая фаза(соответственно частота) поползёт
Go to the top of the page
 
+Quote Post
Fat Robot
сообщение Dec 16 2014, 11:55
Сообщение #47


ʕʘ̅͜ʘ̅ʔ
*****

Группа: Свой
Сообщений: 1 008
Регистрация: 3-05-05
Пользователь №: 4 691



Конечно. Даже в вашем простом примере в диапазоне частот (К=1..511) амплитуда на выходе меняется на 4 разряда или в 16 раз.
Если отсчеты и коэффициенты принять 16 разрядными, то изменение амплитуды в зависимости от частоты будет уже в пределах 8 разрядов. Попытки как-то ограничить разрядность умножителя будут приводить к описываемым эффектам. То, что при полной разрядности арифметических блоков генератор будет стабилен, мы обсудили.

Зависимость амплитуды от частоты я уже даже за недостаток не считаю.

Цитата(_pv @ Dec 16 2014, 10:49) *
давайте поможем друг другу, Вы мне расскажете как правильно printf пользоваться, а я Вам - чем арфиметика с плавающей запятой от целочисленной отличается.
а потом вернёмся к вопросам устойчивости.
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 12:13
Сообщение #48


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(Fat Robot @ Dec 16 2014, 17:55) *
Конечно. Даже в вашем простом примере в диапазоне частот (К=1..511) амплитуда на выходе меняется на 4 разряда или в 16 раз.
Если отсчеты и коэффициенты принять 16 разрядными, то изменение амплитуды в зависимости от частоты будет уже в пределах 8 разрядов. Попытки как-то ограничить разрядность умножителя будут приводить к описываемым эффектам. То, что при полной разрядности арифметических блоков генератор будет стабилен, мы обсудили.

Амплитуда определяется начальными значениями a1 и a2, а не только K который задаёт частоту. и соответственно амплитуду можно сделать какой угодно, так что замечание вообще мимо.
что такое полная разрядность? вот выше пример при 9х9->(18 с округлением до 10) разряном умножении, он как, нестабилен?
давайте до 4х разрядов ограничим
int a0, a1 = 0, a2 = 10, K=12;
...
a0 = (K*a1)/16 - a2;
работать он от этого не перестанет.

зы с printfом то что не так?
Go to the top of the page
 
+Quote Post
Russky
сообщение Dec 16 2014, 12:22
Сообщение #49


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371



Цитата(_pv @ Dec 16 2014, 15:25) *
генератор путём умножениея на матрицу поворота нестабилен, а если реинициализировать его каждые 128 шагов, то синус/косинус всё равно придётся честно вычислять для текущего значения фазы при реинициализации.


Нет. Не придется вычислять каждый раз.
Вы немного не поняли принцып.

У нас есть таблица косинуса на 1024 отсчета. Это значит что я могу начальные значения для каждых 128 отсчетов брать из этой таблицы, а приращение считается только один раз.

Т.е. я считаю приращение по таблице для каждых 128 отсчетов, и матрицу поворота для каждого отсчета.
В итоге все работает вот как:
Когда я запускаю обработку 128 отсчетов, я загружаю начальные значения из таблицы (это константа), загружаю приращения синуса и косинуса (то-же константы расчитанные один раз при задании частоты) и потом считаю 128 раз поворот. После этого я делаю щаг по таблице, и сохраняю состояние указателя таблицы. В следующий раз повторяется все то-же самое.
В итоге, для таблицы в 1024 отсчета, и пакета 128 отсчетов, я могу генерировать синус с частотой кратной 128*1024 ( = 131072). Если нужно, то я могу переинициализировать не каждые 128 отсчетов, а каждые 1024, и получим мы кратность частоты 1024*1024, что в общем афигенно! sm.gif
Соотношением сигнал/шум мы конечно жертвуем в некоторой степени, но "за все надо платить". sm.gif
Go to the top of the page
 
+Quote Post
thermit
сообщение Dec 16 2014, 13:05
Сообщение #50


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата(_pv @ Dec 16 2014, 15:55) *
а что же это тогда?
возьмите калькулятор и разницу меджу {0, 100, 173, 200, 173, 100, 0} и 200*sin(2*PI*i/12) посчитайте.


Да. у вас крутой генератор.
Снимаю чепчик...
Go to the top of the page
 
+Quote Post
_pv
сообщение Dec 16 2014, 13:20
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(thermit @ Dec 16 2014, 19:05) *
Да. у вас крутой генератор.
Снимаю чепчик...

и как же тогда должно быть при 8ми разрядных коэффициентах и частоте в 0.1 от тактовой, взятых просто для примера?
или кто-то мешает разрядность увеличить так, чтобы ошибка квантования стала меньше допустимой?
Go to the top of the page
 
+Quote Post
andyp
сообщение Dec 16 2014, 16:12
Сообщение #52


Местный
***

Группа: Участник
Сообщений: 453
Регистрация: 23-07-08
Пользователь №: 39 163



Цитата(Russky @ Dec 16 2014, 15:22) *
Нет. Не придется вычислять каждый раз.
Вы немного не поняли принцып.


Откройте для себя наконец как работает табличный DDS с интерполяцией. Заодно сможете любую частоту генерить из одной таблицы разумного размера. Вычислений там - пара умножений и сложений на отсчет.
Go to the top of the page
 
+Quote Post
mihalevski
сообщение Jan 6 2015, 14:18
Сообщение #53


Частый гость
**

Группа: Участник
Сообщений: 100
Регистрация: 20-05-10
Из: Omsk
Пользователь №: 57 391



Цитата(Russky @ Dec 10 2014, 22:43) *
Всем привет!
Вот есть задача - генерировать квадратурный сигнал для DDC. DDC сам реализован внутри DSP, поэтому надо алгоритм чтобы его можно было-бы реализвать потом на аасемблере.
Используется плавующая точка.
В идеальном случае ф-я должна выглядеть так:
result = GenSinCos(float freq); где result это структура содержащая Cos и Sin, т.е. сигналы сдвинуты на 90 градусов.
freq - 0...1.
Ф-я вызывается для каждого отсчета. Начальная фаза в общем не очень важна. Главное чтобы 90 градусов было. По идее это даже не ф-я а макрос.
Как-то так.
Может кто уже встречал подобное? Или может уже есть готовые решения?

Особенность в том, что наверняка есть решение которое не вызывает ф-ю sin и cos каждый раз. sm.gif

Спасибо!

PS. Табличный метод не предлагать! sm.gif



Функция из работающей программы писал для DSP правда на Сях далее сами разберетесь и переведете на asm:



//Генератор гармонического колебания с рекуррентным вычислением
//Возвращает значение функции cos + i * sin при каждом вызове функции
//Fs - частота генерируемого колебания, Гц
//Fd - частота дискретизации, Гц
//phase - начальная фаза в градусах
//order - изменение этого параметра используется для сброса накапливающихся
//ошибок и устанавливает процесс генерации в исходное состояние с заданной фазой
//Параметр order не должен быть равным нулю
//Значения Fs и Fd активируются только одновременно с изменением параметра order
//Параметр order может меняться в любой момент
complex_long_double generator_sin_cos(long double Fs, long double Fd, long double phase, int order)
{
static long double a, b, sin, cos;
static int i = 0;
long double c_1, s_1, pi2, radian;
complex_long_double rez;

if(i != order)//инициализация
{
pi2 = 6.28318530717; radian = 57.29577951308;
a = cosd( pi2 * Fs / Fd ); b = sind( pi2 * Fs / Fd );
sin = sind( phase / radian ); cos = cosd( phase / radian ); i = order;
}


c_1 = cos; s_1 = sin;

cos = a * c_1 - b * s_1;// cos и sin есть отсчеты взаимно ортогональных колебаний
sin = a * s_1 + b * c_1;
rez.re = cos; rez.im = sin;

return rez;
}// end generator_sin_cos()



Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st June 2025 - 06:49
Рейтинг@Mail.ru


Страница сгенерированна за 0.02082 секунд с 7
ELECTRONIX ©2004-2016