Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: загвоздка в написании DDS
Форум разработчиков электроники ELECTRONIX.ru > Цифровая обработка сигналов - ЦОС (DSP) > Алгоритмы ЦОС (DSP)
Frox_SzC
И так, начнем по порядку:

На работе зашел разговор о DDS'никах АналогДивайса, ну и я как обычно плюнул и сказал: "а че тут делать то, было бы желание"..... Как говориться мужик сказал мужик сделал.....Все бы нечего.... Весь алгоритм работы ДДС прозрачен и абсолютно понятен.......
Но вот загвостка:
Перечитав КУЧУ информации по ДДС никак не нашел: что же из себя представляет "код частоты", поступающий на вход......Понял что возможно два варианта развития событий:
1) "код частоты" - есть готовый инкремент фазового аккумулятора....тогда все просто....но возникает другой вопрос: кто его должен подавать на вход???где его считать???
2) "код частоты" - есть численное выражение требуемой частоты в двоичном исчеслении......тогда расчет инкремента фазового аккумулятора необходимо сделать в модуле ДДС.....Отлично!!!
Выбрав второй путь....я написал ДДС....в котором инкремент считается по формуле: dph=((2^n)*Request_freq)/Fclk; где 2^n есть число точек фазы на весь период......
немного подумав....объединяю 2^n/Fclk в одну константу и получаю (при n=32 и Fclk=100МГц) 42,949....
И здесь начался .....хм хм.......плохо короче....
Число которое получается в итоге.....дробное.....Вопрос....Критично ли повлияет его округление навыходной сигнал???.....Если да то придется реализововать умножение на дробное число, что приведет к увеличение площади кристалла и потребления....Как быть??? Спасибо!!!
rezident
Что-то не совсем осознал суть проблемы. Не хочется можете считать во float считайте в целочисленных значениях. Но простое округление даст погрешность около 0,12% В зависимости от максимальной Request_freq сначала домножаете приращение фазы на степень двойки так, чтобы не вылезти за выбранную разрядную сетку (которая видимо должна быть больше исходных 32 бит). Потом производите суммирование фазового сдвига в той же выбранной разрядной сетке и результат сдвигаете вправо на то же число разрядов, что было при домножении. Получаете снова 32-х разрядное число. Увеличение разрядности даже на 8 разрядов уже даст на два порядка более точное целочисленное вычисление фазы.
Расчеты.
2^32*100МГц=42,94967296 при целочисленном округлении до 43 даст погрешность (43.0-42,94967296)/42,94967296*100%=0,117%
2^32*100МГц*2^8=10995,11627776 при целочисленном округлении до 10995 даст погрешность
((float)(10995>>8)-42,94967296)/42,94967296*100%=-0,001%
Вроде так.
Frox_SzC
Цитата(rezident @ Oct 29 2009, 00:23) *
Что-то не совсем осознал суть проблемы. Не хочется можете считать во float считайте в целочисленных значениях. Но простое округление даст погрешность около 0,12% В зависимости от максимальной Request_freq сначала домножаете приращение фазы на степень двойки так, чтобы не вылезти за выбранную разрядную сетку (которая видимо должна быть больше исходных 32 бит). Потом производите суммирование фазового сдвига в той же выбранной разрядной сетке и результат сдвигаете вправо на то же число разрядов, что было при домножении. Получаете снова 32-х разрядное число. Увеличение разрядности даже на 8 разрядов уже даст на два порядка более точное целочисленное вычисление фазы.
Расчеты.
2^32*100МГц=42,94967296 при целочисленном округлении до 43 даст погрешность (43.0-42,94967296)/42,94967296*100%=0,117%
2^32*100МГц*2^8=10995,11627776 при целочисленном округлении до 10995 даст погрешность
((float)(10995>>8)-42,94967296)/42,94967296*100%=-0,001%
Вроде так.


