Курс Arduino с нуля · Управляем светом
Урок 9. Трёхцветный светодиод: смешиваем цвета
Три кристалла в одном корпусе дают любой оттенок. Разбираемся с общим анодом и перевёрнутой логикой, пишем функцию setColor и переливаем радугу.
Что понадобится
- Плата Uno из набора
- Кабель USB
- Макетная плата
- RGB-светодиод
- 3 резистора 470 Ом
- 5 проводов «папа-папа»
Все детали есть в обучающем наборе, по которому идёт курс.
Мы научились задавать светодиоду любую яркость. Сегодня научимся задавать любой цвет. В наборе есть особенная деталь — трёхцветный светодиод, он же RGB: три кристалла в одном корпусе. Смешивая их яркости, можно получить оранжевый, бирюзовый, сиреневый, тёплый белый — вообще любой оттенок.
Урок будет с сюрпризом: этот светодиод включается наоборот. Разберёмся, почему так, и научимся делать, чтобы это не мешало.
Что такое RGB-светодиод
Название — из первых букв английских слов Red, Green, Blue: красный, зелёный, синий. Внутри общей матовой колбы спрятаны три отдельных светодиода, а наружу выходят четыре ножки.
Три ножки — это «личные» выводы кристаллов: красного, зелёного и синего. Четвёртая, самая длинная, — общая для всех троих. Порядок ножек фиксированный: R — A — G — B, если держать светодиод спилом влево (спил — тот же плоский срез на юбке, что и у обычного светодиода).
Почему цветов только три? Потому что этого достаточно. Наш глаз различает цвет тремя типами колбочек — как раз красными, зелёными и синими. Экран телефона, монитор и телевизор устроены так же: миллионы точек, и в каждой три крошечных источника этих трёх цветов. Вы сейчас читаете этот текст на экране, который работает ровно по тому же принципу, что и деталь в вашей руке.
Сюрприз: общий вывод — это «плюс»
Вот главная особенность нашей детали. У обычного светодиода мы подавали на вывод платы плюс, а второй конец уводили на землю. Здесь наоборот: общая ножка идёт на 5 вольт, а выводы платы работают «минусами».
Такой светодиод называют с общим анодом (анод — это как раз «плюс»). Ток течёт от 5 вольт через кристалл к выводу платы — а значит, кристалл зажжётся только тогда, когда на выводе платы будет ноль. Логика перевёрнута:
digitalWrite(RED, LOW)— красный горит;digitalWrite(RED, HIGH)— красный погашен;analogWrite(RED, 0)— полная яркость, а255— темнота.
Это сбивает с толку, и на этом спотыкаются очень многие. Но у нас есть отличное средство — своя функция из седьмого урока. Мы спрячем переворот внутрь неё и снаружи будем писать привычно. Сначала соберём схему.
Собираем схему
Отключите USB. И запомните: резисторов нужно три — по одному на каждый цвет. Общая ножка идёт на 5 вольт напрямую, без резистора.
Расстояние между ножками светодиода совпадает с шагом отверстий макетки, поэтому все четыре встают в соседние столбики сами. Если ножки погнуты — аккуратно выпрямите их пальцами, чтобы они не касались друг друга.
Проверьте перед включением: самая длинная ножка идёт на 5 В (красный провод); у каждой из трёх остальных — свой резистор; выводы 11, 10 и 9 выбраны не случайно — все они с волнистой чертой, а без ШИМ смешивать оттенки не получится.
Шаг 1. Первое включение — и первое удивление
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
void setup() {
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
// LOW зажигает цвет, HIGH — гасит: общий вывод сидит на 5 вольтах,
// и ток течёт, только когда на выводе платы ноль.
digitalWrite(RED, LOW); // красный горит
digitalWrite(GREEN, HIGH); // зелёный погашен
digitalWrite(BLUE, HIGH); // синий погашен
}
Прошейте. Горит красный — хотя мы написали LOW, то есть «выключить». А два других цвета, которым мы написали HIGH, погашены. Всё правильно: так и работает общий анод.
Поменяйте местами LOW и HIGH в строках зелёного и синего — увидите, как загораются они. Поиграйте пару минут: включите два цвета сразу и посмотрите, что получится. Уже на этом этапе можно поймать жёлтый и голубой.
Шаг 2. Прячем путаницу в функцию
Держать в голове перевёрнутую логику — верный способ ошибиться. Поступим как взрослые программисты: напишем функцию setColor, которая принимает цвет привычным образом (0 — нет цвета, 255 — на полную), а внутри сама делает переворот:
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
// Снаружи всё привычно: 0 — цвета нет, 255 — цвет на полную.
// Переворот прячем внутри функции.
void setColor(int r, int g, int b) {
analogWrite(RED, 255 - r);
analogWrite(GREEN, 255 - g);
analogWrite(BLUE, 255 - b);
}
void setup() {
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
setColor(255, 0, 0); // чистый красный
}
Ключевая строка — analogWrite(RED, 255 - r). Если снаружи попросили r = 255 (полный красный), внутрь уйдёт 255 - 255 = 0 — а ноль для нашего светодиода означает «полная яркость». Если попросили r = 0, внутрь уйдёт 255 — «выключено». Переворот случается ровно в одном месте программы, и дальше о нём можно забыть.
Это и есть настоящая работа программиста. Неудобная особенность железа спрятана внутрь функции, а снаружи остался понятный и честный интерфейс: setColor(255, 0, 0) — «дай мне красный». Точно так же устроены библиотеки, которыми мы будем пользоваться дальше в курсе: внутри у них сложность, снаружи — простые команды.
Шаг 3. Смешиваем цвета
Теперь самое интересное. Свет смешивается не так, как краски: если в красках жёлтый плюс синий дают зелёный, то у света всё иначе.
Проверим таблицу вживую — программа переберёт семь состояний:
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
void setColor(int r, int g, int b) {
analogWrite(RED, 255 - r);
analogWrite(GREEN, 255 - g);
analogWrite(BLUE, 255 - b);
}
void setup() {
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
setColor(255, 0, 0); delay(800); // красный
setColor( 0, 255, 0); delay(800); // зелёный
setColor( 0, 0, 255); delay(800); // синий
setColor(255, 255, 0); delay(800); // красный + зелёный = жёлтый
setColor( 0, 255, 255); delay(800); // зелёный + синий = голубой
setColor(255, 0, 255); delay(800); // красный + синий = сиреневый
setColor(255, 255, 255); delay(800); // все три вместе = белый
setColor( 0, 0, 0); delay(800); // всё выключено
}
Прошейте и понаблюдайте. Жёлтый может выйти чуть зеленоватым, а белый — голубоватым: это нормально, кристаллы у дешёвых светодиодов светят с разной силой. Ниже мы это подправим.
Шаг 4. Оттенки, а не только чистые цвета
Настоящая сила RGB — в промежуточных значениях. Уменьшая одну составляющую, получаем десятки оттенков:
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
void setColor(int r, int g, int b) {
analogWrite(RED, 255 - r);
analogWrite(GREEN, 255 - g);
analogWrite(BLUE, 255 - b);
}
void setup() {
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
setColor(255, 120, 0); delay(1200); // оранжевый
setColor(255, 60, 60); delay(1200); // розовый
setColor(120, 0, 255); delay(1200); // фиолетовый
setColor(255, 160, 60); delay(1200); // тёплый белый, как лампа накаливания
setColor( 0, 100, 40); delay(1200); // приглушённый зелёный
}
Обратите внимание на оранжевый: setColor(255, 120, 0). Это красный, к которому добавили меньше половины зелёного. Добавьте больше — получите жёлтый, меньше — красно-оранжевый. Именно так подбирают любой цвет: крутим три числа и смотрим.
Подсказка на будущее. Числа в графических редакторах и в вебе — те же самые. Если вы нашли красивый цвет в интернете и видите запись вроде rgb(255, 160, 60) — это готовые значения для нашей функции setColor(255, 160, 60). А привычная запись #FF6A00 — это то же самое, только в шестнадцатеричном виде.
Шаг 5. Плавный перелив
Сложим всё выученное: цикл из шестого урока, плавность из восьмого и смешивание из сегодняшнего. Получится бесконечный перелив цветов:
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
void setColor(int r, int g, int b) {
analogWrite(RED, 255 - r);
analogWrite(GREEN, 255 - g);
analogWrite(BLUE, 255 - b);
}
void setup() {
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
// Красный медленно уступает место зелёному.
for (int i = 0; i <= 255; i++) {
setColor(255 - i, i, 0);
delay(10);
}
// Зелёный — синему.
for (int i = 0; i <= 255; i++) {
setColor(0, 255 - i, i);
delay(10);
}
// Синий — снова красному.
for (int i = 0; i <= 255; i++) {
setColor(i, 0, 255 - i);
delay(10);
}
}
Присмотритесь к первому циклу: пока i растёт от 0 до 255, красный уменьшается (255 - i), а зелёный ровно настолько же увеличивается (i). В сумме яркость остаётся примерно постоянной, а цвет плавно перетекает из красного через оранжевый и жёлтый в зелёный. Три таких цикла — и мы обошли всю радугу.
Не работает? Разбираемся
- Светодиод горит белым и не слушается. Похоже, общий вывод попал не на 5 В, а на землю: цвета «включаются» постоянно. Проверьте красный провод — он должен идти именно в гнездо 5V.
- Работают не все цвета. Убедитесь, что ножки не перепутаны: порядок R — A — G — B от спила, а самая длинная — вторая по счёту. Если светодиод вставлен задом наперёд, «красным» окажется синий.
- Цвета включаются, но оттенки не смешиваются. Проверьте выводы: нужны именно 11, 10 и 9 — с волнистой чертой. На обычном выводе будет только «включено или выключено».
- Один цвет заметно ярче остальных. Это особенность детали, а не ошибка. Уменьшите его в функции: например, замените
analogWrite(GREEN, 255 - g)наanalogWrite(GREEN, 255 - g * 0.7)— и белый станет ровнее. - Ничего не светится. Проверьте, не перепутали ли вы, что общий вывод идёт без резистора, а каждый цветной — через резистор. И не забыт ли провод на 5 В.
Задания для тренировки
- РазминкаПодберите цвет своего настроения: покрутите три числа в
setColor, пока не получите оттенок, который вам нравится, и запишите его. - ПосложнееСделайте «индикатор температуры»: пусть светодиод плавно переходит от синего (холодно) через зелёный к красному (жарко) — и обратно. Пока без датчика, просто по времени.
- Со звёздочкой ⭐Соберите лампу настроения: пусть светодиод сам выбирает случайный цвет и плавно к нему переходит — без скачков. Разбор ниже.
Показать разбор «лампы настроения»
Чтобы переход был плавным, программа должна помнить текущий цвет и постепенно двигаться к новому. Для этого заведём три переменные вне функций — тогда они переживут конец loop() и сохранят значения:
const int RED = 11;
const int GREEN = 10;
const int BLUE = 9;
// Текущий цвет лампы.
int r = 0;
int g = 0;
int b = 0;
void setColor(int red, int green, int blue) {
analogWrite(RED, 255 - red);
analogWrite(GREEN, 255 - green);
analogWrite(BLUE, 255 - blue);
}
// Плавно доводит текущий цвет до заданного за 255 маленьких шагов.
void fadeTo(int targetR, int targetG, int targetB) {
for (int step = 0; step <= 255; step++) {
// На каждом шаге берём промежуточное значение между текущим и нужным.
int nowR = r + (targetR - r) * step / 255;
int nowG = g + (targetG - g) * step / 255;
int nowB = b + (targetB - b) * step / 255;
setColor(nowR, nowG, nowB);
delay(8);
}
r = targetR;
g = targetG;
b = targetB;
}
void setup() {
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
// Каждый раз — новый случайный цвет, и переход к нему занимает две секунды.
fadeTo(random(0, 256), random(0, 256), random(0, 256));
delay(500);
}
Главная строка — r + (targetR - r) * step / 255. Она вычисляет, где мы находимся между старым и новым цветом на текущем шаге: при step = 0 получается старый цвет, при step = 255 — новый, а между ними — плавная середина. Тот же приём работает для любых плавных переходов: громкости, положения сервопривода, скорости мотора.
Что мы узнали
- RGB-светодиод — три кристалла в одном корпусе; ножки идут в порядке R — A — G — B, самая длинная — общая.
- В нашем наборе светодиод с общим анодом: общий вывод на 5 В, а цвет зажигается низким сигналом. Логика перевёрнута.
- Неудобство железа прячут внутрь своей функции — снаружи остаётся понятная команда
setColor(r, g, b). - Свет смешивается сложением: красный + зелёный = жёлтый, все три = белый.
- Любой оттенок — это три числа от 0 до 255, те же самые, что используются в графических редакторах.
На этом блок «Управляем светом» закончен: вы умеете включать, гасить, регулировать яркость и получать любой цвет. Дальше плата научится слушать: в следующем блоке появится кнопка, и устройства станут отвечать на ваши действия.
Частые вопросы
Как определить выводы RGB-светодиода?
Держите светодиод спилом влево: ножки идут в порядке R — A — G — B. Самая длинная — вторая по счёту, это общий вывод. В наборе светодиод с общим анодом, поэтому длинная ножка подключается к 5 В.
Почему LOW зажигает цвет, а HIGH гасит?
Потому что общий вывод сидит на 5 вольтах. Ток течёт от него через кристалл к выводу платы, и это возможно, только когда на выводе ноль. У светодиодов с общим катодом всё наоборот — там привычная логика.
Сколько резисторов нужно для RGB-светодиода?
Три — по одному на каждый цветной вывод. Общий вывод подключается напрямую. Один общий резистор ставить нельзя: яркость цветов будет меняться в зависимости от того, сколько кристаллов горит одновременно.
Почему белый цвет получается с оттенком?
Кристаллы разных цветов светят с разной силой, поэтому при одинаковых значениях один перевешивает. Это лечится подбором коэффициентов в функции setColor — например, уменьшить зелёную составляющую примерно на треть.
