Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

sin_logoВ одном из ранних уроков мы узнали, что при помощи ШИМ можно изменять скважность сигнала. Тем самым регулировали яркость свечения светодиода. Однако есть более интересный способ, использования широтно-импульсной модуляции.

Итак… Если пропустить генерируемый сигнал через фильтр низких частот, то получится постоянное напряжение.
pwm sin6

Так как скважность изменяется от 0 до 0xFF(255), значит у нас будет 255 уровней постоянного напряжения. Проще говоря, есть диапазон напряжения, допустим от 0 до 5В, этот диапазон разбивается на 255 значений. С шагом 5/255=0,0196В можно выставить любое напряжение.

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

Теперь перейдем к конкретной цели: получить синусоиду с частотой 50Гц с помощью микроконтроллера Atmega8. Глобальная задача — выставлять через определенные промежутки времени напряжение на выходе ШИМ, по синусоидальному закону.

Разберемся с первой частью задачи. Для того, получить определенные промежутки времени воспользуемся таймером. Допустим таймер настроен на частоту 8МГц, т.е. он будет тикать 8000000 раз в секунду. Синусоида колеблется 50 раз в секунду, значит на один период может приходиться 8000000/50=160000 тиков максимум. Раз у нас 256 уровней напряжения, то и максимальное разрешение синусоиды будет равняться 256.

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

Для синуса с разрешением 4:

pwm sin1

Для синуса с разрешением 8 точек:

pwm sin3

 

Для синуса с разрешением 16 точек:

pwm sin2

Думаю «эволюция» синуса наглядно видна — чем больше точек(разрешение), тем меньше угловатостей и тем больше он похож на нормальную синусоиду.  В итоге я решил остановиться на разрешении синуса в 128 точек.

Теперь объединяем все сказанное ранее, 160000 тиков делим на разрешение 128 получаем 1250 — через столько тиков должно сработать прерывание, чтобы выставить следующий уровень напряжения. Значение 1250 нужно пихать в регистр сравнения OCR1A

OCR1AH=0x04;
OCR1AL=0xE2;

Вторая часть глобальной задачи — как построить синусоиду. Вспомним математику :D… Синус изменяется от -1 до 1. ШИМом сгенерить отрицательное напряжение не получится. Поэтому нужно сместить график над осью Х — sin(x)+1. Теперь он будет изменяться от 0 до 2, тоже не вариант, т.к. у нас 256 значений напряжения, поэтому умножим на 127, чтобы максимальным было значение 256. В итоге откопал такую формулу:

excel_pwm

128 — разрешение синуса, х — номер точки по (от 0 до 128). Сосчитал в Excel, получился массив sin[] из 128 значений, которые по очереди подставляются в OCR2.

Последнее о чем стоит упомянуть — фильтр низких частот, возможно в ближайшее время появится урок по фильтрам. В данный момент, формулы для его расчета не имеет смысла приводить, т.к. есть сайты с возможностью онлайн расчетов, достаточно набрать «фнч» в гугле.

Файл прошивки и протеуса

