Управление яркостью LED с ШИМ через кнопку на Arduino Mega
Компоненты и материалы
| Arduino Mega 2560 | 1 |
| Breadboard (макетная плата) | 1 |
| Перемычки (jumper wires) | 11 |
| LED (светодиоды) — 3 разных цвета | 3 |
| Тактическая кнопка 12 мм | 1 |
| Резистор 330 Ом | 4 |
Приложения и онлайн-сервисы
- Arduino IDE
О проекте
Проект демонстрирует плавное изменение яркости светодиодов (PWM) на Arduino. Разбит на три этапа:
- Базовое затухание (Fade Lights)
- Затухание с кнопкой (Fade Lights with Push Button)
- Улучшенная версия: прерывание затухания при отпускании кнопки (Fade Lights with button — improvement to delay)
1. Базовое затухание (Fade Lights)
В результате светодиоды плавно загораются и гаснут в порядке светофора: красный, желтый, зеленый, снова желтый.
Схема подключения

Светодиоды подключены к пинам 3, 6, 9 (поддерживающие ШИМ). Можно использовать другие ШИМ-пины, но нужно обновить код.
Код
Определяем пины:
int ledRed = 9;
int ledYellow = 6;
int ledGreen = 3;
В setup() настраиваем пины на выход:
void setup() {
pinMode(ledRed, OUTPUT);
pinMode(ledYellow, OUTPUT);
pinMode(ledGreen, OUTPUT);
}
В loop() реализуем плавное изменение яркости для каждого цвета через циклы for с analogWrite() и задержкой. Для удобства изменения скорости выносим задержку в константу:
const int fade = 10; // задержка в мс
void loop() {
// Красный
for (int i = 0; i <= 255; i++) { analogWrite(ledRed, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledRed, i); delay(fade); }
// Желтый
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
// Зеленый
for (int i = 0; i <= 255; i++) { analogWrite(ledGreen, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledGreen, i); delay(fade); }
// Желтый (обратно)
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
}
Переменная i меняется от 0 до 255 (нарастание яркости) и обратно (затухание). Задержка fade задает плавность.
2. Затухание с кнопкой (Fade Lights with Push Button)
Теперь последовательность запускается только при нажатии кнопки.
Схема

Добавлена кнопка на пин 7. Светодиоды остаются на тех же пинах.
Код
Добавляем пин кнопки и настройку входа:
int button = 7;
const int fade = 10;
void setup() {
pinMode(ledRed, OUTPUT);
pinMode(ledYellow, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(button, INPUT);
// Начальное состояние: зеленый включен
digitalWrite(ledRed, LOW);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, HIGH);
}
В loop() проверяем нажатие кнопки с простым антидребезгом (delay 15 мс). Если нажата — вызываем функцию fadeLights(). Если не нажата — восстанавливаем начальное состояние (зеленый включен).
void loop() {
if (digitalRead(button) == HIGH) {
delay(15); // антидребезг
if (digitalRead(button) == HIGH) {
fadeLights();
}
} else {
digitalWrite(ledRed, LOW);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, HIGH);
}
}
void fadeLights() {
// Затухание зеленого
for (int i = 255; i >= 0; i--) { analogWrite(ledGreen, i); delay(fade); }
// Нарастание и затухание желтого
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
// Нарастание и затухание красного
for (int i = 0; i <= 255; i++) { analogWrite(ledRed, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledRed, i); delay(fade); }
// Желтый снова
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
// Нарастание зеленого
for (int i = 0; i <= 255; i++) { analogWrite(ledGreen, i); delay(fade); }
}
Если последовательность не совпадает, проверьте правильность подключения пинов и кода.
3. Улучшение: прерывание затухания при отпускании кнопки
В предыдущей версии, если отпустить кнопку во время анимации, она продолжалась до конца. Теперь анимация останавливается сразу после отпускания кнопки, и восстанавливается начальное состояние (зеленый включен).
Схема
Схема не меняется.

