Гирлянда из восьми светодиодов без регистра — это восемь pinMode в setup и восемь digitalWrite в каждом эффекте, копипаста, которая растёт с каждой строкой, а вместе с ней и шанс забыть один из восьми pinMode. Через 74HC595 весь блок сжимается до трёх вызовов: защёлка вниз, shiftOut, защёлка вверх — и восьмёрка светодиодов слушает один байт: бит в байте — конкретный светодиод на макетке, и ничего между ними. Светодиоды с резисторами ставим как обычно, по правилам из урока про светодиод на макетке; сам регистр и его перемычки остались в первом уроке тройки, там же карта корпуса.
Весь этот урок — работа с битами. Волна строится выражением 1 << k: единица сдвигается на k позиций и зажигает k-й выход. Если двоичная система ещё не легла в руку, сначала загляните в урок про двоичную систему — дальше без неё будет тесно: паттерны придётся читать глазами, а не верить копипасте. Двоичная строка байта слева направо — это Q7 к Q0: распечатайте её перед каждым новым эффектом, и половина странного поведения снимается одним взглядом.
Резисторы остаются у каждого светодиода, и номинал я беру 330 Ом: (5 − 2) / 330 ≈ 9 мА на светодиод, 72 мА на восемь горящих разом — на границе корпуса 70 мА, поэтому в длинных статичных шильдиках ставлю 470 и не жадничаю: красный светодиод при шести миллиамперах в комнате вполне презентабелен. Полный расчёт с таблицей номиналов — в уроке про подбор резистора. В симуляторе ниже светодиоды виртуальные: движок не эмулирует shiftOut, поэтому байт рисуется строкой в Serial.
MSBFIRST и LSBFIRST: с какого конца заезжает байт
У shiftOut кроме пинов есть аргумент порядка битов. MSBFIRST — старший бит уходит первым, LSBFIRST — младшим. На проводах это порядок в очереди, на светодиодах — зеркальная картинка: байт 0b10000000 при MSBFIRST зажигает Q7, при LSBFIRST — Q0. Волна поедет в другую сторону, счётчик побежит назад, и никакой магии — просто очередь читается с другого конца. На проводах это выглядит так: при MSBFIRST последний отправленный бит оседает в Q0, при LSBFIRST — в Q7, и разводка макетки обязана это учитывать.
Я держу MSBFIRST всюду и рисую паттерны так, чтобы бит 7 был левым светодиодом: тогда строка Serial.println(x, BIN) совпадает с картинкой на макетке слева направо, и сверка идёт без переворотов в голове. Кто-то выбирает LSBFIRST под конкретную разводку платы — право есть, но зеркальная логика потом вылезает в каждом новом эффекте, и каждый раз заново переворачиваешь байт в уме. Экономия одного аргумента не стоит вечной зеркальности в голове — тот случай, когда единый стандарт выгоднее личных предпочтений.
// Бегущая волна на восьми светодиодах через 74HC595.// DS -> D11, SHCP -> D12, STCP -> D8; MR -> 5 В, OE -> GND.// Ручка A0 задаёт паузу между шагами волны.const int DS = 11;const int SHCP = 12;const int STCP = 8; int speedMs() { return map(analogRead(A0), 0, 1023, 500, 60); // пауза 500..60 мс} void latch(byte pattern) { digitalWrite(STCP, LOW); shiftOut(DS, SHCP, MSBFIRST, pattern); digitalWrite(STCP, HIGH);} void setup() { pinMode(DS, OUTPUT); pinMode(SHCP, OUTPUT); pinMode(STCP, OUTPUT); Serial.begin(9600);} void loop() { for (int k = 0; k <= 7; k++) { // влево: Q0 -> Q7 latch(1 << k); Serial.println(1 << k, BIN); delay(speedMs()); } for (int k = 6; k >= 1; k--) { // обратно, без повторов краёв latch(1 << k); delay(speedMs()); }}После защёлки байт живёт на выходах, пока не придёт следующий: гирлянда не гаснет между шагами и не требует от loop постоянного внимания. Пауза на ручке A0 меняется на ходу — map переводит 0-1023 в 500-60 мс, и волна от ленивого шага разгоняется до строба без перезаливки скетча. Есть и побочный бонус: между защёлками гирлянда не мигает ни разу, средний ток стабилен, и бюджет считается один раз, а не на каждый эффект.
Симулятор рисует то, что после защёлки видят выходы Q0-Q7: строка в мониторе, где решётка — горящий светодиод, точка — спящий. Кнопка D2 разворачивает направление, тумблер D3 включает инверсию: гаснет один светодиод, горят семь — эффект «дырка в гирлянде». На реальной плате shiftOut отправляет этот же байт в 595, а строку рисуют настоящие светодиоды через резисторы 330 Ом.
| Байт | При MSBFIRST горит | При LSBFIRST горит | Что это в эффекте |
|---|---|---|---|
| 0b10000000 | Q7 | Q0 | волна стартует с другого края |
| 0b00001111 | Q0-Q3 | Q4-Q7 | четвёрка зеркалится по линии |
| 0b11111111 | все восемь | все восемь | проверка токового предела корпуса |
| 0b00000000 | ничего | ничего | пауза между эффектами без коммутации |
Гирлянда — самая наглядная, но не самая частая нагрузка. Второй по популярности гость на регистре — шкалы и шильдики: уровень заполнения бака, заряд, четыре режима в строке. Здесь паттерн не бегает, а стоит, и это лучший стенд для арифметики вычитания: шкала «четыре из восьми» — это 0b00001111, минус один шаг — 0b00000111, и обе живут на выходах без единого digitalWrite в основном цикле.
Реле через регистр тоже вешают, но не напрямую: восемь катушек по 70 мА каждая — заведомо больше корпуса, поэтому между Q0-Q7 и реле ставят транзисторные ключи или микросхему ULN2803A с восемью каналами и защитными диодами внутри. Байт остаётся прежним — усилитель после регистровых выходов меняет только железо. Как устроен такой ключ, разобрано в уроке про NPN-транзистор; от него регистру нужен один факт: ток базы берётся с выхода Q через резистор, и бит 1 превращается во включённую катушку. Считается он так же, как в базовом уроке: около миллиампера на базу, запас по усилению транзистора — в десятки раз.
И одна честная граница: 595 не умеет ШИМ. Выходы либо HIGH, либо LOW, и диммировать гирлянду напрямую не выйдет — только миганием быстрее глазного предела, что отдельная возня с таймерами. Для регулировки яркости я беру обычные пины с analogWrite, а регистр оставляю там, где нужен бинарный статус: горит или спит — светофоры, клапаны, реле, и никакой плавной середины.
Эффекты из одного байта
Официальное демо из туториала по shiftOut — счётчик от 0 до 255: байт растёт на единицу каждый такт, и гирлянда показывает двоичное число в реальном времени. Для проверки сборки это удобнее волны: пропущенный бит виден как ступенька, где светодиод не мигнул, — счётчик вскрывает любой плохой контакт в очереди. Мой стенд проверки каскада — тот же счётчик, растянутый до 65535 на двух корпусах: заедающий бит в длинной цепочке вылезает ступенькой в двоичном шаге, и искать его по светодиодам больше не нужно.
Инверсия порождает вторую волну бесплатно: паттерн и 255 минус паттерн в двух регистрах дают гирлянду, где волна и её негатив бегут навстречу. Встречные волны, шахматка, «дырка» — вся эта арифметика крутится вокруг одного байта, без единого лишнего пина. Мелочь, которая экономит сверку: Serial печатает двоичный вид без ведущих нулей, и волне на Q3 соответствует строка 1000, а не 00001000 — дописывайте нули в голове или в формате вывода.
Единственное, что рано или поздно упрётся, — delay внутри цикла: пока волна спит, скетч не слышит кнопок. Перенос шага на millis() даёт волне жить параллельно с остальной логикой — приём разобран в уроке про millis вместо delay. В симуляторе выше шаги и кнопка уже разнесены по времени: нажмите её между строками и убедитесь, что волна не сбивается. Тот же каркас переживёт ручку скорости и переключатель эффектов: шаг волны — одна строка в теле планировщика, и каждая новая функция добавляется без перестройки остального кода. Перенос у меня идёт в три шага: вынести шаг волны в функцию, поставить вызов в тело планировщика, убрать delay из loop.
- 1. Байт 0b00001111 при LSBFIRST зажжёт какие выходы?
- 2. Сколько вызовов нужно, чтобы обновить восемь светодиодов через 595?
- 3. Как построить бегущую волну одним байтом?
- 4. Почему для демо-гирлянды на 595 берут резисторы от 330 Ом?
- 5. Инверсия паттерна «горят все, кроме одного» считается как?
- Вся гирлянда — один байт: защёлка вниз, shiftOut, защёлка вверх — и восемь выходов обновляются разом
- MSBFIRST и LSBFIRST — очередь с разных концов: смена порядка зеркалит картинку на Q0-Q7
- Резисторы 330-470 Ом у каждого светодиода: восемь по 9 мА — 72 мА, впритык к пределу корпуса 70 мА
- Волна — это 1 << k; инверсия — 255 минус паттерн; счётчик 0-255 вскрывает плохие контакты
- delay замирает вместе с волной: как только в скетче заводятся кнопки, шаг переносится на millis()
Частые вопросы по теме урока
- Байт 0b00001111 при LSBFIRST зажжёт какие выходы?
- LSBFIRST отправляет младший бит первым, он первым доезжает до дальнего конца очереди: четвёрка уезжает в Q4-Q7. При MSBFIRST те же биты осели бы в Q0-Q3. Порядок в очереди — это и есть вся разница между двумя режимами. Q4-Q7
- Сколько вызовов нужно, чтобы обновить восемь светодиодов через 595?
- STCP в низ, shiftOut байта, STCP в верх — восемь выходов обновились разом. Пины Arduino при этом расходуются те же три независимо от числа корпусов в каскаде. Число светодиодов не влияет ни на скорость, ни на количество линий. три: защёлка вниз, shiftOut, защёлка вверх
- Как построить бегущую волну одним байтом?
- 1 << k ставит единственную горящую позицию на k-й выход; индекс k гуляет по кольцу 0-7. Это дешевле счётчика и заметнее для глаза. Край кольца обрабатывают условиями, и волна зацикливается без сбоев. сдвигать единицу: 1 << k по кольцу
- Почему для демо-гирлянды на 595 берут резисторы от 330 Ом?
- Предел корпуса — около 70 мА. Восемь светодиодов по 330 Ом дают 72 мА на всех, по 220 Ом — за сотню: регистр работает на пределе и греется. Отсюда же правило: не зажигать длинные серии единиц в статике без пересчёта бюджета. чтобы суммарный ток восьми светодиодов не вылез за предел корпуса
- Инверсия паттерна «горят все, кроме одного» считается как?
- У байта 256 состояний, все единицы — это 255. Вычитание паттерна из 255 переворачивает каждый бит без побитовых операторов. Тот же приём инвертирует паттерны индикатора с общим анодом в третьем уроке. 255 минус паттерн