В принципе вариант на счет float вполне возможен, но не желателен, так как для этого необходимо писать (либо доставать) модуль который занимается этим делом.......но его наличие ведет к увеличению потребления и площади кристалла......а это критично.......
Второй вариант который Вы предложили мне более по душе.........но не могли ли Вы пояснить как будет меняться множитель (2^n) в зависимости от требуемой частоты???

И все же не получается так......наверно я что то не до понял.........10995>>8 все равно даст дробное число......verilog округлить его либо до 43,а скорее всего до 42....тупо отбросив дробную часть......
_Anatoliy
Цитата(Frox_SzC @ Oct 29 2009, 07:10) *
....verilog округлить его либо до 43,а скорее всего до 42....тупо отбросив дробную часть......


Тут округление лучше делать не floor а round,в 2 раза уменьшится максимальная погрешность.
Fat Robot
Так обычно делают. Кто подавать и где считать: внешнее по отношению к DDS устройство.

Цитата(Frox_SzC @ Oct 28 2009, 22:29) *
1) "код частоты" - есть готовый инкремент фазового аккумулятора....тогда все просто....но возникает другой вопрос: кто его должен подавать на вход???где его считать???
Сергей Борщ
Цитата(Frox_SzC @ Oct 29 2009, 08:10) *
наверно я что то не до понял.........10995>>8 все равно даст дробное число......verilog округлить его либо до 43,а скорее всего до 42....тупо отбросив дробную часть......
Фазовый аккумулятор использует все биты, ваши 32 и эти 8, итого 40. Эти 8 учитываются при сдвиге перед выборкой из таблицы.
Frox_SzC
Цитата(Сергей Борщ @ Oct 29 2009, 17:01) *
Фазовый аккумулятор использует все биты, ваши 32 и эти 8, итого 40. Эти 8 учитываются при сдвиге перед выборкой из таблицы.


Я вообще оставляю перед выборкой из таблицы 12 бит.....старший бит управляет полярность (то бишь знаковый бит), его я смогу послать на ЦАП..... а следующий за ним управляет адресом чтения из таблици ( тоесть если он равен 0 значит addr=phase если он равен 1 значит addr=~phase, делается для того чтобы минимизировать память......храня только одну четверть периода)........так скажите мне каким боком еще 8 бит.........от этих 8 бит ничего не поменяется....

есть еще один выход......подавать на ДДС тактовую частоту например 2^27....тогда все получается ровно.....но по моему это дурацкий выход.....только если на входе ДДС стоит PLL......Как такая идея???
rezident
Цитата(Frox_SzC @ Oct 29 2009, 10:10) *
но не могли ли Вы пояснить как будет меняться множитель (2^n) в зависимости от требуемой частоты???
Вы сначала сами поясните, что такое эти ваши (2^n)? smile.gif У вас написано
Цитата("Frox_SzC")
где 2^n есть число точек фазы на весь период......
n это разрядность ЦАП выходит? Или разрядность таймера, формирующего ШИМ?
Цитата(Frox_SzC @ Oct 29 2009, 10:10) *
И все же не получается так......наверно я что то не до понял.........10995>>8 все равно даст дробное число......verilog округлить его либо до 43,а скорее всего до 42....тупо отбросив дробную часть......
Я же написал (и Сергей Брощ уточнил), что суммирование фазы нужно производить в другой (более высокой) разрядной сетке. Если используете доп. 8 бит, то аккумулятор фазы 40 битный должен быть. Вам на конкретных числах пояснить?
Frox_SzC
Цитата(rezident @ Oct 29 2009, 19:18) *
Вы сначала сами поясните, что такое эти ваши (2^n)? smile.gif У вас написано
n это разрядность ЦАП выходит? Или разрядность таймера, формирующего ШИМ?
Я же написал (и Сергей Брощ уточнил), что суммирование фазы нужно производить в другой (более высокой) разрядной сетке. Если используете доп. 8 бит, то аккумулятор фазы 40 битный должен быть. Вам на конкретных числах пояснить?


