# Проект 5: ШИМ (PWM) ![](../media/6fde6075ca685df3a27ac5365f901b94.png) #### Описание ШИМ (широтно-импульсная модуляция) — это распространённая технология электронного управления, которая регулирует среднее значение выходного напряжения или тока путём изменения ширины импульса. Проще говоря, она управляет выходом энергии, контролируя соотношение времени включения и выключения. В этом проекте будет использоваться плата Arduino и светодиод для управления яркостью светодиода с помощью ШИМ. Путём написания кода Arduino мы реализуем эффект градиента яркости светодиода, чтобы понять принцип работы и применение ШИМ. #### Аппаратное обеспечение 1\. Плата разработки UNO R3 (ch340) x1 2\. Светодиод x1 3\. Резистор 220 Ом x1 4\. Макетная плата x1 5\. Соединительные провода #### Принцип работы ШИМ Arduino (широтно-импульсная модуляция) используется для управления яркостью светодиодов, скоростью моторов и т.д. Она позволяет управлять аналоговыми устройствами, быстро переключая цифровые контакты, имитируя различные уровни напряжения. В этом проекте мы изучим, как работает ШИМ на Arduino. Основной принцип ШИМ — регулировать среднее значение выходного напряжения, изменяя ширину импульса. Цифровые контакты Arduino могут выдавать только высокий уровень (5В) или низкий уровень (0В). Но если быстро переключать между высоким и низким уровнем и контролировать длительность высокого уровня, можно имитировать напряжение между 0В и 5В. Отношение длительности высокого уровня к полному циклу называется коэффициентом заполнения. Чем больше коэффициент заполнения, тем выше выходное напряжение. ![IMG_256](../media/bbcfcb9ae56abb7e80ee587246fc4be9.GIF) Функция analogWrite() Arduino легко реализует ШИМ. Она принимает два параметра: номер контакта и коэффициент заполнения. Диапазон значения коэффициента заполнения — от 0 до 255, что соответствует 0%–100%. Например, analogWrite(9, 127) означает вывод ШИМ-сигнала с коэффициентом заполнения 50% на контакт 9. Для генерации ШИМ-сигналов Arduino использует модуль таймера/счётчика. Разные платы Arduino имеют разное количество таймеров/счётчиков. Каждый таймер/счётчик имеет несколько каналов, и каждый канал может независимо генерировать ШИМ. В Arduino UNO есть 3 таймера и 6 каналов ШИМ, расположенных на контактах 3, 5, 6, 9, 10 и 11. ![IMG_256](../media/30643a6d1685c7bd18879e5b993e135a.jpeg) Ядром таймера/счётчика является регистр счётчика (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. ![Img](../media/img-20260330185532.png) #### Пример кода ```cpp /* 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 } ``` #### Объяснение кода Код определяет переменные и константы для управления поведением светодиода: ```cpp 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()` инициализирует настройки: ```cpp void setup() { pinMode(ledPin, OUTPUT); // Set LED pin to output mode } ``` В `setup()` функция `pinMode()` устанавливает `ledPin` в режим вывода (`OUTPUT`), что необходимо для управления яркостью светодиода. Функция `loop()` управляет изменением яркости светодиода: ```cpp 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 миллисекунд. Эта задержка регулирует скорость изменения яркости; меньшие задержки делают изменения быстрее. #### Результат проекта После загрузки кода светодиод будет показывать эффект градиента. ![P5](../media/P5.gif) Яркость будет постепенно увеличиваться от 0 до 255, а затем постепенно уменьшаться до 0. Изменяя переменную `fadeAmount`, можно менять скорость изменения яркости.