Управление яркостью светодиода
Ср, 25/05/2011 — 01:55 | by Alexander
Простой пример управления яркостью светодиода с помощью функции analogWrite(). AnalogWrite() использует широтно-импульсную модуляцию (ШИМ). Эффект изменения яркости достигается за счет очень быстрого, повторяющегося переключения напряжения на выходе с 0В на +5В (для некоторых плат стандартное напряжение +3.3В).
Необходимые компоненты
- контроллер Arduino
- макетная плата
- светодиод
- резистор 220 Ом
Подключение
Подключаем анод (обычно длинная ножка) светодиода через резистор сопротивлением 220 Ом к выходу номер 9 (pin 9). Катод (короткая ножка) подсоединяем напрямую к земле (Grd).
Схема
Код
В секции setup() кода устанавливаем режим выхода для вход/выхода 9 (pin 9).
Функция analogWrite(), которая циклически вызывается в теле скетча, принимает два аргумента: номер выхода и значение ширины импульса ШИМ в диапазоне от 0 до 255.
Для управление яркостью светодиода, его плавного зажигания и плавного затухания, мы будем изменять значение ширины импульса, передаваемое в функцию analogWrite(). При значение 0 светодиод выключен, при 255 светодиод светит на полную яркость. В приведенном ниже скетче ширина импульса задается переменной brightness. Шаг изменения этого значения задан переменной fadeAmount.
Для плавного изменения яркости мы вводим задержку в конце главного цикла (тела) скетча — delay(30).
/*
Пример управления яркостью светодиода
на выходе 9 контроллера Arduino
функцией analogWrite().
*/
int brightness = 0; // уставливаем начально значение яркости
int fadeAmount = 5; // шаг приращения/убывания яркости
void setup() {
// устанваливаем пин 9 в режим выхода
pinMode(9, OUTPUT);
}
void loop() {
// устанавливаем значение широты импульса на выходе 9
// задавая яркость светодиода
analogWrite(9, brightness);
// измением значение в переменной для яркости
brightness = brightness + fadeAmount;
// при достижение крайних значений для яркости
// меняем знак переменной шага приращения/убывания яркости
if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ;
}
// делаем паузу для достижения плавного наращивания/убывания яркости
delay(30);
}
Смотрите также
- setup()
- loop()
- analogWrite()
- int
- for
- ШИМ
- Blink: Пример моргания светодиодом
Сегодня мы будем управлять яркостью светодиода с помощью ШИМ каналов.
Схема подключения на макетной плате:

Интенсивность свечения будет регулироваться от 0 до 254 едениц, где 0 — вчетодиод выклчюен, а 254 — горит максимально (Например при 127 яркость будет на 50%).
Для этого нам понабодится:
- Ардуино
- Бредборд
- Провода
- Светодиод
- Кнопки
- Резисторы
Для подключения светодиода необходимо использовать резистор. Номинал резистора подбирается для каждого светодиода индивидуально, в зависимости от его рабочего напряжения и тока. Обычно резистор в 1 кОм. Можно использовать как универсальный вариант.
Управление реализуем с помощью двух тактовых кнопок. Подключать тактовые кнопки необходимо через подтягивающие резисторы (К земле, GND), для защиты от статических наводок (Ложные срабатывания кнопок от одного лишь касания и тд.). Номинал может быть различный. Рекомендуем вам использовать резисторы 10 кОм — 100 кОм.
Код программы:
int led = 11; // Номер Pin к которому подключен диод
int brightness =0; // Переменная в которой хранится уровень яркости (От 0 до 254)
int buttonPlus=9; // Номер Pin к которому подключена кнопка
int buttonMinus=10; // Номер Pin к которому подключена кнопка -
void setup() {
pinMode(led, OUTPUT); // Порт 11 (led) будет работать как Выход.
}
void loop() { // Этот цикл будет выполняться бесконечное количество раз.
if (digitalRead(buttonPlus) == HIGH) {
brightness += 5;
} // Делаем проверку, если вход под номером 9 (buttonPlus) имеет состояние 5 В. Увеличиваем значение переменной яркости на 5 единиц.
if (digitalRead(buttonMinus) == HIGH) {
brightness -= 5;
} // Делаем проверку, если вход под номером 10 (buttonMinus) имеет состояние 5 В. Уменьшаем значение переменной яркости на 5 единиц.
brightness = constrain(brightness, 0, 254); // Эта функция контролирует, что бы переменная brightness не стала больше 254 и меньше 0, если значение вылазит за границу то функция 0 или 254
analogWrite(led, brightness); // Устанавливаем состояние яркости для светодиода
delay(50); // Пауза 50 миллисекунд.
}
Обычные светодиоды
Светодиод – простейший индикатор, который можно использовать для отладки кода: его можно включить при срабатывании условия или просто подмигнуть. Но для начала его нужно подключить.
Подключение светодиода
Светодиод – это устройство, которое питается током, а не напряжением. Как это понимать? Яркость светодиода зависит от тока, который через него проходит. Казалось бы, достаточно знания закона Ома из первого урока в разделе, но это не так!
- Светодиод в цепи нельзя заменить “резистором”, потому что он ведёт себя иначе, нелинейно.
- Светодиод полярен, то есть при неправильном подключении он светиться не будет.
- Светодиод имеет характеристику максимального тока, на котором может работать. Для обычных 3 и 5 мм светодиодов это обычно 20 мА.
- Светодиод имеет характеристику падение напряжения (Forward Voltage), величина этого падения зависит от излучаемого цвета. Цвет излучается кристаллом, состав которого и определяет цвет. У красных светодиодов падение составляет ~2.5 вольта, у синих, зелёных и белых ~3.5 вольта. Более точную информацию можно узнать из документации на конкретный светодиод. Если документации нет – можно пользоваться вот этой табличкой, тут даны минимальные значения:

