Шим на микроконтроллере своими руками

Обновлено: 05.07.2024

Широтно-импульсная модуляция (pulse width modulation, PWM) часто используется в цифровой технике. AVR-микроконтроллеры имеют встроенную аппаратную возможность генерировать ШИМ-сигнал.
Особенность этого способа модуляции заключается в том, что он позволяет регулировать постоянную составляющую выходного сигнала средствами логических элементов. Другими словами можно изменять яркость светодиодов, скорость вращения коллекторных двигателей, температуру нагревателей и т.д.
Временная диаграмма ШИМ-сигнала:

Подготовка к работе

На нашей плате TutorShield есть трехцветный светодиод. Отдельные цвета подключены к выводам PB1, PB2 и PB3 на которые можно вывести ШИМ-сигнал. Для возможности управления им, установите перемычку "color" так, как показано на рисунке. Всех остальных перемычек быть не должно.

Голубой светодиод подключен к выводу PB1, оранжевый к PB2, зеленый к PB3.

Первый пример

У микроконтроллера есть встроенные таймеры, которые и управляют формированием ШИМ-сигнала. Для использования достаточно правильно настроить таймер и затем для формирования сигнала потребуется только изменять состояние одного регистра.
Вообще, таймеры в микроконтроллерах — очень полезная вещь. Они позволяют точно отмерять время, выполнять "фоновые" программы и т.д. Их полный функционал описан в datasheet от производителя микроконтроллера. В этой статье мы не будем описывать весь функционал таймера, а остановимся только на том, что понадобится нам для генерирования ШИМ-сигнала.
Прежде чем начать объяснения, давайте посмотрим как это будет выглядеть. Скомпилируйте и загрузите в память микроконтроллера следующую программу:

То что программа делает хорошо видно в функции main(). С периодичностью в 1000мс она изменяет яркость светодиода:

Теперь давайте подробно разберемся с настройкой таймера.

Настройка таймера

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

  1. Timer/Counter 1 Control Register A – TCCR1A. Бит COM1A1 это регистра отвечает за сброс таймера при совпадении. Бит WGM11 связан с битами WGM12 и WGM13 следующего регистра.
  2. Timer/Counter 1 Control Register B – TCCR1B. Биты WGM11, WGM12, WGM13, выставленные одновременно, переводят таймер в режим генерирования ШИМ-сигнала. Бит CS10 задает скорость счета таймера одновременно запускает таймер и задает делитель частоты тактового сигнала. Если не задать никакой делитель — таймер будет остановлен. С битом CS10 делитель будет равен единице, то есть таймер будет тактироваться от кварца.
  3. Timer/Counter 1 – TCNT1H и TCNT1L. В этих двух регистрах хранится состояние таймера. Именно в них с каждым "тиком" кварца увеличивается хранимое значение. Обнулим его, на всякий случай
  4. Input Capture Register 1 – ICR1H и ICR1L. Это период следования импульсов. То есть, когда содержимое регистра TCNT1 достигнет значения 0xFF начнется следующий период сигнала
  5. Output Compare Register 1A — OCR1AH и OCR1AL. Задает скважность. То есть пока в регистре TCNT1 значение меньше OCR1A, то на выводе "1", а после этого "0"

Все это гораздо проще понять по следующей картинке:

Диаграмма работы таймера

Диаграмма работы таймера

Мы предположим, в регистр OCR1A записано значение "100".
Тактовый сигнал у нас задан без делителя. Период следования тактовых импульсов 1/16МГц = 62,5нс. С каждым новым тактом, состояние регистра TCNT1 увеличивается на единицу. При это постоянно происходит его сравнение с регистрами OCR1A и ICR1. Как только он досчитывает до OCR1A происходит переключение состояния вывода из "1" в "0". При достижении значения ICR1 состояние TCNT1 сбрасывается в ноль, на выводе снова выставляется "1" и начинается следующий период сигнала.
Несложно посчитать период следования импульсов в нашем проекте: 255*62,5 = 15937,5нс. Примерно 16мкс. Частота при этом 62,5кГц. Это очень большая частота и снизить ее можно увеличив делитель или/и значение ICR1.
В итоге, чтобы изменить скважность сигнала остается только записать новое значение в регистр OCR1. Мы переопределили его директивой

В бесконечном цикле программа именно это и происходит: устанавливаем относительную скважность 200, ждем 1с, скважность 50, ждем 1с. Осталось только самое простое — понять на каком выводе будет этот сигнал. Изменить это нельзя и формироваться он будет на выводе OC1A, который в микроконтроллере Atmega8 подключен к 13му пину PB1 (или D9 выводу Arduino).

Второй пример

Теперь сделаем циклическое изменение яркости. Для потребуется только добавить цикл, перебирающий возможные значения скважности от 0 до 255. Сделаем его при помощи простой функции for().

Если все сделано правильно — то работа будет выглядеть вот так:

Третий пример

Всего в микроконтроллере Atmega8 два аппаратных таймера — 16ти-битный и 8ми-битный. Причем в первом есть сразу два модуля сравнения и он может формировать одновременно два разных ШИМ-сигнала. Третий ШИМ-сигнал может быть сформирован при помощи второго таймера. То есть всего на трех выводах может быть сгенерирован аппаратный ШИМ. Это выводы МК PB1, PB2 и PB3. Именно этим обусловлены ограничения функции Arduino analogWrite().
В этом разделе настроим еще два канала и будем управлять остальными светодиодами.
Для этого потребуется только дополнительно выставить бит COM1B1 и начать управлять регистром OCR1B. На эти действия будет реагировать оранжевый светодиод, подключенный к выводу PB2.
Для использования третьего канала придется вставить дополнительную функцию timer2_init() для запуска второго таймера.

Второй таймер имеет гораздо меньше функций и настраивать его проще. Бит COM21 выводит сигнал на ногу. Биты WGM21 и WGM20 переводят таймер в режим формирования ШИМ. CS20 задает делатель тактового сигнала, равный нулю. Как видите, тут изменять частоту получится только при помощи делителя.
Вот видео работы этого примера:

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

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

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

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

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

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

В данной статье для управления ШИМ в микроконтроллере 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 на это время сигнал будет низкого уровня. Таким образом, мы имеем большую гибкость в управлении ШИМ сигналом используя всего лишь один таймер.

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

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

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

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

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

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

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

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

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

Широтно-импульсная модуляция очень часто используется для регулировки/управления источниками света, двигателями. Целью данного проекта было создание дешевого устройства – ШИМ-контроллера, которое будет полезно во многих областях. Изначально основой конструкции был выбран микроконтроллер компании Atmel ATMega32, т.к. имеющаяся периферия легко позволяла организовать не только многоканальный ШИМ с управлением по последовательному интерфейсу, но и добавить аналоговый интерфейс управления, клавиатуру и LCD-индикатор для организации пользовательского интерфейса, а также получить дополнительные выходные линии общего назначения. Однако, не проигрывая в функциональности, может использоваться и микроконтроллер ATMega16 (это учтено при разработке программного обеспечения). Рабочая частота выбрана из расчета возможности использования микроконтроллеров ATMega32L и ATMega16L.

4 канальный ШИМ-контроллер

Устройство имеет очень гибкие настройки. Например, параметры работы каналов ШИМ могут управляться посредством команд с компьютера, посредством аналоговых регуляторов (потенциометры) или с помощью клавиатуры (с отображением пользовательского интерфейса на LCD-индикаторе). Самим LCD-индикатором также возможно управлять через RS232, отображение текущих установок и режимов возможен в числовом, либо в графическом формате.

Основные характеристики устройства:

  • 4-канала ШИМ, разрешение 8 бит, частота ШИМ - 31 кГц;
  • интерфейс RS232 для управления и контроля с PC;
  • простое схемотехническое решение с минимальным количеством внешних элементов;
  • 12-кнопочная клавиатура;
  • возможность аналоговой регулировки;
  • до 7 выходных линий общего назначения;
  • 4-строчный LCD-дисплей;
  • управление LCD-дисплеем через последовательный интерфейс;
  • пользовательское меню;
  • гибкие настройки;
  • программная реализация буферов FIFO для ускорения работы.

Управление выходами общего назначения (в т.ч. светодиодными индикаторами) осуществляется с компьютера (RS232), пользователь так же имеет возможность считывать историю нажатия клавиш на клавиатуре (последние 32 нажатия клавиш, либо сразу же после нажатия какой-либо клавиши).

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

Логическая схема устройства.

4-канальный ШИМ-контроллер

Принципиальная схема устройства

Схемотехническое решение очень простое. Для тактирования микроконтроллера выбран кварцевый резонатор 8 МГц, источник питания +5.0 В собран на интегральном стабилизаторе LM7805, индуктивность 10 мкГн и конденсатор 100 нФ – образуют фильтр, предотвращающий проникновение помех при переключениях в аналоговых цепях. Преобразователь логических уровней MAX232 используется для реализации последовательного интерфейса. LCD-индикатор на чипсете Hitachi (HD44780) с разрешением 20×4 либо 40×2. Узел управления подсветкой индикатора реализован на транзисторе MJE3055T (возможно использование более дешевого аналога). Матрица клавиатуры, стандартная, 4×3.

