Страница 1 из 1

Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 14:23:25
Symbiosis
Уже намучился с различными схемами на ОУ, лампы стабилизации и прочее. Много обвеса, очень нестабильная работа при перестройке частоты, необходимочть сдвоенных резисторов и прочее прочее...

Заинтересовался DDS, но в интернете не удалось найти простого устройства, только полноценные функциональные генераторы.

А надо всего-то переменный резистор-АЦП-МК-ШИМ-ФИЛЬТР. деталей минимум, стабильность на высоте.

Надо генерировать синус с частотой от 500 до 5000 Гц где-то. Контролировать частоту нет необходимости. (на мосте Вина не получилось достичь этого - амплитуда плавает сильно, форма сигнала пляшет)

Собственно два варианта у меня в голове крутятся :
1. ШИМ
2. R-2R ЦАП

первый проще - меньше деталей =)

И вот , сделал я таблицу синуса, а дальше работа остановилась.

вопрос - как управлять частотой ? Просто паузы одинаковые между переходами на следующую строку таблицы устанавливать ? Ну а задержку управлять от АЦП-переменного резистора.

Подскажите с реализацией. Думаю опрос АЦП по прерыванию вести, но как избежать "рваного" сигнала ?
Помогите алгоритм составить.
Вот нашел почти то что надо, но частота задается через UART: http://www.myplace.nu/avr/minidds/index.htm

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 16:19:23
yaotzin
а как оно вообще работать должно? :))) тебе нужен шим с регулируемой частотой и скважностью? а как же оно в синусоиду превращается ? если расскажиш может помогу :))) через фильтр ? регулируя скважность - напряжение то больше то меньше или что? что за фильтр такой

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 16:25:26
bolek
Полноценный DDS генератор с кнопками и т.п. http://www.scienceprog.com/avr-dds-sign ... rator-v20/
Лично мне больше по душе более простой http://www.scienceprog.com/avr-dds-sign ... rator-v10/
А если лишнее выкинуть (ЖКИ) и оставить только управление от компьютера, то и на Tiny2313 можно сделать: http://www.myplace.nu/avr/minidds/

Я так и сделал (вариант 3) для генерации меандра, выкинув из прошивки синус и пилу. И, заодно, написал свою управляющую программу (см. на картинке). Все работает замечательно.
Единственное замечание: при приеме команды генерация прерывается, понятно почему :)

P.S. Идея с переменным резистором и АЦП не очень хорошая, если очень хочется крутилку, лучше из старой мыши сделать энкодер.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 16:39:30
Symbiosis
yaotzin писал(а):а как оно вообще работать должно? :))) тебе нужен шим с регулируемой частотой и скважностью? а как же оно в синусоиду превращается ? если расскажиш может помогу :))) через фильтр ? регулируя скважность - напряжение то больше то меньше или что? что за фильтр такой


Низкачастотный , например RC фильтр. Чот я уже сомневаюсь что поможешь ;)

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 16:45:18
Symbiosis
bolek писал(а):...


Дык, в том то и дело, что они полноценные =) А мне нужно неполноценный =) Один МК, который при включении генерит синус и все, больше ничего не делает =) Управляется резистором. Ну или две кнопочки - "больше" и "меньше".

Пчму резистор нехорошая идея ?

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

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 17:15:46
yaotzin
Symbiosis писал(а):Низкачастотный , например RC фильтр. Чот я уже сомневаюсь что поможешь ;)

ну вот мне интересно какой сигнал должен выходить с шим чтоб была синусоида? без ее регулирования для начала!

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 17:19:50
bolek
Пчму резистор нехорошая идея ?

Потому, что
- частота будет постоянно немного плавать,
- МК с АЦП дороже МК без него.

...мне ни в коем случае нельзя, чтобы генерация срывалась...

В таком случае проще всего, imho, будет с кнопками.
В цикл генерации добавить:
- счетчик времени паузы между опросами кнопок
- по истечении паузы - опрос кнопок и изменение adder value (если смотреть в asm miniDDS)
Надо только тщательно выравнять времена прохода разных ветвей (ветвлений по условиям) в добавленном коде.
Примерно так (цикл взят из asm miniDDS):

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

LOOP1:
        add        r28,r24            ; 1
        adc        r29,r25            ; 1
        adc        r30,r26            ; 1
        lpm        ;r1,Z+            ; 3
        out        PORTB,r0        ; 1
;
; сюда добавить счетчик времени паузы
; if (если время паузы истекло)
;    опрос кнопок
;    if (если кнопка нажата)
;       изменение r24, r25, r26
;    else
;       выравнивающий код
; else
;    выравнивающий код

        rjmp    LOOP1            ; 2 => 9 cycles


