PWM или ШИМ (широтно импульсная модуляция) на AVR для новичков. Часть 1
На форуме достаточно часто встречаются вопросы по реализации Широтно Импульсной Модуляции на микроконтроллерных устройствах. Я и сам очень много спрашивал по этому поводу и, разобравшись, решил облегчить труд новичкам в этой области, так как информации в сети много и рассчитана она на разработчиков разного уровня, а сам я только- только в нем разобрался и память ещё свежа.
Так как для меня самым важным было применение ШИМ именно для управления яркостью светодиодов, то именно их я и буду использовать в примерах. В качестве микроконтроллера будем использовать горячо любимый ATmega8.
Для начала вспомним, что такое ШИМ. ШИМ сигнал – это импульсный сигнал определенной частоты и скважности:
Частота, это количество периодов за одну секунду. Скважность- отношение длительности импульса к длительности периода. Можно изменять и то и другое, но для управления светодиодами достаточно управлять скважностью. На картинке выше мы видим ШИМ сигнал со скважностью 50 %, так как длительность импульса (ширина импульса) ровно половина от периода.
Соответственно светодиод будет ровно половину времени во включенном состоянии и половину в выключенном. Частота ШИМ очень большая и глаз не заметит мерцания светодиода из за инерционности нашего зрения, поэтому нам будет казаться, что светодиод светится на половину яркости.
Если мы изменим скважность на 75%, то яркость светодиода будет на 3 четверти от полной, а график будет выглядеть так:
Получается, что мы можем регулировать яркость светодиода от 0 до 100 %. А теперь поговорим о таком параметре ШИМ, как разрешение. Разрешение- это количество градаций (шагов) регулировки скважности, мы будем рассматривать разрешение в 256 шагов.
С параметрами вроде разобрались, теперь поговорим о том, как нам получить этот самый ШИМ от микроконтроллера. Берем остро заточенный разогретый паяльник и начинаем пытать МК, одновременно подцепившись к двум его ногам осциллографом и проверяя наличие на них сигнала нужной нам скважности.
В микроконтроллерах есть аппаратная поддержка ШИМ и несколько каналов для него, в нашем случае 3. За выдачу ШИМ отвечают определенные выводы МК, в нашем случае OC2, OC1A, OC1B (15,16,17 нога в DIP корпусе). Так же для этого используются таймеры микроконтроллера, в нашем случае TC1, TC2.
Так как же сконфигурировать МК для выдачи сигнала необходимой скважности? Все очень просто, для начала сконфигурируем нужные нам ноги на выход:
PORTB=0x00;
DDRB=0x0E; // 0b00001110
Далее начнем конфигурировать таймеры. Для таймера TC1 нам потребуются два регистра: TCCR1A и TCCR1B. Открываем даташит и читаем как настраиваются эти регистры. Я настроил его на 8 битный сигнал ШИМ, что соответствует разрешению в 256 шагов:
TCCR1A=0xA1;
TCCR1B=0x09;
Для таймера TC2 мы будем использовать регистр TCCR2=0x69;. Его настройка выглядит так:
TCCR2=0x69;
Всё, таймеры сконфигурированы. Скважность будем задавать регистрами OCR1A,OCR1B, OCR2:
Зададим требуемые скважности:
OCR1A=0x32; //50 шагов
OCR1B=0x6A; //106 шагов OCR2=0xF0; //240 шагов
Ну и поместим инкремент и декремент этих регистров в бесконечный цикл:
While(1)
{
OCR1A++;
OCR1B–;
OCR2++; delay_ms(50);
}
Первая тестовая программа готова и выглядит для CVAVR она так:
#include “mega8.h”
#include “delay.h” void main(void)
{
PORTB=0x00;
DDRB=0x0E; // 0b00001110 TCCR1A=0xA1;
TCCR1B=0x09; TCCR2=0x69; OCR1A=0x32; //50 шагов
OCR1B=0x6A; //106 шагов OCR2=0xF0; //240 шагов while (1) { OCR1A++; OCR1B–; OCR2++; delay_ms(50); };
}
Компилируем и пробуем в протеусе:
Как видим, программа полностью работоспособна и выполняет возложенные на нее задачи, ничего сложного в ней нет.
В следующей статье рассмотрим программный ШИМ, который необходим в случае если число аппаратных нам недостаточно или в силу других причин.
Прикрепленные файлы:
Источник: http://cxem.net/mc/mc231.php
Широтно-Импульсная Модуляция (ШИМ, PWM). Урок AVR 8
Источник: http://articles.greenchip.com.ua/1-1-20.html
Программный ШИМ — DRIVE2
Здесь я покажу, как настоящие зад██ты программисты делают программный ШИМ.
Обычно, чтобы сделать широтно-импульсную модуляцию на каком-либо порту, когда аппаратный ШИМ по той, или иной причине недоступен, используют один из двух подходов:
1.
Шим в циклеТут подход предельно прост: на выходе устанавливается высокий уровень, затем запускается цикл, часто пустой, выдерживающий паузу высокого уровня, затем на порту устанавливается низкий уровень и ещё одна пауза, для удержания низкого уровня. Что-то вроде этого:for(;;) {set_port_high();for (int i = 0; i < duty_cycle; i++) {}set_port_low();for (int i = duty_cycle; i < cycle_len; i++) {}}
Плюс такого подхода, что скорость работы ШИМа достаточно высока, поскольку каждая итерация в цикле ожидания занимает 4-6 тактов, то можно добиться достаточно высокой частоты ШИМ.
Минусы очевидны: программа не может производить никаких действий, пока выводится ШИМ. Если требуется выводить ШИМ на несколько каналов, это усложняет циклы, и снижает скорость. Если требуется совершать посторонние действия в цикле, это повлияет на точность установки ШИМ. Трудно точно предсказать частоту работы ШИМ, которая сильно зависит от того, как подобный код будет скомпилирован.
2. Шим в прерыванииЗдесь подход такой: настраивается периодически срабатывающее прерывание, например, по переполнению таймера, или по сравнению, если таймер работает в режиме CTC.
В прерывании ведётся увеличение счётчика, в зависимости от значения которого, устанавливается тот или иной уровень на ШИМ-выходе.
Например так:ISR(TIMER0_COMPA_vect) {pwm_counter++;if (pwm_conter >= cycle_len) pwm_counter = 0;if (pwm_counter < duty_cycle1) set_port1_high(); else set_port1_low();if (pwm_counter < duty_cycle2) set_port2_high(); else set_port2_low();}
Плюсы — т.к. это прерывание, то оно вызывается в строго предсказуемые моменты времени, значит частота ШИМ известна заранее и достигается большая точность установки ШИМ. Основное ПО может свободно делать свои дела.
Минусы — на вход в обработчик прерывания и выход из него тратится значительная часть процессорного времени. Работа прерывания может занимать более 60 тактов процессора. Если вызов прерывания происходит слишком часто, то это оставляет мало времени на работу основной части ПО:
В результате скорость ШИМ на несколько порядков ниже частоты работы ядра. Например, при частоте 9,6 МГц, и 7 битном ШИМ (счёт от 0 до 127), скорость ШИМ будет меньше 1 кГц.
Оптимизируем!Одна из очевидных оптимизаций, это не вызывать прерывание в те моменты, когда изменение уровня на порту не предполагается.
Например, можно запустить таймер, где один цикл таймера будет соответствовать одному циклу ШИМ, в прерываниях по переполнению и по сравнению менять соответствующим образом уровни на выводах.
Другой вариант, запускать прерывание по сравнению и при каждом срабатывание перенастраивать регистр сравнения на следующее время срабатывания.
В таком подходе можно поднять частоту ШИМ, т.к. время между прерываниями уже не так важно, даже если два подряд срабатывающих прерывания совсем не оставят времени для основного ПО, то в периоды паузы ПО успеет отыграться. Однако, обработчик прерывания должен успеть войти, запланировать следующий запуск и выйти. Чем больше выходов задействовано, тем сложнее получается обработчик и время его работы больше. В любом случае, разрешающая способность такого ШИМ, относительно скорости ядра, остаётся сравнительно небольшой.
Поскольку большая часть времени тратится на запуск и покидание обработчика прерывания, то очевидным подходом будет не выходить из обработчика, если рядом ожидается очередное действие.
Но это не упрощает процедуру планирования следующего запуска, а значит всё равно разрешающая способность остаётся довольно низкой.
Но! Можно заметить, что изменения логических уровней на портах и запуски обработчика происходят в определённые моменты цикла таймера. И от цикла к циклу они не изменяются. А значит, их можно рассчитать один раз заранее.
Планируем заранее!Можно заметить, что в цикле ШИМ с N выводами происходит не более N+1 действий: первое действие устанавливает высокие уровни на всех выводах, а последующие N действий устанавливают низкие уровни на тех или иных выводах.Иначе говоря, мы создаём микрокод — массив из описаний действий.
Каждое из действий это:1) перечень логических уровней, которые нужно вывести на порт;2) значение таймера, на которое нужно настроиться для следующего действия.
Зная, как много времени требуется на запуск прерывания, можно просчитать заранее: нужно ли настраиваться на вызов следующего прерывания, или же дождаться нужного значения таймера не выходя из прерывания. Поэтом добавим ещё флаг:
3) признак, что значение таймера нужно ожидать, не выходя из прерывания.
Наконец, мы хотим, чтобы выдаваемые значения ШИМ можно было менять. Но чего точно не хотим, чтобы они менялись посреди цикла ШИМ, или начали выполняться в момент построения микрокода.
https://www.youtube.com/watch?v=Xki0CD3uy0Y
Для этого у нас будет два массива с микрокодом: в одном содержится микрокод, выполняющийся в данный момент, а другой мы используем для подготовки нового микрокода.Осталось обеспечить переключение микрокода в безопасные моменты.
У нас есть переменная, которая хранит указатель на следующую операцию, которую нужно выполнить. Заведём ещё одну, показывающую, на какой из двух массивов с микрокодом следует переключиться, когда исполнение текущего дойдёт до конца.
Последнюю операцию в микрокоде пометим специальным образом, показывающим, нужно ли брать адрес очередной операции из текущего микрокода, или же адрес следующей операции нужно прочитать из этой переменной.Для этого заведём специальный флаг:
4) признак, что это не последняя операция в микрокоде (т.е. команда продолжать выполнять текущий микрокод)
ПримерчикТут два примера для ATtiny13A. Один — простая демонстрация с использованием 5 ШИМ выводов. Другой отображает температуру на RGB светодиоде. Замер температуры происходит путём сравнения скоростей осцилляторов системного генератора и сторожевого таймера.
Исходники тут:
aterlux.ru/files/SoftPWM.zip (5 ШИМ выводов)
aterlux.ru/files/SoftPWMthermo.zip (замер температуры сравнением скоростей осцилляторов)
Не буду расписывать детали реализации, все комментарии есть в исходниках. Расскажу только то что получилось:1) до 6 ШИМ выходов, с разрешающей способностью в 16 тактов процессора. Т.е. между двумя изменениями уровней может быть всего 16 тактов процессора.2) ШИМ в 128 шагов. Т.е.
вывод значения 0 – «постоянный низкий уровень», 128 – «постоянный высокий уровень». Т.е. частота 1 / 2048 от частоты процессора, и при скорости 9,6 МГц это будет 4,6 кГц.3) Смена уровней на выводах, при одинаковых значениях коэффициентов заполнения, происходит строго одновременно.
Можно также настроить использование нескольких выводов от одного коэффициента, при этом настроить инверсию на некоторые, и добиться работы в противофазе.
4) Можно настроить управление регистром не PORTB, а DDRB, тогда будет работа ШИМ в режиме «открытого стока», как это сделано в примере с измерением температуры.
Использование библиотечкиВ библиотеке три функции:
swpwm_start() — запускает ШИМ.
swpwm_stop() — останавливает ШИМ.
swpwm_update() — компилирует заданные значения коэффициентов заполнения в микрокод.
Для указания коэффициентов заполнения есть массив swpwm[].Т.е. принцип работы такой:Запускаем swpwm_start(), задаём коэффициенты, записывая значения в swpwm[] и применяем их вызовом swpwm_update().
Всё остальное, в исходном коде.
Источник: https://www.drive2.ru/b/484782649219481995/
Шим — широтно-импульсная модуляция
ШИМ или PWM (англ. Pulse-Width Modulation) – широтно-импульсная модуляция – это метод предназначен для контроля величины напряжения и тока. Действие ШИМ заключается в изменении ширины импульса постоянной амплитуды и постоянной частотой.
Свойства ШИМ регулирования используются в импульсных преобразователях, в схемах управления двигателями постоянного тока или яркостью свечения светодиодов.
Принцип действия ШИМ
Принцип действия ШИМ, как указывает на это само название, заключается в изменении ширины импульса сигнала. При использовании метода широтно-импульсной модуляции, частота сигнала и амплитуда остаются постоянными. Самым важным параметром сигнала ШИМ является коэффициент заполнения, который можно определить по следующей формуле:
Также можно отметить, что сумма времени высокого и низкого сигнала определяет период сигнала:
где:
- Ton – время высокого уровня
- Toff – время низкого уровня
- T – период сигнала
Время высокого уровня и время низкого уровня сигнала показано на нижнем рисунке. Напряжение U1- это состояния высокого уровня сигнала, то есть его амплитуда.
На следующем рисунке представлен пример сигнала ШИМ с определенным временным интервалом высокого и низкого уровня.
Расчет коэффициента заполнения ШИМ
Расчет коэффициента заполнения ШИМ на примере:
Для расчета процентного коэффициента заполнения необходимо выполнить аналогичные вычисления, а результат умножить на 100%:
Как следует из расчета, на данном примере, сигнал (высокого уровня) характеризуется заполнением, равным 0,357 или иначе 37,5%. Коэффициент заполнения является абстрактным значением.
Важной характеристикой широтно-импульсной модуляция может быть также частота сигнала, которая рассчитывается по формуле:
Значение T, в нашем примере, следует взять уже в секундах для того, чтобы совпали единицы в формуле. Поскольку, формула частоты имеет вид 1/сек, поэтому 800ms переведем в 0,8 сек.
Благодаря возможности регулировки ширины импульса можно изменять, например, среднее значение напряжения. На рисунке ниже показаны различные коэффициенты заполнения при сохранении той же частоты сигналов и одной и той же амплитуды.
Для вычисления среднего значения напряжения ШИМ необходимо знать коэффициент заполнения, поскольку среднее значение напряжения является произведением коэффициента заполнения и амплитуды напряжения сигнала.
Для примера, коэффициент заполнения был равен 37,5% (0,357) и амплитуда напряжения U1 = 12В даст среднее напряжение Uср:
В этом случае среднее напряжение сигнала ШИМ составляет 4,5 В.
ШИМ дает очень простую возможность понижать напряжение в диапазоне от напряжения питания U1 и до 0. Это можно использовать, например, для регулировки яркости свечения светодиодов, или скорости вращения двигателя DC (постоянного тока), питающиеся от величины среднего напряжения.
Сигнал ШИМ может быть сформирован микроконтроллером или аналоговой схемой. Сигнал от таких схем характеризуется низким напряжением и очень малым выходным током. В случае необходимости регулирования мощных нагрузок, следует использовать систему управления, например, с помощью транзистора.
Это может быть биполярный или полевой транзистор. На следующих примерах будет использован биполярный транзистор BC547.
Пример управления светодиодом при помощи ШИМ.
Сигнал ШИМ поступает на базу транзистора VT1 через резистор R1, иначе говоря, транзистор VT1 с изменением сигнала то включается, то выключается. Это подобно ситуации, при которой транзистор можно заменить обычным выключателем, как показано ниже:
Упрощенная схема управления светодиодом.
Когда переключатель замкнут, светодиод питается через резистор R2 (ограничивающий ток) напряжением 12В. А когда переключатель разомкнут, цепь прерывается, и светодиод гаснет. Такие переключения с малой частотой в результате дадут мигающий светодиод.
Однако, если необходимо управлять интенсивностью свечения светодиодов необходимо увеличить частоту сигнала ШИМ, так, чтобы обмануть человеческий глаз. Теоретически переключения с частотой 50 Гц уже не незаметны для человеческого глаза, что в результате дает эффект уменьшения яркости свечения светодиода.
Чем меньше коэффициент заполнения, тем слабее будет светиться светодиод, поскольку во время одного периода светодиод будет гореть меньшее время.
Такой же принцип и подобную схему можно использовать и для управления двигателем постоянного тока. В случае двигателя необходимо, однако, применять более высокую частоту переключений (выше 15-20 кГц) по двум причинам.
Первая из них касается звука, какой может издавать двигатель (неприятный писк). Частота 15-20 кГц является теоретической границей слышимости человеческого уха, поэтому частоты выше этой границы будут неслышны.
Второй вопрос касается стабильности работы двигателя. При управлении двигателем низкочастотным сигналом с малым коэффициентом заполнения, обороты двигателя будут нестабильны или может привести к его полной остановке. Поэтому, чем выше частота сигнала ШИМ, тем выше стабильность среднего выходного напряжения. Также меньше пульсаций напряжения.
Не следует, однако, слишком завышать частоту сигнала ШИМ, так как при больших частотах транзистор может не успеть полностью открыться или закрыться, и схема управления будет работать не правильно. Особенно это относится к полевым транзисторам, где время перезарядки может быть относительно большое, в зависимости от конструкции.
Слишком высокая частота сигнала ШИМ также вызывает увеличение потерь на транзисторе, поскольку каждое переключение вызывает потери энергии. Управляя большими токами на высоких частотах необходимо подобрать быстродействующий транзистор с низким сопротивлением проводимости.
Управляя двигателем постоянного тока с помощью ШИМ, следует помнить о применении диода для защиты транзистор VТ1 от индукционных всплесков, появляющимся в момент выключения транзистора. Благодаря использованию диода, индукционный импульс разряжается через него и внутреннее сопротивление двигателя, защищая тем самым транзистор.
Схема системы управления скоростью вращения двигателя постоянного тока с защитным диодом.
Для сглаживания всплесков питания между клеммами двигателя, можно подключить к ним параллельно конденсатор небольшой емкости (100nF), который будет стабилизировать напряжение между последовательными переключениями транзистора. Это также снизит помехи, создаваемые частыми переключениями транзистора VT1.
Источник: http://www.joyta.ru/7532-shim-shirotno-impulsnaya-modulyaciya/
ATmega16 – PWM с помощью T/C0, T/C1, T/C2
Adblockdetector