95 комментариев: Урок 11. Получение синусоидального сигнала при помощи ШИМ

  • Добрый день уважаемые гуру микроконтроллеров. Пишет вам ну не совсем чайник, а так начинающий самовар вашего благороднейшого дела. У меня такой вопрос. Вот захотел я сделать на шиме инвертор так сказать на 220В. Но вот по схеме полевики в выходном каскаде сгарали сразу же. вроде как на постоянно замкнутую схему похоже. Действительно на затворе все время напряжение. Вот и уткнулся в МК контроллер так сказать изучить на предмет того, что он не правильно управляет. Но для начала решил повторить схему этого урока и посмотреть так сказать синус в натуре. (Осциллограф С1-65А). Ну вобщем первый вопрос.
    1. Почему схема разработана как будто на 17 ноге должен быть плюс?
    Если 17 нога программируется на выход то она должна действовать как сухой контакт на землю, а плюс должен на неё приходить через нагрузку. (Ссылка А.В. Белов Создаем устройства на микроконтроллерах.)
    2.Ну вобщем я удивился, но не стал делать отсебятину и воссоздал так сказать этот урок в натуре. Прошил МК собрал схемку подключил осциллограф и …………. болты. На 17 ноге все время присутствует порядка 4.7В постоянки (естественно относительно плюса, там же по Белову минус.). А на конденсаторе все что смог поймать это какая то синусоида по амплитуде примерно 0,3В А частота вобще по показаниям порядка 8МГц. (Кристал выставил на внутренний генератор на 8МГц). Замер был естественно отнасительно плюса схемы. Что за чудеса помогите пожалуйста, просто мистика.

  • В протеусе естественно все работает

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

  • Но минусовой потенциал там есть и это факт.

  • 😀 если вы возьмете тестер и померите батарейку то получите +1,5В, если после этого поменять полярность щупов то естественно увидите -1,5в. В этом нет ничего удивительного

  • На счёт смещения по оси У, (а не Х), то вы правы. ножка МК не может выдать отрицательный потенциал. Но я это справил путём использования двух пинов МК. Сначал на одном выводится напряжение от 0 до 5В, на второй ножеке в это время 0, потом, когда значение на первойножке доходит до 0, то на второй ножке значения начинают меняться от 0 до 5 в. Т. е. за каждую полуволну синуса отвечает один пин контроллера. Потом всё это можно подключить черз транисторы. Всё работает, правда нету осцилографа померять, правильность синуса :(. А сайт у Вас хороший. Продолжайте в том же духе.

  • Собрал все как в уроке в протеусе, осцилограмма получилась, но вот светодиод не загорается/затухает плавно, а моргает «как ему нравится». Что это значит? Как исправить ЭТО?

  • Этож синус, то что вы хотите здесь http://avr-start.ru/?p=367

  • синус-то синус, но вот диод моргает не с частотой 50 герц. он моргает «как ему хочется»(((

  • а можно сделать 3-х фазный синус? ессно чтобы между фазами было 120 градусов?

  • 3х фазный можно, посмотрите осциллограмму, на нагрузке, сразу поймете почему он так моргает.

  • Здравствуйте!
    собрал в протеусе схему из 4-го урока, как ни странно осциллограмма «правильная», а диод моргает. поставил V-метр, видно что напряжение прыгает.
    как так?

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

  • Светик моргать и будет. Дело в том, что у синуса переход в точке 0 — резкий, а на горбах очень плавный — функция меняется медленно, потому Вы и видите моргание. Забейте в таблицу значений не синус а треугольник- получите плавные переходы

  • Фильтр работает на всём диапазоне частот? Или придётся подбирать номинал резистора и конденсатора?

  • Не тестировал, слишком много условий, начиная от тактовой и величины таблицы. По идее фильтр работать будет, только амплитуда будет меняться в разных диапазонах

  • Константин, у вас ключевое слово DeadTime, у вас его нет,поэтом и КЗ

  • Ребята это как пример, для хорошего синуса лучше использовать 8 ног порта+ ЦАП
    есть не дорогие и минимум обвязки. после ЦАПа можно поставить фильтр 2-3 порядка,

  • Что не пойму ситуацию с частотой таймера.
    Частота таймера определяется как F_CPU/предделитель/необходимая_частота(например 50 Гц), т.е в вашем случае это 8000000/1/50=160000. Т.к. это значение слишком большое то необходимо использовать предделитель например 128 т.е. в итоге OCR1=0x04E1. И только тогда получим 50 Гц на таймере, Которые уже и стоит разбивать на 128

  • Вы написали тоже самое что в статье, не вижу расхождений

  • 2admin
    Так у вас ведь как раз таки нет предделителя в исходнике, а он необходим! Ваш синус в исходнике не дает 50 Гц он дает 122 Гц.

  • Математика, даже не знаю какой класс:
    1 период состоит из 128 значений, 1 период это 20мс. Значит 20мс разбиваем на 128 точек.
    0.02/128 = 0,00015625 сек — время которое нужно отмерять для подстановки одного значения
    1 тик = 1/8 000 000 = 0,000000125 сек
    теперь получаем количество нужных тиков для формирования прерывания
    0,00015625/0,000000125 = 1250 в шестнадцатеричной это 0x04e2
    Все ровно так, как и описано в статье и в исходнике.

  • Ок. Хочу использовать T2 вместо T1 тогда какие значения загонять в OCR необходимо, для частоты в 100 Гц ?

  • По аналогии:
    1 период состоит из 128 значений, 1 период это 10мс. Значит 10мс разбиваем на 128 точек.
    0.01/128 = 0,000078125 сек — время которое нужно отмерять для подстановки одного значения
    1 тик = 1/8 000 000 = 0,000000125 сек
    теперь получаем количество нужных тиков для формирования прерывания
    0,000078125/0,000000125 = 625 для Т2 это многовато. Можно взять предделитель на 8
    0,000078125/0,000001 = 78,125-1 в хексе это 4d.

  • И как же сделать трехфазный шим? Для работы транзисторов в противофазе нужен инвертированный и неинвертированный шим-сигнал (можно конечно расщепить и инвертировать сигнал уже вне проца, но это другой разговор). Три фазы по два канала шим итого шесть сигналов, а выводов под аппаратный шим в восьмой меге явно не шесть. Программный шим это уже заезженные 8Мгц/256тиков на прерывание/256значения хорошей таблицы синуса итого имеем унылый шим 120~ Гц. Какие ещё есть варианты? (Более навороченные процы не предлагать, AT90PWM серия, к примеру, ко мне едет пол-года и стоит миллионы)

  • Не копал в эту сторону, т.к. не нужно было, на сайте атмела есть апнот AVR447, в котором расписана вся теория для ATmega48/ATmega88/ATmega168. Если поискать можно даже найти перевод этого апнота

  • Помогите разобраться, я так понимаю, синус строиться на таймере Т2, а его частота на Т1? А каким способом Т1 передает тики в Т2? В исходниках смотрел, либо не понял либо не так или не то открыл.

  • T1 формирует «расстояние» между точками синусоиды, а T2 формирует уровень напряжения в этих точках. Т2 это шим

  • Спасибо за идею, разобрался.

  • Кстати, может кто подскажет, реальный синус же делается двумя транзисторами, верхнего и нижнего плеча, и возник вопрос: как обычно разделяют синус, программно на 2 ноги делят или шим идет с одной ноги а потом уже делиться аппаратно?

  • Таки можно отфильтровать постоянную составляющую конденсатором, а затем на усилитель двухполярный.

  • Изменяя содержимое регистра сравнения — можно изменять ширину импульса. И если мне надо получить пилообрзный сигнал, то нужно менять значение этого регистра сравнения по треугольному закону?Я что ли беру от болды запоминаю в памяти программ массив констант и эти константы буду использовать как отсчеты?Но какие значения брать констант как по треугольному закону это понять?

  • см.ответ выше:
    T1 формирует «расстояние» между точками синусоиды, а T2 формирует уровень напряжения в этих точках. Т2 это шим
    Таким образом Вам нужно формировать точки через равные промежутки с помощью Т1, а в этих точках от нуля до максимума увеличивать значение заполнения T2, т.е. менять напряжение. Пилообразный сигнал просто сформировать, для этого даже константы не нужны:
    if(OCR2 < 254) OCR2=OCR2+1; else OCR2=0;

  • Здравствуйте уважаемые знатоки микроконтроллеров.
    В микроконтроллерах я полный чайник, разве что смогу запрограммировать готовым кодом.
    Хочется сделать инвертор с чистым синусом на выходе отсюда и проблема. В коде не смыслю ничего 🙁 . Для управления верхних ключей мостовой схемы нужны 2 сигнала PWM. Нижние ключи думал открывать простым п импульсом в такт ШИМ импульсам противоположного верхнего плеча. Помогите пожалуйста написать код.

  • Подсказать и помочь с ошибками еще куда ни шло, но не думаю, что здесь есть энтузиасты, готовые писать за Вас код. Ищите готовые проекты, наверняка их великое множество.

  • Здравствуйте нашел такую программку для Atmega 16

    //—————————————————————————————-
    //Programmer: Syed Tahmid Mahbub
    //Target Microcontroller: ATMEGA16
    //Compiler: mikroC PRO for AVR (Can easily port to any other compiler)
    //——————————————————————————————

    unsigned int sin_table[32]={0, 100, 199, 296, 390, 480, 566, 645, 718,
    783, 840, 889, 928, 958, 979, 989, 989, 979, 958, 928, 889, 840, 783,
    718, 645, 566, 480, 390, 296, 199, 100,0};

    #define MOSA PORTD0_bit
    #define MOSB PORTD1_bit
    #define MOSC PORTD2_bit
    #define MOSD PORTD3_bit

    unsigned char FlagReg;
    #define Direction FlagReg.B0
    //0 -> MOS A + D
    //1 -> MOS B + C

    unsigned int TBL_POINTER_NEW, TBL_POINTER_OLD, TBL_POINTER_SHIFT, SET_FREQ;
    unsigned int TBL_temp;
    unsigned char DUTY_CYCLE;

    void interrupt() org IVT_ADDR_TIMER1_OVF{
    TBL_POINTER_NEW = TBL_POINTER_NEW + SET_FREQ;
    if (TBL_POINTER_NEW > 11;
    DUTY_CYCLE = TBL_POINTER_SHIFT;
    TBL_POINTER_SHIFT = sin_table[DUTY_CYCLE];
    OCR1AH = TBL_POINTER_SHIFT >> 8;
    OCR1AL = TBL_POINTER_SHIFT & 0x0F;
    TBL_POINTER_OLD = TBL_POINTER_NEW;
    }

    void main() {
    SET_FREQ = 410;
    TBL_POINTER_SHIFT = 0;
    TBL_POINTER_NEW = 0;
    TBL_POINTER_OLD = 0;
    DUTY_CYCLE = 0;
    DDRC = 0xFF;
    DDRD = 0XFF;
    OCR1AH = 0;
    OCR1AL = 0;
    TCCR1A = 0x82;
    ICR1H = 0x03;
    ICR1L = 0xE7;
    //ICR1 = 999 -> TOP -> 16kHz
    TIMSK = 0x04;
    TCCR1B = 0x19;
    SREG_I_bit = 1;
    while(1);
    }
    Можно ли как то в ней увеличить разрешение синуса ? и как это сделать. ШИМ там работает с частотой 16 кГц.

  • Вчера перерыл запасы радиодеталей к схеме что в предыдущем посте. Нету подходящего кварца наверное придется заказывать Нельзя ли настроить программу так чтобы тактирование контроллера было от 12 МГц или 8 Мгц? И как это сделать? В протеусе моделька работает на 16 МГЦ с шимом 16 кГц.

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

  • Пробовал увеличить, но тогда сам синус искажается в виду как понимаю несовпадения шима синуса и импульсов идущих на логику. Хотя могу и ошибаться.

  • nikola56rus, начните с малого, запустите пример из статьи. Вам нужен CAVR и Proteus. Посмотрите на шим в протеусе. Попробуйте изменить частоту синуса, путем изменения OCR1A в большую/меньшую сторону. Разберитесь с тем как OCR1A получается из формулы.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика