Курс Arduino с нуля · Управляем светом
Урок 5. Светодиод и резистор: первое управление светом
Подключаем светодиод к цифровому выводу платы и зажигаем его командой из программы: включить, погасить, заставить мигать в любом ритме.
Что понадобится
- Плата Uno из набора
- Кабель USB
- Макетная плата
- Светодиод (любого цвета)
- Резистор 470 Ом
- 3 провода «папа-папа»
Все детали есть в обучающем наборе, по которому идёт курс.
У вас уже есть два умения: писать программу (урок 3) и собирать цепь на макетной плате (урок 4). Сегодня соединим их — и это будет самый важный шаг всего курса. Светодиод на макетке загорится по команде программы: захотим — включим, захотим — погасим, захотим — заставим мигать в любом ритме. С этого момента плата перестаёт быть батарейкой и становится управляющим устройством.
Что меняется: один провод переезжает
В прошлом уроке светодиод питался от гнезда 5V — там всегда ровно 5 вольт, поэтому светодиод горел постоянно, и программа была не нужна. Сегодня мы переставим этот провод в гнездо цифрового вывода 10. Разница огромна: на цифровом выводе напряжение появляется только тогда, когда программа этого захочет.
Что такое цифровой вывод. На верхней гребёнке платы 14 гнёзд с номерами от 0 до 13 — это цифровые выводы. Каждый умеет ровно два состояния: HIGH — «выдать 5 вольт» и LOW — «ноль вольт». Никаких промежуточных значений: как выключатель в комнате, только включённый и выключенный. Плавную яркость мы получим позже, хитрым приёмом — и это будет отдельный урок.
Почему именно вывод 10
Особой магии нет: подошёл бы почти любой вывод от 2 до 13. Мы берём десятый по двум причинам. Во-первых, ровно этот вывод используется в печатной брошюре набора — удобно, когда бумажная и онлайн-версия совпадают. Во-вторых, рядом с числом 10 на плате напечатана волнистая черта: ~10. Она означает, что этот вывод умеет кое-что дополнительное — то самое, из чего в восьмом уроке получится плавная яркость. Пока просто запомним: волнистая черта — хороший знак.
А вот выводы 0 и 1 лучше не занимать: через них плата разговаривает с компьютером, и подключённая к ним деталь может помешать загрузке программы. Вывод 13 тоже особенный — к нему уже подключён встроенный светодиод L.
Схема цепи
На языке принципиальных схем сегодняшняя цепь выглядит так — и она почти не отличается от вчерашней:
Резистор по-прежнему нужен: цифровой вывод — это те же 5 вольт, просто управляемые. Без резистора светодиод сгорит так же быстро, как и от постоянного питания, а заодно может повредить сам вывод платы.
Собираем схему
Отключите кабель USB от платы. Все переделки — на обесточенной схеме.
- Зелёный провод (сигнальный): одним концом — в гнездо 10 на верхней гребёнке платы, другим — в отверстие a6 макетки (столбик 6). Цвет провода не важен, но сигнальные удобно делать не красными и не синими: сразу видно, где питание, а где команда.
- Синий провод (земля): из гнезда GND платы — в шину «−» макетки. Красный провод из 5V сегодня не нужен — питание светодиод получит прямо с вывода 10.
- Резистор 470 Ом: одна ножка в b6 (тот же столбик, что и зелёный провод — значит, они соединены), вторая — в b10.
- Светодиод: длинная ножка (плюс) — в d10, к резистору; короткая — в d12.
- Перемычка: из e12 — в шину «−». Цепь замкнулась: вывод 10 → резистор → светодиод → земля.
Проверьте перед включением: зелёный провод сидит в гнезде с цифрой 10 (а не 1 или 0); ножки резистора — в разных столбиках; длинная ножка светодиода смотрит в сторону резистора. Теперь можно подключать USB.
Подключили? Светодиод не горит — и это правильно. В плате сейчас живёт программа из третьего урока, которая про вывод 10 ничего не знает. Исправим.
Пишем программу — снова по шагам
Создайте новый проект (назовите его, например, Мой светодиод) и наберите первые строки:
void setup() {
// Вывод 10 будет выходом: плата сама подаёт на него напряжение.
pinMode(10, OUTPUT);
}
void loop() {
}
Знакомо? Это та же pinMode() из третьего урока, только вместо LED_BUILTIN мы пишем просто 10 — номер вывода, в который воткнут зелёный провод. Прошейте плату: ничего не произойдёт, светодиод останется тёмным. Мы лишь предупредили плату, что вывод 10 будет выходом — то есть плата будет им командовать, а не слушать его.
Шаг 2. Зажигаем
void setup() {
pinMode(10, OUTPUT);
digitalWrite(10, HIGH); // подали напряжение на вывод 10 — светодиод горит
}
void loop() {
}
Прошейте — и светодиод на макетке загорится. Он будет гореть ровно до тех пор, пока плата включена: команда digitalWrite(10, HIGH) стоит в setup(), а этот блок выполняется один раз при включении.
Остановитесь на секунду и оцените, что произошло: вы включили лампочку строчкой кода. Всё остальное в этом курсе — развитие этой мысли. Умный дом, светофор, сигнализация — там та же команда, только вместо светодиода лампа, мотор или замок.
Шаг 3. Заставляем мигать
Чтобы светодиод не просто горел, а мигал, команды нужно перенести в loop() — блок, который повторяется бесконечно — и добавить паузы:
void setup() {
pinMode(10, OUTPUT); // вывод 10 — выход
}
void loop() {
digitalWrite(10, HIGH); // включили светодиод
delay(500); // горит полсекунды
digitalWrite(10, LOW); // выключили
delay(500); // не горит полсекунды
}
Прошейте. Светодиод мигает раз в секунду: полсекунды горит, полсекунды отдыхает. Логика ровно та же, что в третьем уроке, — но теперь мигает ваш светодиод, который вы сами воткнули в макетку.
Шаг 4. Даём выводу имя
Сейчас число 10 встречается в программе четыре раза. Пока строк мало, это терпимо. Но представьте: в схеме двадцать деталей, и вы решили переставить светодиод на другой вывод — придётся искать по всему тексту и ничего не пропустить. Программисты решают это одной строкой:
// Номер вывода записан ОДИН раз: захотим переставить светодиод —
// поменяем только эту строку, а не всю программу.
const int LED = 10;
void setup() {
pinMode(LED, OUTPUT);
}
void loop() {
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
delay(500);
}
Разберём новую строку по частям:
const— «постоянная величина»: значение задаётся один раз и больше не меняется. Если случайно попробуете изменить его в программе, среда сразу предупредит об ошибке — это защита от опечаток.int— тип значения: целое число (от англ. integer). Номер вывода — конечно, целое.LED— имя, которое мы придумали сами. Могло бытьSVETODIODилиLAMPA: главное, чтобы имя было понятным, латиницей и без пробелов. Заглавными буквами имена констант пишут по традиции — чтобы в тексте программы их было видно сразу.= 10;— само значение и точка с запятой в конце, как у любой команды.
Строка стоит до setup() — в самом верху программы. Такие «объявления» принято собирать наверху, чтобы, открыв чужой скетч, сразу увидеть, что и куда подключено. Теперь для переезда светодиода на вывод 6 достаточно поменять одно число в одной строке.
Привыкайте писать так с самого начала. Дальше в курсе схемы будут усложняться: пять светодиодов, кнопка, датчик, экран. Без имён такие программы превращаются в кашу из чисел, где невозможно вспомнить, что такое «7» — вывод зуммера или вывод третьего светодиода.
Эксперименты
Теперь самое интересное — покрутить готовое. Каждый эксперимент занимает минуту, а понимания добавляет надолго.
- Скорость. Замените
500на2000— светодиод станет мигать медленно и лениво. Поставьте50— превратится в нервную мигалку. А теперь поставьте5: мигание исчезнет, останется ровное тусклое свечение. Мы уже видели этот эффект в третьем уроке — глаз не успевает за платой. - Разные паузы. Сделайте первую паузу
50, вторую1950— получится маяк: короткая вспышка раз в две секунды. - Два светодиода сразу. Наш на макетке и встроенный L на плате могут работать независимо — по очереди:
const int LED = 10; // наш светодиод на макетной плате
void setup() {
pinMode(LED, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT); // встроенный светодиод платы
}
void loop() {
digitalWrite(LED, HIGH); // наш горит,
digitalWrite(LED_BUILTIN, LOW); // встроенный погашен
delay(400);
digitalWrite(LED, LOW); // а теперь наоборот
digitalWrite(LED_BUILTIN, HIGH);
delay(400);
}
Прошейте и посмотрите на плату: пока горит ваш красный светодиод, встроенный погашен, и наоборот. Вы только что управляли двумя устройствами из одной программы — а это уже почти бегущий огонёк, которым мы займёмся в следующем уроке.
Не работает? Разбираемся по порядку
Не расстраивайтесь: на этом уроке спотыкаются почти все — просто потому, что теперь ошибиться можно и в схеме, и в программе. Проверяйте по списку, сверху вниз.
- Светодиод не горит совсем. Первое подозрение — полярность: переверните светодиод. Второе — тот ли столбик: ножка резистора и длинная ножка светодиода должны стоять в одном столбике, а не в соседних. Третье — тот ли вывод: пересчитайте гнёзда на плате, зелёный провод должен сидеть в гнезде с надписью ~10.
- Горит постоянно и не мигает. Скорее всего, команды остались в
setup()вместоloop()— или в плате ещё живёт программа с шага 2. Прошейте текущий вариант заново. - Мигает встроенный светодиод L, а ваш — нет. Значит, в плату загружена программа из третьего урока (она про
LED_BUILTIN). Проверьте, тот ли проект вы прошиваете. - Светит очень тускло. Похоже, стоит резистор 10 кОм вместо 470 Ом. Сверьтесь с цветными кольцами: у нужного — жёлтое, фиолетовое, коричневое.
- Среда ругается и не собирает. Прочитайте карточку ошибки: чаще всего это пропущенная точка с запятой или скобка. Если пишете
digitalwriteс маленькой буквы — тоже ошибка: язык различает большие и маленькие буквы.
Задания для тренировки
- РазминкаПереставьте светодиод на вывод 6: измените схему и одно число в программе. Убедитесь, что всё работает как раньше.
- ПосложнееСоберите «сердцебиение»: две быстрые вспышки подряд, затем длинная пауза — и снова. Попробуйте сами, а потом сверьтесь с разбором ниже.
- Со звёздочкой ⭐Добавьте на макетку второй светодиод другого цвета со своим резистором на вывод 9 и заставьте два светодиода мигать по очереди — как поворотники. Подсказка: понадобится вторая константа, например
const int LED2 = 9;.
Показать разбор задания «сердцебиение»
Хитрости нет: в loop() просто пишем команды по порядку — включить, подождать чуть-чуть, выключить, подождать чуть-чуть, ещё раз включить и выключить, а в конце поставить длинную паузу. Плата выполнит их сверху вниз и начнёт заново:
const int LED = 10;
void setup() {
pinMode(LED, OUTPUT);
}
void loop() {
// Два коротких удара...
digitalWrite(LED, HIGH);
delay(120);
digitalWrite(LED, LOW);
delay(120);
digitalWrite(LED, HIGH);
delay(120);
digitalWrite(LED, LOW);
// ...и длинная пауза перед следующей парой.
delay(900);
}
Обратите внимание: loop() не обязан быть коротким и не обязан состоять из четырёх строк. Внутри может быть сколько угодно команд — плата честно выполнит все, прежде чем начать круг заново.
Что мы узнали
- Цифровые выводы 0–13 — это управляемые «розетки» платы:
HIGH— есть 5 вольт,LOW— нет. - Светодиод подключается к выводу только через резистор, длинной ножкой в сторону вывода.
- Выводы 0 и 1 занимать не стоит — через них идёт связь с компьютером.
- Номера выводов удобно записывать константами (
const int LED = 10;) в начале программы. - Из одной программы можно управлять несколькими выводами независимо.
Вы прошли поворотную точку курса: дальше всё будет строиться на этом умении. В следующем уроке светодиодов станет пять, и мы соберём бегущий огонёк — а заодно познакомимся с приёмом, который избавляет от копирования одинаковых строк.
Частые вопросы
Можно взять другой вывод вместо 10?
Да, подойдёт любой цифровой вывод от 2 до 12. Не занимайте только 0 и 1 — через них плата общается с компьютером, и подключённая деталь может помешать загрузке программы. Вывод 13 занят встроенным светодиодом L.
Что будет, если подключить светодиод без резистора?
Через светодиод потечёт слишком большой ток: он перегреется и выйдет из строя, иногда за считаные секунды. Пострадать может и сам вывод платы. Резистор 470 Ом обязателен в каждой схеме со светодиодом.
Почему светодиод горит, но очень тускло?
Скорее всего, вместо резистора 470 Ом (жёлтое, фиолетовое, коричневое кольца) установлен 10 кОм. Чем больше сопротивление, тем меньше ток и слабее свечение — замените резистор.
Зачем писать const int LED = 10 вместо простого числа?
Чтобы номер вывода хранился в одном месте. При переносе светодиода на другой вывод правится одна строка вместо поиска числа по всей программе, а сам код становится понятнее: сразу видно, что и куда подключено.