Код
Удаляем константу fade, так как задержку реализуем пустым циклом с проверкой кнопки. В fadeLights() каждый шаг яркости сопровождается внутренним циклом, который опрашивает кнопку. Если кнопка отпущена (LOW), выполняется return — выход из функции.
int ledRed = 9;
int ledYellow = 6;
int ledGreen = 3;
int button = 7;
void setup() {
pinMode(ledRed, OUTPUT);
pinMode(ledYellow, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(button, INPUT);
digitalWrite(ledRed, LOW);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, HIGH);
}
void loop() {
if (digitalRead(button) == HIGH) {
delay(15);
if (digitalRead(button) == HIGH) {
fadeLights();
}
} else {
digitalWrite(ledRed, LOW);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, HIGH);
}
}
void fadeLights() {
// Зеленый затухает
for (int i = 255; i >= 0; i--) {
analogWrite(ledGreen, i);
for (int y = 0; y < 1000; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Желтый нарастает
for (int i = 0; i <= 255; i++) {
analogWrite(ledYellow, i);
for (int y = 0; y < 400; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Желтый затухает
for (int i = 255; i >= 0; i--) {
analogWrite(ledYellow, i);
for (int y = 0; y < 400; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Красный нарастает
for (int i = 0; i <= 255; i++) {
analogWrite(ledRed, i);
for (int y = 0; y < 1000; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Красный затухает
for (int i = 255; i >= 0; i--) {
analogWrite(ledRed, i);
for (int y = 0; y < 1000; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Желтый нарастает
for (int i = 0; i <= 255; i++) {
analogWrite(ledYellow, i);
for (int y = 0; y < 400; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Желтый затухает
for (int i = 255; i >= 0; i--) {
analogWrite(ledYellow, i);
for (int y = 0; y < 400; y++) {
if (digitalRead(button) == LOW) return;
}
}
// Зеленый нарастает
for (int i = 0; i <= 255; i++) {
analogWrite(ledGreen, i);
for (int y = 0; y < 1000; y++) {
if (digitalRead(button) == LOW) return;
}
}
}
Внутренние циклы (for y) создают задержку и одновременно проверяют кнопку. Количество итераций (1000, 400) подобрано экспериментально для нужной скорости. При отпускании кнопки функция немедленно завершается, и управление возвращается в loop(), где срабатывает ветка else (зеленый включен).
Исходные коды
1. Fade Lights (базовый)
int ledRed = 9; int ledYellow = 6; int ledGreen = 3; const int fade = 10;
void setup() { pinMode(ledRed, OUTPUT); pinMode(ledYellow, OUTPUT); pinMode(ledGreen, OUTPUT); }
void loop() {
for (int i = 0; i <= 255; i++) { analogWrite(ledRed, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledRed, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledGreen, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledGreen, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
}
2. Fade Lights with Push Button
int ledRed = 9; int ledYellow = 6; int ledGreen = 3; int button = 7; const int fade = 10;
void setup() {
pinMode(ledRed, OUTPUT); pinMode(ledYellow, OUTPUT); pinMode(ledGreen, OUTPUT);
pinMode(button, INPUT);
digitalWrite(ledRed, LOW); digitalWrite(ledYellow, LOW); digitalWrite(ledGreen, HIGH);
}
void loop() {
if (digitalRead(button) == HIGH) { delay(15); if (digitalRead(button) == HIGH) fadeLights(); }
else { digitalWrite(ledRed, LOW); digitalWrite(ledYellow, LOW); digitalWrite(ledGreen, HIGH); }
}
void fadeLights() {
for (int i = 255; i >= 0; i--) { analogWrite(ledGreen, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledRed, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledRed, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); delay(fade); }
for (int i = 0; i <= 255; i++) { analogWrite(ledGreen, i); delay(fade); }
}
3. Fade Lights with Push Button (improvement to delay)
int ledRed = 9; int ledYellow = 6; int ledGreen = 3; int button = 7;
void setup() {
pinMode(ledRed, OUTPUT); pinMode(ledYellow, OUTPUT); pinMode(ledGreen, OUTPUT);
pinMode(button, INPUT);
digitalWrite(ledRed, LOW); digitalWrite(ledYellow, LOW); digitalWrite(ledGreen, HIGH);
}
void loop() {
if (digitalRead(button) == HIGH) { delay(15); if (digitalRead(button) == HIGH) fadeLights(); }
else { digitalWrite(ledRed, LOW); digitalWrite(ledYellow, LOW); digitalWrite(ledGreen, HIGH); }
}
void fadeLights() {
for (int i = 255; i >= 0; i--) { analogWrite(ledGreen, i); for (int y = 0; y < 1000; y++) if (digitalRead(button) == LOW) return; }
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); for (int y = 0; y < 400; y++) if (digitalRead(button) == LOW) return; }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); for (int y = 0; y < 400; y++) if (digitalRead(button) == LOW) return; }
for (int i = 0; i <= 255; i++) { analogWrite(ledRed, i); for (int y = 0; y < 1000; y++) if (digitalRead(button) == LOW) return; }
for (int i = 255; i >= 0; i--) { analogWrite(ledRed, i); for (int y = 0; y < 1000; y++) if (digitalRead(button) == LOW) return; }
for (int i = 0; i <= 255; i++) { analogWrite(ledYellow, i); for (int y = 0; y < 400; y++) if (digitalRead(button) == LOW) return; }
for (int i = 255; i >= 0; i--) { analogWrite(ledYellow, i); for (int y = 0; y < 400; y++) if (digitalRead(button) == LOW) return; }
for (int i = 0; i <= 255; i++) { analogWrite(ledGreen, i); for (int y = 0; y < 1000; y++) if (digitalRead(button) == LOW) return; }
}
Схемы


Производственный процесс
- Создание игры в реальном времени на Arduino Nano с гироскопом MPU-6050 и OLED-дисплеем
- Надежная система учета рабочего времени на Arduino с RFID и Python
- Проект с датчиком DHT11: индикация температуры светодиодами и пьезо-динамиком на Arduino
- Создание ультразвукового левитатора на Arduino: пошаговое руководство
- Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
- Автоматическая система полива растений на Arduino — уходи в отпуск спокойно
- Простой ИК-датчик препятствий на Arduino: ИК-светодиод и фотодиод
- Find Me: Умный поисковик вещей на Arduino и Bluetooth
- Измерение массы Земли с Arduino: пошаговое руководство по DIY
- Управление 4-пиновым PWM-вентилятором 25 кГц на Arduino Uno — Сборка, код и тесты