R = (Vcc - Vdo) / I, где Vcc это напряжение питания, Vdo – напряжение падения (зависит от светодиода), I – ток светодиода, а R – искомое сопротивление резистора. Посчитаем резистор для обычного 5 мм светодиода красного цвета при питании от 5 Вольт на максимальной яркости (2.5 В, 20 мА): (5-2.5)/0.02=125 Ом. Для синего и зелёного цветов получится 75 Ом. Яркость светодиода нелинейно зависит от тока, поэтому “на глаз” при 10 мА яркость будет такая же, как на 20 мА, и величину сопротивления можно увеличить. А вот уменьшать нельзя, как и подключать вообще без резистора. В большинстве уроков и проектов в целом для обычных светодиодов всех цветов ставят резистор номиналом 220 Ом. С резистором в 1 кОм светодиод тоже будет светиться, но уже заметно тусклее. Таким образом при помощи резистора можно аппаратно задать яркость светодиода. Как определить плюс (анод) и минус (катод) светодиода? Плюсовая нога длиннее, со стороны минусовой ноги бортик чуть срезан, а сам электрод внутри светодиода – крупнее:
Мигаем
Мигать светодиодом с Ардуино очень просто: подключаем катод к GND, а анод – к пину GPIO. Очень многие уверены в том, что “аналоговые” пины являются именно аналоговыми, но это не так: это обычные цифровые пины с возможностью оцифровки аналогового сигнала. На плате Nano пины A0-A5 являются цифровыми и аналоговыми одновременно, а вот A6 и A7 – именно аналоговыми, то есть могут только читать аналоговый сигнал. Так что подключимся к A1, настраиваем пин как выход и мигаем!
void setup() {
pinMode(A1, OUTPUT);
}
void loop() {
digitalWrite(A1, HIGH);
delay(500);
digitalWrite(A1, LOW);
delay(500);
}
Как избавиться от delay() в любом коде я рассказывал вот в этом уроке.
Мигаем плавно
Как насчёт плавного управления яркостью? Вспомним урок про ШИМ сигнал и подключим светодиод к одному из ШИМ пинов (на Nano это D3, D5, D6, D9, D10, D11). Сделаем пин как выход и сможем управлять яркостью при помощи ШИМ сигнала! Читай урок про ШИМ сигнал. Простой пример с несколькими уровнями яркости:
void setup() {
pinMode(3, OUTPUT);
}
void loop() {
analogWrite(3, 10);
delay(500);
analogWrite(3, 100);
delay(500);
analogWrite(3, 150);
delay(500);
analogWrite(3, 200);
delay(500);
analogWrite(3, 255);
delay(500);
}
Подключим потенциометр на A0 и попробуем регулировать яркость с его помощью:
void setup() {
pinMode(3, OUTPUT);
}
void loop() {
// analogRead(0) / 4 == 0... 255
analogWrite(3, analogRead(0) / 4);
delay(100);
}
Как вы можете видеть, все очень просто. Сделаем ещё одну интересную вещь: попробуем плавно включать и выключать светодиод, для чего нам понадобится цикл из урока про циклы.
void setup() {
pinMode(3, OUTPUT);
}
void loop() {
for (int i = 0; i < 255; i++) {
analogWrite(3, i);
delay(20);
}
for (int i = 255; i > 0; i--) {
analogWrite(3, i);
delay(20);
}
}
Плохой пример! Алгоритм плавного изменения яркости блокирует выполнение кода. Давайте сделаем его на таймере аптайма.
void setup() {
pinMode(3, OUTPUT);
}
uint32_t tmr;
int val = 0;
bool dir = true;
void loop() {
if (millis() - tmr >= 20) {
tmr = millis();
if (dir) val++; // увеличиваем яркость
else val--; // уменьшаем
if (val >= 255 || val <= 0) dir = !dir; // разворачиваем
analogWrite(3, val);
}
}
Теперь изменение яркости не блокирует выполнение основного цикла, но и остальной код должен быть написан таким же образом, чтобы не блокировать вызовы функции изменения яркости! Ещё одним вариантом может быть работа по прерыванию таймера, см. урок.
Светодиод будет мигать не очень плавно: яркость будет нарастать слишком резко и практически не будет меняться. Связано это с тем, что человеческий глаз воспринимает яркость нелинейно, а мы управляем ей линейно. Для более плавного ощущения яркости используется коррекция по CRT гамме, которая переехала из этого урока в отдельный урок по миганию светодиодом по CRT гамме в блоке алгоритмов. Изучи обязательно!
Ещё один момент: если подключить светодиод наоборот, к VCC, то яркость его будет инвертирована: 255 выключит светодиод, а 0 – включит, потому что ток потечет в другую сторону:
Светодиодные ленты
Светодиодная лента представляет собой цепь соединённых светодиодов. Соединены они не просто так, например обычная 12V лента состоит из сегментов по 3 светодиода в каждом. Сегменты соединены между собой параллельно, то есть на каждый приходят общие 12 Вольт. Внутри сегмента светодиоды соединены последовательно, а ток на них ограничивается общим резистором (могут стоять два для более эффективного теплоотвода): 
Подключаем к Arduino
Здесь всё очень просто: смотрите предыдущий урок по управлению нагрузкой постоянного тока. Управлять можно через реле, транзистор или твердотельное реле. Нас больше всего интересует плавное управление яркостью, поэтому продублирую схему с полевым транзистором: 
Управление
Подключенная через транзистор лента управляется точно так же, как светодиод в предыдущей главе, то есть все примеры кода с миганием, плавным миганием и управление потенциометром подходят к этой схеме. Про RGB и адресные светодиодные ленты мы поговорим в отдельных уроках.
Питание и мощность
Светодиодная лента потребляет немаленький ток, поэтому нужно убедиться в том, что выбранный блок питания, модуль или аккумулятор справится с задачей. Но сначала обязательно прочитайте урок по закону Ома! Потребляемая мощность светодиодной ленты зависит от нескольких факторов:
- Яркость. Максимальная мощность будет потребляться на максимальной яркости.
- Напряжение питания (чаще всего 12V). Также бывают 5, 24 и 220V ленты.
- Качество, тип и цвет светодиодов: одинаковые на вид светодиоды могут потреблять разный ток и светить с разной яркостью.
- Длина ленты. Чем длиннее лента, тем больший ток она будет потреблять.
- Плотность ленты, измеряется в количестве светодиодов на метр. Бывает от 30 до 120 штук, чем плотнее – тем больший ток будет потреблять при той же длине и ярче светить.
Лента всегда имеет характеристику мощности на погонный метр (Ватт/м), указывается именно максимальная мощность ленты при питании от номинального напряжения. Китайские ленты в основном имеют чуть меньшую фактическую мощность (в районе 80%, бывает лучше, бывает хуже). Блок питания нужно подбирать так, чтобы его мощность была больше мощности ленты, т.е. с запасом как минимум на 20%.
- Пример 1: нужно подключить 4 метра ленты с мощностью 14 Ватт на метр, лента может работать на максимальной яркости. 14*4 == 56W, с запасом 20% это будет 56*1.2 ~ 70W, ближайший блок питания в продаже будет скорее всего на 100W.
- Пример 2: берём ту же ленту, но точно знаем, что яркость во время работы не будет больше половины. Тогда можно взять блок на 70 / 2 == 35W.
Важные моменты по току и подключению:
- Подключение: допустим, у нас подключено ленты на 100W. При 12 Вольтах это будет 8 Ампер – весьма немаленький ток! Ленту нужно располагать как можно ближе к блоку питания и подключать толстыми (2.5 кв. мм и толще) проводами. Также при создании освещения есть смысл перейти на 24V ленты, потому что ток в цепи будет меньше и можно взять более тонкие провода: если бы лента из прошлого примера была 24-Вольтовой, ток был бы около 4 Ампер, что уже не так “горячо”.
- Дублирование питания: лента сама по себе является гибкой печатной платой, то есть ток идёт по тонкому слою меди. При подключении большой длины ленты ток будет теряться на сопротивлении самой ленты, и чем дальше от точки подключения – тем слабее она будет светить. Если требуется максимальная яркость на большой длине, нужно дублировать питание от блока питания дополнительными проводами, или ставить дополнительные блоки питания вдоль ленты. Дублировать питание рекомендуется каждые 2 метра, потому что на такой длине просадка яркости становится заметной уже почти на всех лентах.
- Охлаждение: светодиоды имеют не 100% КПД, плюс ток в них ограничивается резистором, и как результат – лента неслабо греется. Рекомендуется приклеивать яркую и мощную ленту на теплоотвод (алюминиевый профиль). Так она не будет отклеиваться и вообще проживёт гораздо дольше.
Видео
Полезные страницы
- Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
- Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
- Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
- Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
- Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
- Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
- Поддержать автора за работу над уроками
- Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])
Прочтите перед выполнением
Список деталей для эксперимента
Для дополнительного задания
-
еще 1 светодиод
-
еще 1 резистор номиналом 220 Ом
-
еще 2 провода
Принципиальная схема

