Использование широтно-импульсной модуляции (ШИМ) в микроконтроллерах AVR ATmega16

Широтно-импульсная модуляция (сокр. ШИМ, от англ. PWM — Pulse Width Modulation) является технологией, позволяющей изменять ширину импульсов в то время как частота следования импульсов остается постоянной. В настоящее время она применяется в разнообразных системах контроля и управления, а также в различных приложениях, таких как, к примеру, управление скоростью вращения двигателей, измерениях, управление мощностью чего-либо, связь и др.

Использование широтно-импульсной модуляции (ШИМ) в микроконтроллерах AVR ATmega16: внешний вид конструкции

Также при использовании ШИМ можно генерировать аналоговые сигналы используя цифровые сигналы. В данной статье мы рассмотрим основы применения широтно-импульсной модуляции (ШИМ) в микроконтроллере ATmega16 (семейство AVR) на примере изменения интенсивности свечения светодиода. Данный пример уже рассматривался на нашем сайте в этой статье (более подробная и наглядная статья), но здесь материал изложен немного по другому – у вас есть возможность выбрать какой из этих материалов использовать.

Контакты ШИМ в микроконтроллере AVR ATmega16

Микроконтроллер Atmega16 имеет 4 контакта для использования ШИМ модуляции — PB3(OC0), PD4(OC1B), PD5(OC1A), PD7(OC2). Более наглядно они представлены на следующем рисунке.

Контакты ШИМ в микроконтроллере AVR ATmega16

Также ATmega16 имеет два 8-битных (Timer0 и Timer2) и один 16-битный таймер (Timer1). Для понимания принципов формирования ШИМ мы должны понимать основы работы с этими таймерами. Как известно, частота представляет собой количество циклов в секунду поэтому она однозначно связано зависимостью с временем. То есть чем более высокая частота нам нужна, тем более быстрый таймер мы должны использовать. Чем выше частота ШИМ, тем более точно мы можем управлять ее параметрами.

В данной статье для управления ШИМ в микроконтроллере ATmega16 мы будем использовать его Timer2. С его помощью можно выбрать коэффициент заполнения (duty cycle) ШИМ в широких пределах. Кратко рассмотрим основы этого процесса.

Что такое ШИМ сигнал

ШИМ – это сигнал с различными интервалами ON и OFF сигнала (различными продолжительностями включения). Время, в течение которого сигнал имеет высокий уровень, называется временем включения (“on time”), а время, в течение которого сигнал имеет низкий уровень — время выключения (“off time”). У ШИМ сигнала есть два параметра, которые мы рассмотрим далее.

Коэффициент заполнения ШИМ

Процент времени, в течение которого ШИМ сигнал имеет высокий уровень, называется коэффициентом заполнения. К примеру, коэффициент заполнения ШИМ сигнала с периодом (длительностью) 100 мс, в котором в течение 50 мс сигнал имеет высокий уровень и в течение 50 мс имеет низкий уровень, равен 50%. Аналогично, если для такой же длительности (100 мс) сигнал 25 мс остается на высоком уровне и 75 мс на низком, то коэффициент заполнения для такого сигнала будет равен 25%. Для его определения нам необходимо знать только длительность высокого уровня сигнала (длительность низкого уровня легко определить как разность между периодом сигнала и длительность сигнала высокого уровня). Более наглядно ШИМ сигнал представлен на следующем рисунке.

Принцип широтно-импульсной модуляции (ШИМ)

Формула для расчета коэффициента заполнения (Duty Cycle) выглядит следующим образом:

Duty Cycle (%) = On Time/(On Time + Off Time)

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

Выбор режима ШИМ

После выбора нужного нам коэффициента заполнения необходимо выбрать еще режим ШИМ – то есть то, каким образом ШИМ будет работать. Существует три типа ШИМ:

  1. Быстрая ШИМ (Fast PWM).
  2. ШИМ с коррекцией фазы (Phase Correct PWM).
  3. ШИМ с коррекцией фазы и частоты (Phase and Frequency Correct PWM).

Быстрая ШИМ используется в случаях когда нам не важна фаза импульсов, например, управление скоростью вращения двигателя или яркостью свечения светодиода.

Для генерации быстрой ШИМ нам необходимо будет запустить на таймере счет и когда он досчитает до определенного значения сбрасывать значение таймера снова в ноль. Таким образом мы установим период следования ШИМ импульсов. Таким образом мы можем контролировать импульс, устанавливая высокое значение сигнала когда счетчик таймера досчитает до определенного значения. А когда счетчик будет возвращаться в 0 на это время сигнал будет низкого уровня. Таким образом, мы имеем большую гибкость в управлении ШИМ сигналом используя всего лишь один таймер.

