Программная ШИМ (PWM)

ШИМ - Широтно импульсная модуляция
PWM - Pulse Width Modulation (т.е. то же самое, что и ШИМ)

Что такое ШИМ и зачем он нужен?

http://ru.wikipedia.org/wiki/PWM

Зачем нужен программный ШИМ?

Затем, что на самом AVR (Atmega) каналов шим 1-2, что часто не хватает для того, что надо.

Пусть у нас есть 3 (три) светодиода и яркостью каждого их них мы хотим управлять индивидуально. Встроенных ШИМ каналов таймера не хватит. И, вообще, может мы еще какой-то особый контроль хотим осуществлять над каждым из них. Поэтому сажаем их на обычные ноги (в примере PORTC ноги 3,4,5) и управляем программно.

Схема:

Дополнительная информация по поводу подключения: http://www.radiokot.ru/start/mcu_fpga/avr/05/ и в даташите к контроллеру.

Расчет резистора для светодиода:

Питание: 5В. Падение напряжения на светодиоде можно считать 1.5В. Тока на светодиоде должен быть не более 20мА (некоторые поспорят, что надо 15мА, но мне нравится поярче).
По закону Ома: I=U/R, R=U/I=(5-1.5)/0.02=175 Ом. Я поставил резисторы R1,R2 и R2 - 220 Ом.

Алгоритм

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

Во-первых надо определить с двумя вещами: с какой частотой будут моргать светодиоды, чтобы не было видно этого моргания и, второе, сколько уровней яркости может иметь светодиод.

По уровням яркости пусть будет 256. 0 - выключен полностью, 255 - включен полностью (т.е. ШИМ канал находится в логической единице все время, т.е. duty cycle = 100%.

Что такое duty cycle: http://en.wikipedia.org/wiki/Duty_cycle

Однако, сейчас я малек запутаю вас.

Суть в том, что у нас ПЛЮС диода на схеме тыкнут на прямую на питание, а минус идет через резистор к ноге (где резистор - не важно, важно что к ноге МК). Поэтому светодиод светится, когда на ноге МК низкий уровень, т.е. ноль, т.е. нога внутри МК прокинута на GND, т.е. на ЗЕМЛЮ. Это значит, что на самом деле 0 и 1 в ШИМ должны быть инвертированы. Т.е. чем дольше в сигнале будет 0 по отношению к 1, тем ярче будет диод.

И так, уровней яркости 256.

О каком моргании идет речь? Суть в том, что если мы должны подать ШИМ сигнал на много много диодов и делаем это последовательно на каждый, то после вывода сигнала на первый диод надо вернуться к выводу сигнала на него же за такое время, чтобы:

  1. успеть сформировать полноценный ШИМ сигнал,
  2. не прошло более 1/25 секунды, иначе будет заметное мигание светодиода,
  3. между отрезками сигнала ШИМ не было заметных пауз в генерации шим, т.е. чтобы ШИМ сигнал НЕ БЫЛ ИСКАЖЕН.

Вот пример искажения ШИМ сигнала:

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

И так, вот исходный код (для AVR studio, т.е. gcc):

Принцип работы программы

Есть счетчик отрезков времени - scancount. Максимальное значение этого счетчика - это количество уровней яркости минус 1. Каждый оборот цикла он увеличивается на единицу, потом переваливает за 255 и снова становится 0. В каждом обороте цикла происходит установка сигнала для каждого светодиода. Если счетчик меньше больше или равен уровню яркости, то выключаем диод. Если счетчик меньше уровня яркости заданного для диода - то включаем это диод. И как каждый цикл. Например, если уровень яркости равен 0, то счетчик всегда будет равен или более нуля и диод всегда будет выключен. Если уровень яркости 255, то счетчик будет меньше этого значения 254 из 255 оборотов счетчика и будет гореть практически в полную силу. Если яркость установлена в 50, то 50 первых оборотом цикла диод будет включен, а 206 оставшихся оборотов - выключен, т.е. на него будет подана 50/256 тока от максимума.

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

Надо также знать, что зависимость яркости от тока у светодиодов НЕ ЛИНЕЙНАЯ. Т.е. 128 не в два раза тусклее, чем 255 и не в 2 раза ярче, чем 64.

За сколько проворачивается весь цикл со всеми диодами, нас здесь мало интересует, так как понятно, что на чистоте 1Мгц (именно на ней у меня работает МК), это будет достаточно быстро, чтобы глаз не видел никаких мерцаний.

Фото сборки:

нажмите на фото, чтобы увеличить

И вот видео работы: (avi, divx, 3MB)
Видео плохо показывает процесс перехода яркости, так как матрица фотоаппарата не обладает такой инерцией зрения, как человеческий глаз, но, в целом, процесс виден.


(C)1999-2021 Артем Кучин
Email: artem@artem.ru
На письма без темы или без имени отправителя не отвечаю

При использовании материалов ссылка на сайта www.artem.ru обязательна! Автор оставляет за собой право отказать в праве использования материалов на безвозмездной основе без объяснения причин. Материалы сайта защищены законом об авторских и смежных правах.

Цена домена: 1 500 000 руб.