Только надо не сильно раздуть доп. код, иначе 5 кГц не получить приличной формы

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 17:26:10
Symbiosis
ууу, аж голова кругом пошла =) Я ток на Си работаю =) Но смысл понял. Есть сэмплы на Си ?


yaotzin: почитай что такое ШИМ, гугль выдаст ошеломляющее количество ссылок, а там все понятно будет =)
ну или даже вот тебе ссылки =)

http://www.gaw.ru/html.cgi/txt/app/micr ... AVR131.htm
http://easyelectronics.ru/avr-uchebnyj- ... -shim.html

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 17:59:38
bolek
Да там asm-а то пара-тройка команд, можно и разобраться.
Я и сам в asm не силен, однако ж подправил программку под свои нужды :)
А на C вряд ли получится точно выравнять времена проходов.
Впрочем, попробуй, идея простая, может именно у тебя получится?

Есть, правда, другой вариант - чисто аппаратный, цифро-аналоговый:
генератор -> счетчик -> ПЗУ с отсчетами SIN -> КМОП буфер -> ЦАП
Частоту генератора можно крутить резистором, ЦАП сделать на резисторах, ПЗУ - поискать в старом хламе, КМОП буфер - 2 штуки 561ЛН2 или любой КМОП 8 битный регистр/драйвер.
Если на период SIN положить 256 отсчетов, то достаточно ПЗУ 256*8, хотя скорее можно найти 2К*8.
И по частоте генератор получается реализуемым: 5000*256=1 280 000 -> 1,28 Мгц, можно взять генератор из 74HC4046.
Лет 25 назад я так бы и сделал :)
Правда, фильтровать SIN будет сложнее, особенно на 500 Гц.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Пт ноя 12, 2010 18:36:25
yaotzin
Symbiosis писал(а):ууу, аж голова кругом пошла =) Я ток на Си работаю =) Но смысл понял. Есть сэмплы на Си ?


yaotzin: почитай что такое ШИМ, гугль выдаст ошеломляющее количество ссылок, а там все понятно будет =)
ну или даже вот тебе ссылки =)

http://www.gaw.ru/html.cgi/txt/app/micr ... AVR131.htm
http://easyelectronics.ru/avr-uchebnyj- ... -shim.html

как бы шим я знаю что такое! разве я про шим спрашивал ? тю не хочешь не надо.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Сб ноя 13, 2010 01:48:46
Symbiosis
Ну коли знаешь, чего спрашиваешь ? =) Скважность сигнала постоянно изменяется , а после интегрирования получаем постоянное напряжение, изменяющееся по тому же закону. Ну или точнее, уже не постоянное напряжение , а переменное =) Посмотри по ссылкам что я дал картинки, наглядно.

bolek: А оптимально сколько отсчетов на период взять, то есть сколько берут обычно ?

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Сб ноя 13, 2010 14:19:30
s64
здесь на форуме присутствует Леонид Иванович автор генератора http://telesys-ru.1gb.ru/electronics/pr ... hp?do=p035 можете с ним пообщаться.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Сб ноя 13, 2010 16:10:03
bolek
Symbiosis писал(а):... оптимально сколько отсчетов на период взять, то есть сколько берут обычно ?
Для 8 разрядного ЦАП без знака примем амплитуду равной 128.
Тогда минимальное число отсчетов на квадрант, обеспечивающее приращение амплитуды на 1 в районе максимума будет равно 13, т.е на весь период SIN нужно 13*4=52 отсчета.
Можно выбрать большее количество отсчетов, тогда фильтровать будет несколько проще.
Критериев выбора можно придумать множество. :)

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Сб ноя 13, 2010 18:01:14
Symbiosis
Вот я точно определился, как это будет выглядеть и как работать. Решил использовать кнопки, т.к. в магазине нет импортных резисторов красивых, только убогие СП3. В прикрепленном файле блок схема и описание.

Сейчас начал рисовать алгоритм и сразу же обнаружил грабли. Которые пока незнаю как обойти. Индикацию сделаю по прерыванию от таймера. А кнопки решил опрашивать прямо в основном цикле.

Тоесть:

Опрос кнопок. Сперва одну кнопку опрашиваю, если нажата, то жду 50мс и еще раз опрашиваю, если по прежнему нажата, то увеличиваю соответствующую переменную, или уменьшаю (антидребезг). Так каждая кнопка по очереди опрашивается.

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

Если нажатие кнопки спровоцирует прерывание, что произойдет с генерацией ? В этот момент ШИМ на некоторое время зависнет на одном из значений ? Т.е. чуть более чем на 50 мс ШИМ будет выводить одно и тоже значение таблицы.

В общем, помогите, как организовать опрос кнопок, чтобы не калечить генерацию.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Сб ноя 13, 2010 18:44:46
yaotzin
сделать опрос постоянным, т.е. пауза будит постоянная, коэффициент заполнения при этом будит постоянно чего то не доставать. тогда и ничего рваться не будит. верней будет все время рваться но об этом никто не узнает :)))

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Вс ноя 14, 2010 04:29:00
Symbiosis
Узнать не узнает, но почувствовать - почувствует =))) Как мне объяснили, этот прибор будет использоваться в медецинских целях. Ребята медфизики чего-то мудрят ... =)

Короч видимо надо с резисторами делать и опрашивать АЦП по таймеру. В таком случае все нормально будет. Опрос АЦП 14 тактов ведь.

необходимость диспля в таком случае отпадает.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Вс ноя 14, 2010 06:44:26
bolek
Мы писали,
Вы читали,
И мозги у Вас устали :))

Все, что нужно для нормальной реализации, уже посоветовали.
Дальше - дело хозяйское.

Добавлено: Вс ноя 14, 2010 10:02:43
ARV
1. для ваших целей лучше отказаться от динамической индикации и использовать статическую - на ЖКИ, например.
2. опрос кнопок проводить одновременно всех, а не по одной поочередно. для этого надо лишь подключить все кнопки к одномк порту МК.
3. генерацию ШИМ-модулированного сигнала делать по прерыванию, тогда это будет единственное прерывание в вашей программе и его периодичность ничем не будет нарушаться - вы достигнете своей задуманной "стабильности".
4. для простоты рекомендую число "дискрет" синуса брать 256, в крайнем случае кратно степени двойки, тогда накладные расходы на формирование очередной скважности ШИМ будут меньше. проводить "оптимизацию", используя симметрию синуса как по полупериодам, так и по четвертьпериодам, совершенно не стоит.
5. большинство ваших "проблем" - надуманные, в действительности все достаточно просто для вашего диапазона частот.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Вт фев 15, 2011 09:56:20
George22
I. Синус - по таблице.
Перестройка по частоте - смена частоты дискретизации.
Выход - ЦАП R-2R.

II.Шим.

III.Генератор на цифровом фильтре.

Re: Простой генератор синуса на микроконтроллере AVR

Добавлено: Ср янв 11, 2012 17:22:52
George22
Генератор на цифровом фильтре 1000Гц:

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

//--------"ГЕНЕРАТОР НА ЦИФРОВОМ ФИЛЬТРЕ"----------
#include <mega8.h>
#include <math.h>

#pragma uchar+

void main(void);
void Init(void);
interrupt [TIM1_OVF] void Timer1_ovf(void);

#pragma opt-
 float x1=0,x2=0,y=0;
 const float dwTone =1000.0;     //частота основного тона,Гц
 const float dwFrequency =16000.0; //частота дискретизации
 const float A =112.0;//амплитуда
 float k;

 
//----------
 void main(void) 
 {
 Init();

 #asm("sei")//разрешить прерывания

 for(;;)
  {
  #asm("sleep")
  }
 }
//----------





//----------
void Init(void)
 {
 k = 2*cos(2*PI*dwTone/dwFrequency);
 x1 =0;  //начальные значения
 x2 = -A*sin(2*PI*dwTone/dwFrequency);

 DDRC=0x00;
 PORTC=0xFF;

 DDRB=0x00;
 PORTB=0xFF;

 DDRD=0xff;
 PORTD=0x00;

 //Timer(s)/Counter(s) Interrupt(s) initialization
 TIMSK=0x04;//разрешить прерывания от таймеров

 TCNT1H=0xFC;
 TCNT1L=0x37;
 TCCR1B=1;

 //разрешить режим засыпания
 MCUCR =1<<SE;

 // Watchdog Timer initialization
 #pragma optsize-
 WDTCR=(1<<WDCE);
 WDTCR=(1<<WDCE)|(1<<WDE)|(1<<WDP2)|(1<<WDP1);
 }
//----------





//----------
 interrupt [TIM1_OVF] void Timer1_ovf(void)
 {
 TCCR1B=0;//останов таймера 1

 //задержка для точной коррекции частоты
 // #asm ("nop")   
     
 TCNT1H=0xFC;
 TCNT1L=0x37;
 TCCR1B=1;//старт таймера 1     
 #asm("wdr")                         
 y = k*x1-x2;             
 x2 = x1;                 
 //x1 = y;
 if(y>127.0)
 x1=127.0;
 else
 x1=y;
 if(y<(-127.0))
 x1=-127.0;
 else
 x1=y;
 
 PORTD=y+127;                   
 }
//----------

работает без сбоев годами. На выходе ЦАП, у меня просто матрица R-2R.