Схема на макетке

Обратите внимание
-
Мы подключили «землю» светодиода и переменного резистора (потенциометра) к длинной рельсе «-» макетной платы, и уже ее соединили с входом GND микроконтроллера. Таким образом мы использовали меньше входов и от макетки к контроллеру тянется меньше проводов.
-
Подписи «+» и «-» на макетке не обязывают вас использовать их строго для питания, просто чаще всего они используются именно так и маркировка нам помогает
-
Не важно, какая из крайних ножек потенциометра будет подключена к 5 В, а какая к GND, поменяется только направление, в котором нужно крутить ручку для увеличения напряжения. Запомните, что сигнал мы считываем со средней ножки
-
Для считывания аналогового сигнала, принимающего широкий спектр значений, а не просто 0 или 1, как цифровой, подходят только порты, помеченные на плате как «ANALOG IN» и пронумерованные с префиксом
A. Для Arduino Uno — это A0-A5.
Скетч
- p030_pot_light.ino
-
// даём разумные имена для пинов со светодиодом // и потенциометром (англ potentiometer или просто «pot») #define LED_PIN 9 #define POT_PIN A0 void setup() { // пин со светодиодом — выход, как и раньше... pinMode(LED_PIN, OUTPUT); // ...а вот пин с потенциометром должен быть входом // (англ. «input»): мы хотим считывать напряжение, // выдаваемое им pinMode(POT_PIN, INPUT); } void loop() { // заявляем, что далее мы будем использовать 2 переменные с // именами rotation и brightness, и что хранить в них будем // целые числа (англ. «integer», сокращённо просто «int») int rotation, brightness; // считываем в rotation напряжение с потенциометра: // микроконтроллер выдаст число от 0 до 1023 // пропорциональное углу поворота ручки rotation = analogRead(POT_PIN); // в brightness записываем полученное ранее значение rotation // делённое на 4. Поскольку в переменных мы пожелали хранить // целые значения, дробная часть от деления будет отброшена. // В итоге мы получим целое число от 0 до 255 brightness = rotation / 4; // выдаём результат на светодиод analogWrite(LED_PIN, brightness); }
Пояснения к коду
-
С помощью директивы
#defineмы сказали компилятору заменять идентификаторPOT_PINнаA0— номер аналогового входа. Вы можете встретить код, где обращение к аналоговому порту будет по номеру без индексаA. Такой код будет работать, но во избежание путаницы с цифровыми портами используйте индекс. -
Переменным принято давать названия, начинающиеся со строчной буквы.
-
Чтобы использовать переменную, необходимо ее объявить, что мы и делаем инструкцией:
int rotation, brightness;
-
Для объявления переменной необходимо указать ее тип, здесь —
int(от англ. integer) — целочисленное значение в диапазоне от -32 768 до 32 767, с другими типами мы познакомимся позднее -
Переменные одного типа можно объявить в одной инструкции, перечислив их через запятую, что мы и сделали
-
Функция
analogRead(pinA)возвращает целочисленное значение в диапазоне от 0 до 1023, пропорциональное напряжению, поданному на аналоговый вход, номер которого мы передаем функции в качестве параметраpinA -
Обратите внимание, как мы получили значение, возвращенное функцией
analogRead(): мы просто поместили его в переменнуюrotationс помощью оператора присваивания=, который записывает то, что находится справа от него в ту переменную, которая стоит слева
Вопросы для проверки себя
-
Можем ли мы при сборке схемы подключить светодиод и потенциометр напрямую к разным входам GND микроконтроллера?
-
В какую сторону нужно крутить переменный резистор для увеличения яркости светодиода?
-
Что будет, если стереть из программы строчку
pinMode(LED_PIN, OUTPUT)? строчкуpinMode(POT_PIN, INPUT)? -
Зачем мы делим значение, полученное с аналогового входа перед тем, как задать яркость светодиода? что будет, если этого не сделать?
Задания для самостоятельного решения

Введение. Понятие ШИМ
Широко-импульсная модуляция (сокращенно ШИП) – это
техника, используемая для преобразования аналогового сигнала в цифровой. Ведь компьютер
не может выдавать аналоговый сигнал: выходы цифровой техники могут принимать
только одно из двух значений – например, 0V или 5V. Поэтому используется счетчик высокой точности для кодирования
аналогового сигнала в ШИМ-сигнал, которые – уже цифровой, поскольку в любой
момент времени он принимает значение либо 5V (ВКЛ), либо 0V
(ВЫКЛ). Напряжение подается на аналоговую нагрузку (например, светодиод, или
сервопривод) в виде повторяющейся последовательности ВКЛ и ВЫКЛ. Получаемое выходное
напряжение вычисляется по продолжительности сигналов ВКЛ и ВЫКЛ, по следующей формуле:
Выходное напряжение = (Время ВКЛ / время импульса) *
максимальное напряжение.
Взгляните на рисунок ниже для лучшего понимания.
ШИМ имеет множество применений, например:
- регулирование яркость свечения ламп,
- скорости вращения мотора,
- генерация звука и т.д.
ШИМ имеет 3 параметра:
- Период
- Скважность
- Величина

У Ардуино 6 портов, поддерживающие ШИМ: это цифровые пины
3, 5, 6, 9, 10 и 11.
В предыдущем примере мы подключили LED к цифровому
пину. Теперь мы будем менять его яркость с помощью ШИМ-сигнала.
Часть 1. Управление яркостью светодиода
Необходимые компоненты
- LED
M5 - 220R
Схема
Соберем вот эту схему:
Обратите внимание, что мы подключаем LED к цифровому
пину 11, которые поддерживает ШИМ. Если подключить к пину 12, то желаемого результата
мы не получим.
Скетч
/*******************************************************
* (C) jarduino.ru 2019
* Изучение ардуино через опыты.
*
* Опыт №3.1. Управление яркостью светодиода
*
* ****************************************************/
// Глобальные константы и переменные
const int pinLed = 11; // порт для светодиода
const int nDelay = 2; // задержка в мсек. между изменением яркости
const int nLedMin = 0; // минимальная яркость
// настройка платы
void setup()
{
pinMode(pinLed, OUTPUT);
}
// основной цикл
void loop()
{
static int i = nLedMin; // статическая переменная для хранения текущей яркости светодиода
// постепенной увеличиваем яркость светодиода:
while (i < 255)
{
analogWrite(pinLed, i);
delay(nDelay);
++i;
}
// постепенно уменьшаем яркость светодиода:
while (i > nLedMin)
{
analogWrite(pinLed, i);
delay(nDelay);
--i;
}
}
Результат
Часть 2. Управление яркостью с помощью потенциометра
Необходимые компоненты
- Дополнительно на понадобится потенциометр
Схема
Добавим на схему потенциометр:
Среднюю ногу потенциометра мы подключаем к аналоговому входу A0.
Скетч
/*******************************************************
* (C) jarduino.ru 2019
* Изучение ардуино через опыты.
*
* Опыт №3.2 Управление яркостью светодиода с помощью потенциометра
*
* ****************************************************/
// Глобальные константы и переменные
const int pinLed = 11; // порт для светодиода
const int pinPot = A0; // порт для светодиода
// настройка платы
void setup()
{
Serial.begin(9600); // инициализировать последовательные порт
pinMode(pinLed, OUTPUT); // установть пин светодиода в режим вывода
// аналоговые пины по умолчанию уже стоят в режиме ввода.
}
// основной цикл
void loop()
{
static int nValOld = 0;
static int nVal; // статическая переменная для хранения текущей яркости светодиода
nVal = analogRead(pinPot);
// выведем значение nVal в окно отладки, а чтобы
// не реагировать на помехи, будет выводить значение только если оно изменилось хотя бы на 3:
if (abs(nValOld - nVal) > 3) {
Serial.println(nVal);
nValOld = nVal;
}
analogWrite(pinLed, nVal / 4);
delay(10); // пауза в 0.01 сек.
}
Результат
Когда вы вращаете ручку потенциометра, вы видите в
мониторе последовательно порта как меняется напряжение и яркость светодиода в соответствии
с ним.
Объяснение
В программе мы считываем аналоговое значение, задаваемое
потенциометром, и применяем его к цифровому ШИМ порту, к которому подключен
светодиод. В соответствии с изменением ШИМ-сигналом, меняется и яркость
светодиода.
Обратите внимание, что максимальное значение для порта ШИМ – это 255, а аналогового порта – 1024. Поэтому считанное значение приходится делить на 4.
Заключение
В этом примере мы показали как использовать ШИМ, изменять
напряжение на цифровом выходе, использовать потенциометр для управления нагрузкой.
Пины Arduino могут выдавать напряжение ровно 5 вольт. Что делать, если нужно меньше? На выручку приходит широтно-импульсная модуляция (ШИМ), управление которой производится через функцию analogWrite().
Меньшее значение напряжения может пригодиться, чтобы подключенный к Arduino светодиод горел тусклее.
Посмотрим подробнее, что такое ШИМ и как это работает.
Фокус с лампочкой
Представим, что к Arduino подключена пьезопищалка, которая каждый раз во время исполнения программы издает прерывистый, щелкающий звук.
Мы отчетливо слышим, как она включается и выключается. Что с ней происходит?
В плату был загружен вот такой код:
void setup() {
pinMode(6, OUTPUT);
}
void loop() {
digitalWrite(6, HIGH);
delay(5);
digitalWrite(6, LOW);
delay(5);
}
Как видите, мы подаем напряжение, ждем 5 миллисекунд и на следующие 5 миллисекунд отключаем его.
Чередование промежутков, когда есть напряжение и нет, создает колебания пьезопластины. Это очень похоже на то, как если бы мы дергали струну и отпускали. В результате слышим издаваемый динамиком прерывистый звук.
Можно предположить, что если в данной схеме заменить пьезопищалку на светодиод, то мы увидим мигание. Но это не так. Давайте разбираться, почему.
Дело в том, что 5 мс — это очень маленькое время. Одна миллисекунда в тысячу раз быстрее секунды, и человеческий глаз просто не успевает заметить мигания. Наблюдателю кажется, что свет горит непрерывно.
Эксперименты со скважностью
Здесь стоит поговорить о такой характеристике переменного сигнала как скважность. Этим термином обозначается отношение длительности включения и отключения напряжения (T) к отрезку времени, когда напряжение подается (t1).
Другими словами, скважность показывает соотношение времени, когда напряжение подается и когда оно нулевое.
Перебирая различные комбинации задержек в нашей программе, можно заметить, что с сокращением времени подачи напряжения — яркость светодиода снижается.
Пример таких значений можно увидеть в приведенном ниже коде (лампочка здесь горит с меньшей яркостью, чем до этого):
void setup () {
pinMode(6, OUTPUT);
}
void loop () {
digitalWrite(6, HIGH);
delay(1); // Всего одна миллисекунда!
digitalWrite(6, LOW);
delay(19);
}
Верно и обратное. Если подавать напряжение дольше, а выключать пин на меньшее время, то светодиод станет ярче.
Если бы сигнал не прерывался, то все 100% времени подключенный к плате элемент получал бы максимальное напряжение.
Добавляя паузы, мы снижаем действие напряжения. В изначальном примере, где чередование было задано как 5 мс отключения после 5 мс работы, светодиоду передавалась только половина от максимального напряжения в 5 вольт — то есть 2,5 вольта.
Функции генерации переменного сигнала
Для получения различных уровней напряжения совсем не обязательно подбирать и прописывать паузы самостоятельно — можно воспользоваться специальными функциями.
Одна из них — tone(). С ее помощью получают звук заданной частоты.
Подробнее об этой функции можно почитать в посвященной ей статье. Сейчас нас интересует только то, что она генерирует сигнал с одинаковыми промежутками подачи и отключения напряжения (см. Рис. 2).
Для широтно-импульсной модуляции используется функция analogWrite(). Она позволяет подавать нужное напряжение на указанный пин.
В отличие от tone(), функция analogWrite() работает на постоянной частоте 490Hz.
Запись функции выглядит следующим образом:
analogWrite(X, Y);
В скобках указаны два параметра, которые принимает функция. Х означает номер пина, на который необходимо подавать напряжение, Y — уровень напряжения.
Функция будет генерировать равномерный сигнал с заданными параметрами рабочего цикла, пока не последует новый вызов analogWrite() на тот же пин, но с другим значением Y.
Уровень напряжения функция понимает в «зашифрованном» виде. Принимаются значения от 0 до 255.
0 вольт — это просто 0, а 5 вольт, то есть максимум, соответствует цифре 255.
Пример использования функции analogWrite():
void setup() {
pinMode(10, OUTPUT);
}
void loop() {
analogWrite(10, 255); // Подаем напряжение 5 В на 10-й пин
delay(500);
analogWrite(10, 0); // Подаем напряжение 0 В на 10-й пин
delay(500);
analogWrite(10, 128); // Подаем напряжение 2,5 В на 10-й пин
delay(1000);
analogWrite(10, 50); // Подаем напряжение 1 В на 10-й пин
delay(1500);
}
Эта команда очень похожа на digitalWrite() при установленном режиме OUTPUT для выбранного пина. Отличие в том, что вместо HIGH, что означало просто включение пина на 5 вольт, здесь указывается уровень напряжения.
Курсы Робикс, в которых изучается этот материал
- Робикс: 1-й уровень
- Робикс: 2-й уровень. «Робот линии»
Дополнительные материалы к статье
- Описание функции analogWrite()
- Описание функции tone()
- Описание функции digitalWrite()
Ардуино (Arduino). #1
Меняем яркость светодиода плавно
Ниже рассмотрим пример использования выходов с ШИМ (PWM) для управления яркостью светодиода.
Подразделы
- Схема электрическая принципиальная 1
- Схема электрическая принципиальная 2
- Реализация
- Скетч 1
- Скетч 2
- Приложение
Как-то, при изучении программирования Ардуино на просторах Интернета, наткнулся на такой вопрос пользователя Николая :
Здравствуйте))) Подскажите пожалуйста новечьку, Как можно реализовать такой скечь При нажатии на кнопку светодиод плавно загорается если нажать ещё раз на кнопку то светодиод плавно тухнет…?
Схема 1
Итак, нам необходимо сделать так, чтобы по нажатии на кнопку, медленно повышалась яркость светодиода до максимального, а при повторном нажатии на кнопку – медленно снижалась до полного гашения. Чтобы видеть законченность процесса изменения яркости – сделал сигнализацию через встроенный светодиод на pin13, поэтому в начальных настройках его гашу.
Для реализации такой программы потребуется светодиод VD1(HL1) , ограничивающий резистор R1 на 330…2000 Ом, кнопка SB1 , стягивающий резистор R2 на 10…18 кОм.
Последовательное соединение светодиода VD1(HL1) и R1 подключается между контактами Ардуино pin11 и GND. Можно использовать любой другой pin, из тех, что имеют возможность выводить ШИМ (PWM) – это контакты (на Arduino UNO) 3, 5, 6, 9, 10, 11, отмеченные на плате значком тильды ~.
Схема 2
Предыдущая схема рабочая, но можно построить схему более оптимально и убрать лишние детали. Так, если мы будем использовать инверсную логику, это когда сигнал от кнопки будет принимать по нажатии не высокий уровень HIGH, а низкий – LOW, то мы сможем использовать подтягивающий резистор внутри микроконтроллера, задав в настройке скетча команду:
pinMode(buttonPin, INPUT_PULLUP);
Эта команда пин, сконфигурированный как вход, подтягивает к +5V, тем самым мы убираем внешний стягивающий резистор R1. Если бы мы использовали несколько пинов как вход, то таким приёмом мы бы хорошо упростили схему. Поэтому новичкам рекомендую использовать инверсную логику, когда кнопки одним выводом подсоединяются к пинам микроконтроллера, а другим выводом – к GND.
Реализация
Реализуем схему 1. Кнопка одним контактом подключена к +5V, а второй контакт к стягивающему резистору R1. От их соединения идёт подключение к контакту pin2. Второй свободный вывод резистора подключен к контакту GND.
Для макетирования удобно использовать макетные панельки (Breadboard).
Скетч 1
Ниже приведён скетч схемы 1:
/*********************************************************** * 2018-02-26 Mr.ALB Тренировка в программировании Ардуино ***********************************************************/ // Переменные с пинами подключенных устройств int buttonPin = 2;// Подключаем кнопку SB1 на 2-й pin // Подключаем светодиод на 11-й pin, можно на любой с PWM int ledPin = 11; // Переменные для хранения состояния кнопки и светодиода boolean lastButton = LOW; boolean currentButton = LOW; int ledLevel = 0; // Настройка изменения яркости int deltaLevel = 10; // Шаг изменения яркости int sign = 1; // Знак шага int step_delay = 120;// Здержка в шаге изменения яркости светодиода // Настройка сигнализатора окончания изменения яркости int max_blink = 3; // Число морганий светодиода LED_BUILTIN int blink_delay = 500;// Задержка состояния светодиода на pin13 /*********************************************************** * Настроечная функция, выполняется один раз вначале ***********************************************************/ void setup() { pinMode(buttonPin, INPUT); pinMode(ledPin, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); // Потушим светодиод на pin13 (LED_BUILTIN) digitalWrite(LED_BUILTIN, LOW); } /*********************************************************** * Функция постоянно повторяется * При нажатии на кнопку, светодиод медленно увеличивает яркость * При повторном нажатии на кнопку, светодиод медленно гаснет ***********************************************************/ void loop() { currentButton = debounce(lastButton);// Опрос кнопки if(lastButton == LOW && currentButton == HIGH) { if(ledLevel == 0) sign = 1; if(ledLevel == 255) sign = -1; // Изменяем яркость светодиода fn_stepBrightness(step_delay,deltaLevel,sign); // Сигнализируем об окончании изменения fn_blink(max_blink, blink_delay); } lastButton = currentButton;// Переписываем состояние кнопки } /*********************************************************** * Функция для подавления дребезга ***********************************************************/ boolean debounce(boolean last) { boolean current = digitalRead(buttonPin);// Читаем состояние кнопки if(last != current) { delay(5); current = digitalRead(buttonPin); } return current; } /*********************************************************** * Функция сигнализации окончания цикла * изменения яркости светодиода ***********************************************************/ void fn_blink(int blink_max, int blink_delay) { for(int i = 0; i < blink_max; i++) { digitalWrite(LED_BUILTIN, HIGH); delay(blink_delay); digitalWrite(LED_BUILTIN, LOW); delay(blink_delay); } } /*********************************************************** * Функция изменения яркости светодиода ***********************************************************/ void fn_stepBrightness(int step_delay, int deltaLevel, int sign) { for(int i = 0; i < (int(256 / deltaLevel) + 1); i++) { ledLevel = ledLevel + deltaLevel * sign; if(ledLevel > 255) ledLevel = 255; if(ledLevel < 0) ledLevel = 0; delay(blink_delay); analogWrite(ledPin, ledLevel); delay(step_delay); } }
Данный пример мною подробно закоментирован и, надеюсь, всё понятно. Конечно можно делать по другому, можно удалить лишнее и код будет меньше. Тут лишь вариант управления яркостью светодиода через ШИМ (PWM).
Можно на базе этого скетча сделать разные модификации, к примеру, по нажатии на кнопку – светодиод будет увеличивать яркость, а потом так же плавно её снижать до затухания. Можно поиграться с задержками и процесс разгорания и гашения светодиода убыстрить и т.п. вариации.
/*********************************************************** * При нажатии на кнопку: * светодиод медленно увеличивает яркость, * а потом медленно гаснет ***********************************************************/ void loop() { currentButton = debounce(lastButton);// Опрос кнопки if(lastButton == LOW && currentButton == HIGH) { fn_stepBrightness(step_delay,deltaLevel,1); // Зажигается fn_stepBrightness(step_delay,deltaLevel,-1);// Тухнет // Сигнализируем об окончании изменения fn_blink(max_blink, blink_delay); } lastButton = currentButton;// Переписываем состояние кнопки }
Для расширения возможностей этого примера, можно добавить ещё кнопку и по её нажатию можно будет выбирать режим работы светодиода: 1) как в базовом варианте, 2) как в дополнительном, т.е. совместить обе модификации в одной реализации. А если кому и этого мало 
Скетч 2
Рассмотрим отличия скетча 2 от первого варианта. Основное отличие в инверсной логике, т.е. срабатывание кнопки тогда, когда на контакте пина 2 будет логическое LOW. Далее изменены типы переменных, значение которых не более 255 принимают тип byte. Для знака sign увеличения яркости или её снижения выбран тип boolean.
Эта оптимизация кода позволила уменьшить его на 76 байт. В этой небольшой программе как бы не существенно, но когда программа увеличивается, то бывает важен каждый байт, поэтому лучше сразу писать код более оптимальным, чем потом стараться его уменьшить.
/*********************************************************** 2018-02-26 Mr.ALB Тренировка в программировании Ардуино Скетч 1 2022-05-17 Mr.ALB Использование инверсной логики Скетч 2 ПОДКЛЮЧЕНИЕ: R2 - pin11 HL1 A - R2 HL1 k - GND SB1 - pin2 и GND 2022-05-17 Скетч 1 использует 1660 байт 2022-05-17 Скетч 2 использует 1584 байт разница: 1660 - 1584 = 76 ***********************************************************/ // Определение отладки, если не нужно, то закомментировать // строку ниже //#define DEBUG // Отладка #define BT_PIN 2 // Подключаем кнопку SB1 на 2-й pin #define LED_PIN 11 // Подключаем светодиод на 11-й pin, ; // можно на любой с PWM #define MAX_BLINK 3 // Число морганий светодиода LED_BUILTIN // Переменные для хранения состояния кнопки и светодиода bool lastButton = HIGH; bool currentButton = HIGH; int ledLevel = 0; // Настройка изменения яркости byte deltaLevel = 10; // Шаг изменения яркости bool sign = true; // Знак шага int step_delay = 120;// Здержка в шаге изменения яркости светодиода // Настройка сигнализатора окончания изменения яркости int blink_delay = 300;// Задержка состояния светодиода на pin13 /*********************************************************** Настроечная функция, выполняется один раз вначале ***********************************************************/ void setup() { #ifdef DEBUG Serial.begin(9600); #endif pinMode(BT_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); // Потушим светодиод на pin13 (LED_BUILTIN) digitalWrite(LED_BUILTIN, LOW); } /*********************************************************** Функция постоянно повторяется При нажатии на кнопку, светодиод медленно увеличивает яркость При повторном нажатии на кнопку, светодиод медленно гаснет ***********************************************************/ void loop() { currentButton = debounce(lastButton); // Опрос кнопки if (lastButton == HIGH && currentButton == LOW) { fnBlink(1, blink_delay); // Сигнал нажатия кнопки if (ledLevel == 0) sign = true; // Знак на увеличение if (ledLevel == 255) sign = false; // Знак на уменьшение // Изменяем яркость светодиода fnStepBrightness(step_delay, deltaLevel, sign); // Сигнализируем об окончании изменения fnBlink(MAX_BLINK, blink_delay); } lastButton = currentButton; // Переписываем состояние кнопки } /*********************************************************** Функция для подавления дребезга ***********************************************************/ boolean debounce(boolean last) { boolean current = digitalRead(BT_PIN);// Читаем состояние кнопки if (last != current) { delay(10); current = digitalRead(BT_PIN); } return current; } /*********************************************************** Функция сигнализации окончания цикла изменения яркости светодиода blink_max - сколько мигнуть blink_delay - задержка в мс ***********************************************************/ void fnBlink(byte blink_max, unsigned int blink_delay) { for (byte i = 0; i < blink_max; i++) { digitalWrite(LED_BUILTIN, HIGH); delay(blink_delay); digitalWrite(LED_BUILTIN, LOW); delay(blink_delay); } } /*********************************************************** Функция изменения яркости светодиода step_delay - Задержка в мс на шаг deltaLevel - На сколько изменить за шаг sign - Знак уменьшение/увеличение ***********************************************************/ void fnStepBrightness ( unsigned int step_delay, byte deltaLevel, bool sign ) { for (byte i = 0; i < (byte(256 / deltaLevel) + 1); i++) { ledLevel = ledLevel + deltaLevel * ((sign == true) ? 1 : -1); #ifdef DEBUG Serial.print(i); Serial.print("t ledLevel="); Serial.println(ledLevel); #endif // Ограничиваем диапазон значений ledLevel = constrain(ledLevel, 0, 255); analogWrite(LED_PIN, ledLevel); delay(step_delay); } }
В приведённом выше скетче использована функция debounce() для устранения дребезга кнопки, при её нажимании. Взял где-то в Интернете или в примерах в Arduino IDE.
Приложение
Программы для повторения:
- Скетч 1: sketch__1.zip2018-07-23
- Скетч 2: sketch__1.2.zip2022-05-17
2018-03-08. ©Mr.ALB
2022-05-17. ©Mr.ALB
Проблема экономии электроэнергии является одной из ключевых в современном мире. Часто можно наблюдать, как где-нибудь горит электрический свет в то время как в помещении (на улице) достаточно светло, тем самым растрачивая впустую электроэнергию. На нашем сайте мы уже рассматривали детектор темноты на основе Arduino и фоторезистора, который включал и выключал свет в зависимости от освещенности в комнате. Но в данном проекте мы будем не просто включать/выключать свет от уровня освещенности, но адаптивно регулировать (подстраивать) его яркость в зависимости от окружающей обстановки (освещенности). В качестве источника света будет использоваться светодиод мощностью 1 Вт, которым мы будем управлять с помощью платы Arduino и транзистора.
Принцип управления яркостью свечения светодиода будет основан на использовании ШИМ (широтно-импульсной модуляции), изменяя коэффициент заполнения которой можно заставить светодиод гореть ярче/темнее.
Необходимые компоненты
- Плата Arduino Uno (купить на AliExpress).
- Фоторезистор (LDR) (купить на AliExpress).
- Транзистор 2N2222 (купить на AliExpress).
- Резистор 510 Ом (купить на AliExpress).
- Резистор 100 кОм (купить на AliExpress).
- Конденсатор 0,1 мкФ (купить на AliExpress).
- Светодиод мощностью 1 Вт (купить на AliExpress).
- Соединительные провода.
- Макетная плата.
Схема проекта
Схема автоматического управления яркостью свечения светодиода с помощью Arduino и фоторезистора представлена на следующем рисунке.