После подачи питания, микроконтроллер устанавливает последние сохраненные параметры в EEPROM: режимы управления каналами ШИМ (аналоговое управление, управление по последовательному интерфейсу, управление с клавиатуры), формат отображения параметров на индикаторе (управление по последовательному интерфейсу, отображение значений ШИМ, отображение аналоговых значений), а также состояние выходных линий общего назначения, состояние подсветки дисплея.

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

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

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

Пример реализации выходных каскадов ШИМ-контроллера

Следующая часть будет посвящена программному обеспечению микроконтроллера, где будут рассмотрены основные блоки алгоритма, их особенности.

Это простой ШИМ-генератор работающий от стабилизированного источника питания с напряжением 4,75…5,25 В. На его выходе генерируется прямоугольный сигнал с постоянной частотой 1 Гц, но с регулируемым коэффициентом заполнения в диапазоне 0…100% с шагом 1%, в зависимости от установленных перемычек J1-J7.

Устройство найдет применение в мастерской каждого радиолюбителя, например, при тестировании различных прототипов цифровых схем.

Основой генератора является популярный микроконтроллер ATmega48. Вместо него можно использовать модели ATmega88 или ATmega168, которые отличаются только большим объемом памяти.

Управляющая программа написана на ассемблере и идентична для каждого из упомянутых микроконтроллеров (занимает 2440 байт флэш-памяти). После включения источника питания или сброса микроконтроллера с помощью кнопки S1 управляющая программа конфигурирует вывод PB0 (№ 14) в качестве выхода с низким логическим уровнем (LOW), а все остальные выводы — как входы с высоким логическим уровнем (включены внутренние подтягивающие резисторы).


Затем микроконтроллер считывает состояние перемычек J1-J7, которые подключены к контактам PD0…PD6. Если все перемычки открыты (OFF), программа переходит к выполнению цикла, генерирующего сигнал с заполнением 0% (режим 0) и на выходе генератора все еще остается низкое логическое состояние (LOW).

Однако если при помощи перемычек установлено некоторое двоичное значение X = 1…99 (J1 — самый младший бит), то программа переходит к соответствующему циклу (режим X), который выполняется без прерывания.

В каждом таком цикле есть две инструкции, которые переключают состояние выхода PB0 на противоположное. Время между переключениями различается (за исключением 50% заполнения), но их сумма всегда равна 1 секунде. Благодаря этому на выходе генератора получается прямоугольный сигнал с различным заполнением, но всегда с частотой 1 Гц.

Если перемычками установлено двоичное значение X > 99, программа переходит к выполнению цикла, генерирующего 100% сигнал (режим 100), при этом на выходе генератора постоянно высокое логическое состояние (HIGH).

Для правильной работы генератора необходимо использовать кварцевый резонатор Q1 с номинальной частотой 4 МГц, поскольку циклы в управляющей программе написаны именно для этой частоты микроконтроллера.

Резистор R2 и конденсатор C1 образуют низкочастотный фильтр, который подавляет дребезг контактов, возникающий в момент нажатия кнопки S1. Транзисторы VT1 (BC547) и VT2 (BC557) работают в качестве выходного буфера с током до 100 мА.

Все возможные для установки комбинации перемычек J1-J7 и соответствующий им коэффициент заполнения сигнала, приведены в следующей таблице.

После пайки всех элементов убедитесь, что нет коротких замыканий. Подайте питание и запрограммируйте микроконтроллер, используя любой ISP программатор через разъем CON3. Контакты разъема CON3 расположены стандартным образом, рекомендованным Atmel.

4

При программировании необходимо установить соответствующие fuse и lock биты:

  • FL (Fuse Low): $F7
  • FH (Fuse High): $DF
  • FE (Fuse Extended): $F9 ($FF для ATmega48)
  • LB (Lock Bits): $FF

При таких настройках:

  • используется внешний кварцевый резонатор (биты CKSEL3-0 = 0111);
  • делитель частоты на 8 отключен, что вызывает тактирование микроконтроллера на полной частоте резонатора (CKDIV8 = 1);
  • увеличено время запуска до 65 мс после включения напряжения питания (SUT1-0 = 11);
  • отключена генерация тактовой частоты микроконтроллера на выводе PB0 (CKOUT = 1);
  • включена возможность сброса PC6 (RSTDISBL=1) и программирования через последовательный интерфейс (SPIEN=0).

После программирования микроконтроллера отключите программатор от платы. Затем перемычками J1-J7 установите комбинацию, которая соответствует выбранному коэффициенту заполнения, и нажмите кнопку S1. На выходе генератора должен появиться прямоугольный сигнал с частотой 1 Гц и выбранной скважностью.

Читайте также: