Проект 5: ШИМ (PWM)

Описание
ШИМ (широтно-импульсная модуляция) — это распространённая технология электронного управления, которая регулирует среднее значение выходного напряжения или тока путём изменения ширины импульса. Проще говоря, она управляет выходом энергии, контролируя соотношение времени включения и выключения.
В этом проекте будет использоваться плата Arduino и светодиод для управления яркостью светодиода с помощью ШИМ. Путём написания кода Arduino мы реализуем эффект градиента яркости светодиода, чтобы понять принцип работы и применение ШИМ.
Аппаратное обеспечение
1. Плата разработки UNO R3 (ch340) x1
2. Светодиод x1
3. Резистор 220 Ом x1
4. Макетная плата x1
5. Соединительные провода
Принцип работы
ШИМ Arduino (широтно-импульсная модуляция) используется для управления яркостью светодиодов, скоростью моторов и т.д. Она позволяет управлять аналоговыми устройствами, быстро переключая цифровые контакты, имитируя различные уровни напряжения. В этом проекте мы изучим, как работает ШИМ на Arduino.
Основной принцип ШИМ — регулировать среднее значение выходного напряжения, изменяя ширину импульса. Цифровые контакты Arduino могут выдавать только высокий уровень (5В) или низкий уровень (0В). Но если быстро переключать между высоким и низким уровнем и контролировать длительность высокого уровня, можно имитировать напряжение между 0В и 5В. Отношение длительности высокого уровня к полному циклу называется коэффициентом заполнения. Чем больше коэффициент заполнения, тем выше выходное напряжение.
Функция analogWrite() Arduino легко реализует ШИМ. Она принимает два параметра: номер контакта и коэффициент заполнения. Диапазон значения коэффициента заполнения — от 0 до 255, что соответствует 0%–100%. Например, analogWrite(9, 127) означает вывод ШИМ-сигнала с коэффициентом заполнения 50% на контакт 9.
Для генерации ШИМ-сигналов Arduino использует модуль таймера/счётчика. Разные платы Arduino имеют разное количество таймеров/счётчиков. Каждый таймер/счётчик имеет несколько каналов, и каждый канал может независимо генерировать ШИМ. В Arduino UNO есть 3 таймера и 6 каналов ШИМ, расположенных на контактах 3, 5, 6, 9, 10 и 11.

Ядром таймера/счётчика является регистр счётчика (TCNTn). Он автоматически увеличивается на единицу каждый такт до достижения заданного максимального значения (TOP), после чего сбрасывается в ноль и начинает считать заново. Одновременно существует регистр сравнения (OCRnA/B), в котором хранится значение коэффициента заполнения. Каждый раз, когда значение счётчика совпадает с регистром сравнения, выход ШИМ меняет состояние (с высокого уровня на низкий или наоборот). Изменяя значения TOP и регистра сравнения, можно менять частоту и коэффициент заполнения ШИМ.
Функция analogWrite() автоматически настраивает режим работы таймера, обычно используется режим быстрого ШИМ (Fast PWM). В этом режиме счётчик непрерывно считает с фиксированной частотой и сравнивает значение с регистром сравнения. Как только счётчик достигает TOP, он сбрасывается в ноль, и выход ШИМ меняет состояние.
Например, если использовать тактовую частоту 16 МГц и 8-битный счётчик с TOP=255, а значение сравнения 127, то частота ШИМ будет 16МГц/(255+1)=62,5 кГц. ШИМ выдаёт высокий уровень, когда значение счётчика меньше 127, и низкий — когда больше. Поскольку 127/256=50%, получается ШИМ с коэффициентом заполнения 50%, что эквивалентно постоянному напряжению 2,5 В.
Итого, Arduino ШИМ быстро переключает уровень контакта через таймер и регулирует коэффициент заполнения, имитируя непрерывно изменяемое аналоговое напряжение на цифровом контакте. Это простой и гибкий способ управления яркостью светодиодов, скоростью моторов и т.д. Понимание принципа ШИМ поможет лучше применять эту технологию и создавать более интересные проекты на Arduino.
Схема подключения
Подключение такое же, как в Проекте 3.

Пример кода
/*
Electronics Learning Starter Kit for Arduino
Project 5
PWM
Edit By Keyes
*/
int ledPin = 9; // Define the pin of the LED
int brightness = 0; // Define the brightness variable of the LED
int fadeAmount = 5; // Define the step size of the brightness change
void setup() {
pinMode(ledPin, OUTPUT); // Set LED pin to output mode
}
void loop() {
analogWrite(ledPin, brightness); // Use analogWrite function to output PWM signal
brightness = brightness + fadeAmount; // Adjust brightness variable
if (brightness <= 0 || brightness >= 255) {
fadeAmount = -fadeAmount; // When the brightness reaches the maximum or minimum value, change the direction of the brightness change
}
delay(30); // Delay 30ms to control the speed of brightness change
}
Объяснение кода
Код определяет переменные и константы для управления поведением светодиода:
int ledPin = 9; // LED pin
int brightness = 0; // LED brightness
int fadeAmount = 5; // Brightness change step
Здесь ledPin установлен в 9, что означает, что светодиод подключён к цифровому контакту 9 на плате Arduino. brightness отслеживает текущую яркость светодиода, начиная с 0 (выключено). fadeAmount — это шаг изменения яркости, установленный в 5.
Функция setup() инициализирует настройки:
void setup() {
pinMode(ledPin, OUTPUT); // Set LED pin to output mode
}
В setup() функция pinMode() устанавливает ledPin в режим вывода (OUTPUT), что необходимо для управления яркостью светодиода.
Функция loop() управляет изменением яркости светодиода:
void loop() {
analogWrite(ledPin, brightness); // Use analogWrite to control LED brightness
brightness = brightness + fadeAmount; // Adjust brightness
if (brightness <= 0 || brightness >= 255) {
fadeAmount = -fadeAmount; // Reverse direction when reaching max/min
}
delay(30); // Delay to control brightness change speed
}
В loop() функция analogWrite() выводит ШИМ-сигнал на ledPin, контролируя яркость светодиода. Значение brightness изменяется на fadeAmount, создавая эффект плавного затухания.
Когда brightness достигает 0 или 255, fadeAmount меняет знак с помощью fadeAmount = -fadeAmount;, меняя направление изменения яркости. Это создаёт плавное переключение между максимальной и минимальной яркостью.
Наконец, delay(30); приостанавливает программу на 30 миллисекунд. Эта задержка регулирует скорость изменения яркости; меньшие задержки делают изменения быстрее.
Результат проекта
После загрузки кода светодиод будет показывать эффект градиента.

Яркость будет постепенно увеличиваться от 0 до 255, а затем постепенно уменьшаться до 0. Изменяя переменную fadeAmount, можно менять скорость изменения яркости.