Управляем одной кнопкой несколькими светодиодамиСтавлю задачу.
Сделать так, чтобы одна кнопка управляла включением и выключением нескольких светодиодов следующим образом. Изначально светодиоды погашены. Первое нажатие на кнопку зажигает первый (слева) светодиод. Второе нажатие кнопки гасит первый светодиод и зажигает второй. Третье нажатие гасит второй и зажигает третий и т.д. до восьмого светодиода. После зажигания и погашения восьмого светодиода должен быть статус, когда погашены все светодиоды. А последующие нажатия кнопки должны всё повторить и так по кругу.Собираю на макетке схему из восьми сетодиодов и одной кнопки. Для светодиодов задействую цифровые выводы от 0 до 7. За состоянием кнопки будет следить 13-ый цифровой вывод.
Чтобы проверить, что схема собрана правильно, пишу временный скетч, в котором зажигаю все светодиоды на секунду и выключаю
Код: Выделить всё
void setup() {
// Выводы 0-7 назначаем выходами
for (int i=0; i<=8; i++)
{
pinMode(i, OUTPUT);
}
// На выходы 0-7 подаём высокий уровень, зажигаем светодиоды
for (int i=0; i<=8; i++)
{
digitalWrite(i, HIGH);
}
delay(1000);
// На выходы 0-7 подаём низкий уровень, зажигаем светодиоды
for (int i=0; i<=8; i++)
{
digitalWrite(i, LOW);
}
}
void loop() {
}
Пытаюсь загрузить скетч в память контроллера, но не тут-то было. Натыкаюсь на ошибку "
avrdude: stk500_recv(): programmer is not responding". Что делал и что НЕ помогло:
1. Перетыкание USB в том числе и в другой разъём.
2. Перезагрузка компьютера.
Полез в интернет и вот
здесь наткнулся на интересную инфу о том, что предыдущие скетчи могут мешать загрузке новых. Вернее, не так. Предыдущие скетчи могут так запрограммировать входы/выходы, что в новой схеме это приведёт к каким-либо косякам: к коротким замыканиям, неустойчивым состояниям и прочему. Поэтому рекомендуется
сначала прошить контроллер новым скетчем и только после этого собирать схему. Так-что похоже, что я словил вторые свои грабли на ардуине. Ведь я сначала собрал схему, а потом прошивал, не очистив память контроллера от предыдущей прошивки. Но эта инфа всего лишь дала мне толчок в нужном направлении, а предыдущий скетч тут был ни причём. Начав по порядку, а именно с нулевого цифрового вывода, выдернув проводок, успешно загрузив скетч, вставив проводок и опять получив ошибку, понял, что этот вывод (цифровой нулевой) можно использовать в схеме только после перепрошивки. А если на него что-то схемно уже навешано, как в моём случае светодиод с резистором, то это приводит к ошибке "
avrdude: stk500_recv(): programmer is not responding" при загрузке скетча. Также должен отметить, что светодиод, подключенный к первому выводу как-то странно помыргивал. Вообщем, я решил отказаться от их использования и всю схему сдвинул на два вывода, задействовав со 2 по 9 выводы. Проверил, загрузив скетч. Всё отлично! Все 8 светодиодов зажигаются на секунду и гаснут. Можно двигаться дальше.
Пишу следующий код
Код: Выделить всё
const int BUTTON = 13; // Контакт 13 для подключенния кнопки
int tekButton = LOW; // Текущее состояние кнопки
int prevButton = LOW; // Предыдущее состояние кнопки
int Status = 0; // Хранилище состояния системы:
// 0 - светодиоды погашены
// 1 - горит первый светодиод
// 2 - горит второй светодиод
// 3 - горит третий светодиод
// 4 - горит четвёртый светодиод
// 5 - горит пятый светодиод
// 6 - горит шестой светодиод
// 7 - горит седьмой светодиод
// 8 - горит восьмой светодиод
void setup() {
// Выводы 2 - 9 назначаем выходами
for (int i = 2; i <= 9; i++)
{
pinMode(i, OUTPUT);
}
// Вывод 13 назначаем входом
pinMode(13, INPUT);
}
// Функция сглаживания дребезга. Принимает в качестве
// аргумента предыдущее состояние кнопки и выдаёт фактическое.
boolean debounce(boolean last)
{
boolean current = digitalRead(BUTTON); // Считываем состояние кнопки
if (last != current) // Если изменилось...
{
delay(5); // Ждём 5 мс
current = digitalRead(BUTTON); // Считываем состояние кнопки
return current; // Возвращаем состояние кнопки
}
}
void loop() {
tekButton = debounce(prevButton); // Считываем состояние кнопки
if (prevButton == LOW && tekButton == HIGH) // Если нажатие...
{
Status++; // Увеличиваем Status на единицу
if (Status > 8) // Если Status вышел за допустимые пределы
{
Status = 0; // Обнуляем
}
}
prevButton = tekButton;
// На выходы 2 - 9 подаём низкий уровень, гасим светодиоды
for (int i = 2; i <= 9; i++)
{
digitalWrite(i, LOW);
}
if (Status > 0) // Если Status больше нуля...
{
digitalWrite(Status + 1, HIGH); // Зажигаем соответствующий светодиод
}
}
Функцию debounce() я честно скоммуниздил из книги "
Практическая энциклопедия ARDUINO" из примера обработки нажатия кнопки. Но остальное всё сам написал. Кстати, в среде программистов тырить чьи-нибудь удачные, эффективные, да и просто понравившиеся коды - это нормальная практика. На то он и открытый код, чтобы его могли изучать и использовать все, кому не лень в нём разбираться.
Итак, что делает данный скетч?
В функции setup() выводы со 2-го по 9-ый назначаются выходами, а 13-ый вывод - входом.
В функции loop() считываем состояние кнопки функцией debounce(). Если есть нажатие, то увеличиваем статус на единицу. Если после увеличения статус превысил допустимый верхний предел, то обнуляем его. В переменной prevButton сохраняем текущее состояние кнопки. Далее гасим все светодиоды и если статус больше нуля, то зажигаем светодиод, соответствующий статусу.
https://youtu.be/X1lWJJk3BEk