Полный код программы приведен в конце статьи, здесь же обсудим его наиболее важные фрагменты.
Сначала в программе нам необходимо объявить используемые переменные и инициализировать используемые контакты – на pin 12 мы будем формировать ШИМ (PWM) сигнал, а на A0 считывать аналоговое значение напряжения.
|
int pwmPin = 2; // на pin 2 мы будем формировать ШИМ сигнал int LDR = A0; // с контакта A0 мы будем считывать аналоговое значение напряжения int c1 = 0; // объявляем переменную c1 int c2 = 0; // объявляем переменную c2 |
Далее, в функции loop мы будем считывать аналоговое значение напряжения с помощью команды “analogRead(LDR)”, а затем сохранять это значение напряжения в переменной “value”. Потом при помощи несложных математических преобразований мы будем формировать ШИМ сигнал с нужным нам коэффициентом заполнения. Если аналоговое значение напряжения (с выхода АЦП) меньше 500, то мы будем адаптивно управлять яркостью свечения светодиода, а если больше или равно 500 – то мы будем включать его на полную мощность.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
int value = analogRead(LDR); Serial.println(value); c1= value; c2= 500—c1; // вычитаем c1 из 500 и результат сохраняем в c2 if (value < 500) { digitalWrite(pwmPin, HIGH); delayMicroseconds(c2); digitalWrite(pwmPin, LOW); delayMicroseconds(c1); } if (value > 500) { digitalWrite(2,LOW); } } |
Более подробно об использовании ШИМ в Arduino можно прочитать в этой статье.
Принцип работы проекта
Как можно видеть из представленной выше схемы, мы использовали делитель напряжения, состоящий из фоторезистора и резистора сопротивлением 100 кОм. Выход делителя напряжения подключен к аналоговому входу Arduino – с выхода его АЦП мы считываем значение напряжения. Из-за изменений условий освещенности сопротивление фоторезистора уменьшается, следовательно, изменяется и значение напряжения на аналоговом входе Arduino. Если вокруг темно, то сопротивление фоторезистора велико, следовательно напряжение на аналоговом входе Arduino мало. Это полученное значение напряжения мы затем преобразуем в коэффициент заполнения ШИМ, который непосредственным образом влияет на яркость свечения светодиода. Принцип работы нашей схемы можно пояснить с помощью следующей условной диаграммы:
Интенсивность света на фоторезисторе ↓ — Сопротивление фоторезистора↑ — Напряжение на аналоговом входе Arduino↓ — Коэффициент заполнения ШИМ (PWM)↑ — Яркость свечения светодиода↑.
Если вокруг достаточно светло и значение на выходе АЦП аналогового входа Arduino более 500, то мы выключаем светодиод.
Также на нашем сайте вы можете посмотреть все проекты, в которых был использован фоторезистор.
Исходный код программы
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
int pwmPin = 2; // на pin 2 мы будем формировать ШИМ сигнал int pot = A0; // с контакта A0 мы будем считывать аналоговое значение напряжения int c1 = 0; // объявляем переменную c1 int c2 = 0; // объявляем переменную c2 void setup() // setup loop { pinMode(pwmPin, OUTPUT); pinMode(pot, INPUT); Serial.begin(9600); } void loop() { int value = analogRead(pot); Serial.println(value); c1= value; c2= 500—c1; // вычитаем c1 из 500 и результат сохраняем в c2 if (value < 500) { digitalWrite(pwmPin, HIGH); delayMicroseconds(c2); digitalWrite(pwmPin, LOW); delayMicroseconds(c1); } if (value > 500) // если светло – выключаем светодиод { digitalWrite(2,LOW); } } |
Видео, демонстрирующее работу схемы
Загрузка…
1 143 просмотров
Introduction: Controlling LED Brightness With a Potentiometer and Arduino
In this tutorial we will learn how to control the LED brightness with a potentiometer and Arduino.
Watch a demonstration video.
Step 1: What You Will Need
- Arduino UNO (or any other Arduino)
- LED
- Potentiometer
- Jumper wires
- Visuino program: Download Visuino
Step 2: The Circuit
- Connect potentiometer pin [DTB] to arduino analog pin [A0]
- Connect potentiometer pin [VCC] to arduino pin [5V]
- Connect potentiometer pin [GND] to arduino pin [GND]
- Connect LED positive pin to Arduino digital pin [10]
- Connect LED positive pin to Arduino pin [GND]
Step 3: Start Visuino, and Select the Arduino UNO Board Type
To start programming the Arduino, you will need to have the Arduino IDE installed from here: https://www.arduino.cc/.
Please be aware that there are some critical bugs in Arduino IDE 1.6.6. Make sure that you install 1.6.7 or higher, otherwise this Instructable will not work! If you have not done follow the steps in this Instructable to setup the Arduino IDE to program Arduino UNO! The Visuino: https://www.visuino.eu also needs to be installed. Start Visuino as shown in the first picture Click on the «Tools» button on the Arduino component (Picture 1) in Visuino When the dialog appears, select «Arduino UNO» as shown on Picture 2
Step 4: In Visuino Connect Components
Connect Arduino AnalogIn pin[Out] to Arduino Digital [10] pin — Analog (PWM)
Step 5: Generate, Compile, and Upload the Arduino Code
In Visuino, Press F9 or click on the button shown on Picture 1 to generate the Arduino code, and open the Arduino IDE
In the Arduino IDE, click on the Upload button, to compile and upload the code (Picture 2)
Step 6: Play
If you power the Arduino UNO module, and change the potentiometer position the LED will change its brightness.
Congratulations! You have completed your project with Visuino. Also attached is the Visuino project, that I created for this Instructable, you can download it here and open it in Visuino: https://www.visuino.eu
Be the First to Share





