Необходимые компоненты

Микроконтроллер ATmega16
Источник питания с напряжением 5 Вольт
Программатор AVR-ISP, USBASP или другой подобный
Кварцевый генератор на 16 МГц
Конденсатор 100 нФ (2 шт.)
Конденсатор 22 пФ (2 шт.)
Кнопка
Соединительные провода
Макетная плата
Светодиод (2 шт.)

Схема устройства

Схема устройства приведена на следующем рисунке.

Использование широтно-импульсной модуляции (ШИМ) в микроконтроллерах AVR ATmega16: схема соединений

Мы будем использовать для формирования ШИМ сигнала контакт OC2 микроконтроллера ATmega16, поэтому соедините контакт Pin21 (PD7) микроконтроллера со светодиодом.

Программирование ШИМ сигнала в микроконтроллере ATmega16 на языке С (Си)

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

Начать программирование ШИМ ATmega16 необходимо с установки нужного значения регистра Таймера 2 – его биты приведены на следующем рисунке. Изменяя данные биты, мы можем настраивать нужные нам параметры ШИМ.

Регистр Таймера 2 ATmega16

В регистре Таймера 2 три группы битов:

  1. FOC2 (Force Output Compare for Timer2) – устанавливается когда WGM биты определяют не режим ШИМ.
  2. WGM2(Wave Generation Mode for Timer2 – режим генерации волны) – эти биты контролируют последовательность счета, максимальное значение счета (TOP counter value) и какой тип формы сигналов будет использован.
  3. COM2 (Compare Output Mode for Timer2 – режим сравнения для Таймера 2) – можно выбрать режим с инвертированием и без инвертирования.

Установим биты WGM20 и WGM21 чтобы активировать режим быстрой ШИМ.

TCCR2 |= (1<<WGM20)|(1<<WGM21);

Биты WGM20 и WGM21 Таймера 2 в микроконтроллере ATMega16

Для полной информации относительно возможных режимов ШИМ, устанавливаемых битами WGM20 и WGM21, посмотрите официальный даташит на ATmega16.

Поскольку мы не будем использовать предделитель, запишем в необходимые биты ‘001’:

TCCR2 |=(1<<COM21)|(1<<CS20)|(0<<CS21)|(0<<CS22);

Установка битов для настройки предделителя таймера 2 микроконтроллера ATmega16

Настройки режима сравнения (Compare Output Mode) для режима быстрой ШИМ приведены в следующей таблице.

COM21 COM20 Описание
0 0 Normal port operation, OC2 disconnected
0 1 Зарезервировано
1 0 Clear OC2 on Compare match, Set OC2 at TOP
1 1 Set OC2 on compare match, clear OC2 at TOP

Увеличиваем коэффициент заполнения ШИМ от 0 до 100% — таким образом яркость свечения светодиода будет изменяться с течением времени. Будем использовать значения в диапазоне 0-255, которые будем передавать в OCR2 – это как раз тот байт, который отвечает за установку того самого значения, которое задает различные продолжительности включения (отношение длительности импульса к периоду повторения) импульсов ШИМ.

for(duty=0; duty<255; duty++) // 0 to max duty cycle
{
OCR2=duty; //медленно увеличиваем яркость свечения светодиода
_delay_ms(10);
}

Аналогичным образом уменьшаем коэффициент заполнения со 100% до 0% чтобы постепенно уменьшать яркость свечения светодиода.

for(duty=0; duty>255; duty--) // max to 0 duty cycle
{
OCR2=duty; // медленно уменьшаем яркость свечения светодиода
_delay_ms(10);
}

Полный текст программы

#define F_CPU 16000000UL // задаем частоту микроконтроллера
#include "avr/io.h"
#include <util/delay.h>

void PWM_set() // задаем настройки ШИМ
{
DDRD |= (1<<PD7); //устанавливаем PD7 как выход ШИМ
TCCR2 |= (1<<WGM20)|(1<<WGM21); //выбираем режим быстрой ШИМ
TCCR2 |=(1<<COM21)|(1<<CS20)|(0<<CS21)|(0<<CS22); //clear OC2 on compare match
}

int main ()
{
unsigned char duty;
PWM_set(); // вызов функции установки параметров ШИМ
while (1)
{
for(duty=0; duty<255; duty++) // 0 to max duty cycle
{
OCR2=duty; // медленно увеличиваем яркость свечения светодиода
_delay_ms(10);
}
for(duty=0; duty>255; duty--) // max to 0 duty cycle
{
OCR2=duty; // медленно уменьшаем яркость свечения светодиода
_delay_ms(10);
}
}
}

Видео, демонстрирующее работу схемы

(Проголосуй первым!)
Загрузка...
8 просмотров


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

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