Ребят, 2^n есть число точек фазы (то бишь амплитуды) по кругу периода......нарисуйте круг и разделите его на 2^n частей....одна часть этого круга будет минимальным приращением.....правильно???
Аккумулятор не может быть больше чем 32 бита.........это гемморой если он будет больше.....
Frox_SzC
Возьмите хоть 42разрядный аккумулятор.....разницы от этого нет....
Если это возможно объясните мне в цифрах....
Frox_SzC
Возьмите хоть 42разрядный аккумулятор.....разницы от этого нет....
Если это возможно объясните мне в цифрах....
rsv
есть же готовая корка от ксайлинкса, там в описании про это рассказывается. если использовать простое усечение фазы, то появляются нехорошие гармоники. бороться с ними можно либо добавлением случайной величины к фазе, либо слаживанием рядом тейлора
а ддска от аналог девайса вещь довольно странная, хоть мы ее победили, но она нам не понравилась
rezident
Цитата(Frox_SzC @ Oct 29 2009, 21:54) *
Ребят, 2^n есть число точек фазы (то бишь амплитуды) по кругу периода......нарисуйте круг и разделите его на 2^n частей....одна часть этого круга будет минимальным приращением.....правильно???
Дык все-таки фазы или амплитуды? cranky.gif Фаза с частотой и временем связана, а амплитуда с напряжением. Потом конечно напряжение можно в какую-то другую величину преобразовать, то изначально именно с напряжением. Фаза и частота ограничены разрядностью какого-либо таймера, который период выборок отсчитывает. Амплитуда ограничена величиной опоры и разрядностью ЦАП (или разрядностью ШИМ, если сигнал с помощью ШИМ формируется). Вы уж разберитесь как-то сами, что это у вас за (2^n), каковы разрядность таймера выборок и разрядность ЦАП?
Frox_SzC
Ну я думаю никто не будет спорить что фаза является адресом в таблицу амплитуд.......значит есть зависимость амплитуды от фазы.....на рисунке снизу показано..... 2^n есть разрядность аккумулятора.....отбрасываем 20 разрядов.......еще 2 разряда управляющих......получается что разрядность амплитуды 2^10......
rezident
Frox_SzC, так вы синус формируете или сигнал произвольной формы? Мне уже неудобно, но видимо ссылку на википедию придется дать. laughing.gif
rezident
Попробую еще раз "на пальцах" и в цифрах. Допустим
имеем:
частота тактирования - 1Мгц,
таблица синуса - 36 отсчетов на период,
дискретность изменения амплитуды 1/256 (ЦАП - 8 разрядов).
хотим:
получить выходную частоту 23кГц.
Таблица у нас с приращением фазы 10 градусов для частоты сэмплирования 1МГц/36=27777,7(7)Гц
а) считаем требуемое приращение фазы 23кГц/(1МГц/36)=0,828, если просто округлим до целых получим 0, если правильно округлим, то получим 1. Облом-с. Тогда отсчеты у нас будут строго по таблице и выходная частота получится, не 23кГц, а 27,777кГц. Ошибка выходной частоты при этом будет (1МГц/36-23кГц)/23кГц*100%=+20,77%. Чтобы уменьшить погрешность вычисления фазы отсчетов увеличим разрядность фазового аккумулятора. Для этого при расчете фазового приращения домножим его значение на 256 и получим 256*23кГц/(1МГц/36)=211,968. После округления будем иметь фазовое приращение dph=212. Поскольку у нас всего 36 элементов в таблице, то для аккумулятора фазы хватит 6-и разрядов. Но мы еще должны учесть 8-и битное расширение приращения фазы. Поэтому для аккумулятора фазы возьмем (6+8)>=16 разрядов. Берем пример исходного когда из википедии и немного дорабатываем его.
Код
#include <stdint.h>

#define SINTBLSIZE 36U    //размер таблицы синуса
#define TBLIDXPRD (256U*36U)    //период фазового аккумулятора

uint8_t sinTbl[SINTBLSIZE]=
{ 128, 150, 171, 191, 209, 225, 238, 247, 253, 255,
  253, 247, 238, 225, 209, 191, 171, 150, 128, 105,
  84, 64, 46, 30, 17, 8, 2, 0, 2, 8,
  17, 30, 46, 64, 84, 105
]; // таблица синуса

