Как именно работают велосипедные светодиоды? (Проект Arduino)
Оглавление:
- Чего я хочу достичь
- Проблема, с которой я столкнулся
- Что я пробовал
- Возможные гипотезы
Чего я хочу достичь
Привет, ребята, я работаю над проектом DIY LED Light для установки на мой велосипед, где я хочу воссоздать, как работают настоящие светодиодные велосипедные фонари:
[Этап 1] Нажмите кнопку один раз: светодиод загорается вечно, пока кнопка не будет нажата снова. [Этап 2] Нажмите кнопку дважды: светодиод мигает вечно, пока кнопка не будет нажата снова. [Этап 3] Нажмите кнопку трижды: светодиод выключается (возвращается в исходное состояние).
Проблема, с которой я столкнулся
После небольшого исследования я знаю, как разработать код для [Stage 1] (отслеживая текущее и предыдущее состояния кнопок). Но я не могу осуществить [Стадию 2].
Что я пробовал
Я пытался вместо отслеживания предыдущего и текущего состояний кнопок, почему бы не использовать счетчик, то есть:
Счетчик = 0 (начальный) При однократном нажатии кнопки счетчик = 1 (светодиод горит вечно, пока кнопка не будет нажата снова)
При повторном нажатии кнопки, Счетчик = 2 (светодиод мигает вечно, пока кнопка не будет нажата снова)
При повторном нажатии кнопки, Счетчик = 3 (светодиод выключается, возвращается в исходное НИЗКОЕ состояние) Счетчик снова сбрасывается на = 0
Вот мой код ниже:
const int ledPin = 8;
const int buttonPin = 7;
int buttonState;
int ledState;
int counter = 0;
int newcounter;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
digitalWrite(ledPin, HIGH);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
newcounter = counter + 1;
delay(500);
if (newcounter != counter) {
switch (newcounter) {
case 1:
digitalWrite(ledPin, LOW);
counter = newcounter;
break;
case 2:
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
break;
case 3:
digitalWrite(ledPin, HIGH);
counter = 0;
break;
default:
digitalWrite(ledPin, HIGH);
counter = 0;
break;
}
}
}
}
Возможные гипотезы (пожалуйста, критикуйте/поправьте меня, если я ошибаюсь)
А) Есть проблема с моим кодом (моя логика программирования и т. Д.)
Б) Может быть, это не проблема кода/программы? Это может быть связано с конструкцией электрической цепи (потому что я видел видео на YouTube, где светодиоды можно заставить мигать с помощью конденсаторов и транзисторов. Но как происходит последовательность от этапов 1 до 3 в велосипедном светодиодном фонаре? (https://www.youtube.com/watch?v=cXCExzIBNsA)
Я буду бесконечно благодарен, если кто-нибудь сможет помочь! Спасибо!!
@, 👍1
Обсуждение2 ответа
вы не заявляете, какие результаты вы получаете.
Я вижу, что вы не предустановляете свои переменные состояния.
Это всегда хорошая практика, чтобы избежать случайных условий запуска.
у вас есть логика, которая будет работать только тогда, когда кнопка удерживается , ваш оператор if (newcounter != counter) и switch выполняются только при нажатии кнопки. переместите их за пределы проверки состояния кнопки и ищите изменения ТОЛЬКО в том случае, если кнопка изменилась.
попробуй это; он будет действовать только при изменении кнопки а не непрерывно поэтому изменения происходят только при каждом нажатии
я оставлю вас играть с условиями переключения
const int ledPin = 8;
const int buttonPin = 7;
int buttonState, chngButtonState = 0;
int ledState;
int counter = 0;
int newcounter;
void setup() {
chngButtonState = buttonState;
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
digitalWrite(ledPin, HIGH);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH && !buttonState == chngButtonState ) { // read once only if changed button state changed not on every loop
newcounter = counter + 1;
delay(500);
chngButtonState = buttonState; // mae them equal again
} // NOTE I moved 1 of the } from the bottom
if (newcounter != counter) {
switch (newcounter) {
case 1:
digitalWrite(ledPin, LOW);
counter = newcounter;
break;
case 2:
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);
delay(500);
digitalWrite(ledPin, HIGH);
delay(500);
break;
case 3:
digitalWrite(ledPin, HIGH);
counter = 0;
break;
default:
digitalWrite(ledPin, HIGH);
counter = 0;
break;
}
}
}
теперь просто поиграйте с операторами Switch, чтобы получить свои результаты.
pinMode(buttonPin, ВХОД);
ваша проводка кнопок не ясна.
Скорее всего, у вас есть кнопка, подключенная к VCC и контакту 7. У вас все еще должен быть выдвижной резистор от arduino pin7 до GND, чтобы получить надежные состояния.
Однако, если кнопка находится от pin7 до GND и не подтягивается, состояние также не изменится.
Если это так; измените pinMode(buttonPin, INPUT) на pinMode(buttonPin, INPUT_PULLUP), и внешний подтягивающий резистор не понадобится.
Подумайте о "стадиях", которые вы определили как состояния или режимы работы, и нажатия кнопок циклически переходят от одной стадии к другой.
Затем для "этапа 2" вы переписываете его как функцию, которая в основном не блокируется и не простаивает в течение 3,5 секунд, но которая немедленно возвращает управление обратно в цикл ()
, чтобы вы могли быстро проверить наличие дополнительных нажатий кнопок:
// эта функция построена по образцу примера в
// https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
void stage2(void){
const unsigned long interval = 500;
static unsigned long last = 0;
if(millis() - last >= interval){
last += interval;
digitalWrite(ledPin, !digitalRead(ledPin));
}
}
а затем вы включаете сцену в цикле событий:
switch (stage) {
case 0: // idle
break;
case 1: // on
digitalWrite(ledPin, LOW);
counter = newcounter;
break;
case 2: // blinking
stage2();
break;
case 3: // turn off
digitalWrite(ledPin, HIGH);
stage = 0;
break;
default:
digitalWrite(ledPin, HIGH);
counter = 0;
break;
}
...
Этот переключатель почти не занимает времени и возвращает управление циклу событий, поэтому пользовательский интерфейс может быстро реагировать на другие нажатия кнопок или проверять наличие других задач.
Я не переписывал остальную часть вашего кода, но вот ключевые различия между вашим кодом и тем, что работает в велосипедном свете:
Используйте переменные состояния и конечные автоматы для изменения режима работы.
Избегайте захвата процессора в "блокирующий" код, который использует delays (), for(;;), while (); и т. Д... Вместо этого полагайтесь на цикл событий (
loop()
в Arduino), чтобы вернуть управление вашим функциям.
Существует имитация велосипедного фонаря с использованием этих шаблонов кодирования на Wokwi по адресу https://wokwi.com/arduino/projects/325075981102482003
- Питание светодиодной ленты - Сколько ампер?
- Несколько условий оператора if
- Светодиоды: разница между общим анодом и общим катодом
- Светодиод L продолжает гореть
- Улучшенное циклическое переключение цветов RGB.
- Плавное мигание светодиодов
- Остановить мигание светодиодов
- FastLED - Как управлять определенными светодиодами
Прежде всего, вам нужно избавиться от всех этих вызовов
delay () ' и реализовать его неблокирующим способом (посмотрите на
BlinkWithoutDelay.ino`)., @Sim SonВы пропускаете строку
counter = newcounter;
в вашем "случае 2:", но реальная проблема (вероятно, поскольку вы на самом деле не описали, что означает " Но я не могу сделать [Этап 2]") почти наверняка заключается в том, что у вас есть только 3 мигания, а затем ваш код выходит из состояния и возвращается к началу цикла. Сим Сын уже дал вам один способ исправить это. Ваш код может работать немного больше, чем вы предполагаете, если вы переместите весь блок "switch" за пределы блока " if (buttonState == HIGH)". Как вы уже написали,дело
со всеми миганиями выполняется только при нажатии кнопки., @brhansВаша проблема в том, что ваш код управления светодиодом полностью запутан с вашим нажатием кнопки и кодом счетчика. Разделите их на совершенно независимые блоки кода. Тот, который просто увеличивает счетчик с помощью кнопки, и тот, который отображает разные вещи в зависимости от текущего значения счетчика., @Majenko
@glen_geek, Это код Arduino. Библиотека Aduino эффективно вызывает
while(true) loop();
https://www.arduino.cc/reference/en/language/structure/sketch/loop/, @Solomon Slow