uint8_t next_amp(uint16_t dph)
{   static uint16_t phase=0;
    uint8_t amp;
    unsigned int idx;
    phase+=dph;
    while(phase>TBLIDXPRD)
        phase-=TBLIDXPRD;
    idx=phase>>8;
    amp=sinTbl[idx];
    return amp;
}

Результатом работы при dph=212 будет такая последовательность
Код
128    128    150    171    191    209    209    225    238    247
253    255    255    253    247    238    225    209    209    191
171    150    128    105    105    84    64    46    30    17
17    8     2     0     2     2     8     17    30    46
64    64    84    105
                  127    150    171    171    191    209
225    238    247    247    253    255    253    247    238    238

Отступом я выделил период, который равен 44 отсчетам. Считаем период получившейся частоты. 1МГц/44=22727,27(27)Гц. Ошибка формирования выходной частоты составляет (1МГц/44-23кГц)/23кГц*100%=--1,19%. Сравните с исходной погрешностью +20,77% Улучшение точности выше, чем на порядок!
Такой пример вам будет понятен? laughing.gif Еще в дополнение замечу, что поскольку в моем примере разрядность фазового аккумулятора была 16, а требуемая разрядность индекса таблицы отсчетов составляла всего 6 разрядов, то легко можно было домножать не на 2^8=256, а на 2^10=1024. Точность вычисления фазы была бы еще выше. Правда для выбранных условий это не очень актуально, т.к. выходная частота и табличная частота сэмплирования слишком близкие.
Frox_SzC
Полностью с Вами согласен.... Увеличение фазового аккумулятора приводит к уменьшению ошибки....это было известно заранее............ Наверно мы малость недопоняли друг друга....точнее я Вас.....
Спасибо за подробное объяснение....оно исчерпывающие.....теперь я Вас понял..... У моего фазового аккумулятора разрядности хватает....все в нормеsmile.gif Просто я переживал за ошибку которая будет при округлении.... и мне хотелось узнать внесет ли она какие либо существенные (принципиальные) изменения в сигнал......
В единственном я до сих пор не разобрался..... Как все таки делать ДДС..... Будем ли мы подавать на вход уже приращение или же будем считать его внутри ДДС.....я склоняюсь к первому варианту......хотя реализовал второйsmile.gif Как Вам?
ANV
Цитата(Frox_SzC @ Oct 30 2009, 08:04) *
В единственном я до сих пор не разобрался..... Как все таки делать ДДС..... Будем ли мы подавать на вход уже приращение или же будем считать его внутри ДДС.....я склоняюсь к первому варианту......хотя реализовал второйsmile.gif Как Вам?


Ещё раз, на пальцах (упрощённо).
У Вас есть два регистра, счётчик фазы и приращение фазы. Разрядность счётчика фазы определяет точность частоты, а разрядность регистра приращения влияет на максимальную генерируемую частоту.
С каждым тактом генератора Вам необходимо сделать следующее:
- прибавить к счётчику фазы приращение фазы;
- N старших разрядов счётчика фазы, адресуют таблицу формы сигнала, тут необходимо восстановить форму колебания
- послать получившееся амплитудное значение на ЦАП

--
обычно в DDS-ску записывают приращение фазы, а его считают внешним микроконтроллером.
Frox_SzC
Спасибо за Вашу помощь товарищи!!!
Михаил_K
Когда-то вот здесь http://electronix.ru/forum/index.php?showt...mp;#entry372344 выкладывал готовую DDS.
Слово частоты N рассчитывается как N = (f_требуемое*2^32)/f_clk
Frox_SzC
Цитата(Михаил_K @ Nov 9 2009, 08:19) *
Когда-то вот здесь http://electronix.ru/forum/index.php?showt...mp;#entry372344 выкладывал готовую DDS.
Слово частоты N рассчитывается как N = (f_требуемое*2^32)/f_clk


а округляли round???
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.