Мое переключение светодиодов не работает так, как я хочу
Я хочу переключать светодиоды, поэтому написал это:
int led=13, button=12;
void setup()
{
// поместите сюда код установки для однократного запуска:
pinMode(led,OUTPUT);
pinMode(button,INPUT);
}
void loop()
{
// поместите сюда ваш основной код для многократного запуска:
if(digitalRead(button)==HIGH && digitalRead(led)==LOW)
{
digitalWrite(led,HIGH);
}
if(digitalRead(button)==HIGH && digitalRead(led)==HIGH)
{
digitalWrite(led,LOW);
}
}
Но это не работает, иногда мне нужно нажать кнопку много раз, чтобы включить или выключить... а иногда и всего одним нажатием.
Я видел это видео, но плохо его понял: https://www.youtube.com/watch?v=aMato4olzi8&t=415s
В любом случае, я не знаю, почему мой способ не работает.
@sumer fattoum, 👍1
Обсуждение1 ответ
Лучший ответ:
Есть несколько проблем с вашим подходом.
Кажется, у вас кнопка перевернута. Вы должны подключить кнопку так, чтобы она находилась между контактом и землей. Таким образом, при нажатии он должен читаться как НИЗКИЙ, а не ВЫСОКИЙ. Он также должен иметь pinMode(pin, INPUT_PULLUP) вместо INPUT. Если кнопка подключена так, как у вас написано HIGH, вам понадобится дополнительный резистор для каждой кнопки. Если он подключен правильно, где он читает НИЗКИЙ, тогда ему не нужно ничего дополнительно.
Если первое утверждение if истинно, и кнопка нажата, и загорается светодиод, как вы думаете, каковы шансы, что вы достаточно быстро уберете палец с кнопки за 62,5 наносекунды? чтобы перейти к следующему оператору if? Этого не произойдет, поэтому кнопка все еще нажата там, и теперь горит светодиод, поэтому эта линия сразу же отключает его. Только в том редком случае, когда вы уберете палец с кнопки в нужный момент, светодиод останется гореть. Чтобы решить эту проблему, посмотрите «Пример изменения состояния», который поставляется с IDE. Он показывает, как отслеживать последнее состояние кнопки в переменной, чтобы вы могли действовать только один раз, когда кнопка действительно меняет состояние.
После того как вы разберетесь с этим, вы заметите, что каждый раз, когда вы нажимаете кнопку, регистрируются десятки нажатий. Это отказ переключателя. Это термин, который вы должны найти в Google. Контакты замыкаются и размыкаются очень быстро в промежуточном состоянии между нажатым и ненажатым. Но вам нужно решить первые две проблемы, прежде чем беспокоиться о отказе.
хорошо...помогло...спасибо, @sumer fattoum
Я проверил пример изменения состояния, но не понял, почему задержка для отскока используется именно в этом месте? зачем устанавливать lastButtonState = buttonState; так как состояние кнопки в любом случае вернется к 0, когда кнопка будет отпущена, любое lastButtonState в любом случае было 0 ... так что в нем нет никаких изменений?, @sumer fattoum
Вы делаете это, чтобы вы могли сказать, когда состояние изменилось с цикла на следующее., @Delta_G
Таким образом, небольшая задержка в 50 мс предназначена для обнаружения дребезга переключателя. Вы знаете, что такое дребезг переключателя? Когда вы нажимаете кнопку, есть небольшой период времени, когда контакты почти замыкаются, и они как бы замыкаются, а затем разрываются, а затем замыкаются и разрываются снова и снова, когда они сближаются и почти соприкасаются. Затем, как только они соприкасаются полностью, они закрываются. То же самое происходит, когда выключатель только начинает открываться. Таким образом, вы добавляете небольшую задержку, чтобы пропустить все эти быстрые изменения., @Delta_G
Вы правы, что buttonState будет иметь 0 при отпускании, но при нажатии будет 1. Таким образом, кнопка не нажата, а buttonState и lastButtonState равны 0. Затем вы нажимаете кнопку. Когда кнопка читается, теперь она ВЫСОКАЯ, но lastButtonState все еще НИЗКАЯ, теперь мы обнаружили изменение состояния. Так что мы можем принять некоторые меры. В следующий раз кнопка по-прежнему будет иметь значение HIGH, но lastButtonState теперь также будет HIGH, потому что мы установили его в соответствии с buttonState в конце цикла. Так что ничего не происходит, потому что они одинаковы., @Delta_G
И теперь мы реагируем только на смену состояния, а не постоянно что-то делаем, пока кнопка HIGH. Это позволяет нам что-то делать один раз за нажатие. Мы реагируем только при первом нажатии. Когда вы отпускаете кнопку, она считывается и получает НИЗКИЙ, но lastButtonState по-прежнему ВЫСОКИЙ, поэтому вы можете один раз отреагировать на выпуск, если хотите, а затем в конце цикла lastButtonState устанавливается в buttonState, который сейчас НИЗКИЙ, и еще раз они совпадают. Еще раз мы обнаружили изменение с ВЫСОКОГО на НИЗКИЙ., @Delta_G
большое спасибо... да понял, @sumer fattoum
поэтому в примере задержка во избежание подпрыгивания - это когда условие if завершено .... но подпрыгивание происходит при однократном нажатии и однократном отпускании кнопки, поэтому, чтобы избежать подпрыгивания, почему написано только из если, а не так, если ( buttonState == HIGH) delay (50), чтобы он мог подождать, пока кнопка не станет стабильной, прежде чем включить светодиод ?, @sumer fattoum
Вы не ждете, пока кнопка станет стабильной. Вы просто тратите время, чтобы не прочитать его. Таким образом, если кнопка была низкой, а теперь стала высокой, вы знаете, что она была нажата. Вы можете отреагировать в этот момент. Вам не нужно ждать, пока он перестанет подпрыгивать, чтобы отреагировать на это. Вам нужно подождать, пока он перестанет подпрыгивать, чтобы реагировать на что-либо еще, и поэтому мы убираем 50 мс., @Delta_G
Имейте в виду, что задержка на самом деле не связана с устранением дребезга. Это не так. Это просто хак, чтобы вы не видели отскока. Если вы читаете кнопку только один раз каждые 50 мс, вы никогда не увидите, как она отскакивает., @Delta_G
ага..хорошо.. задержка предназначена для чтения кнопки, а не для цифровой записи, вы сказали выше, если кнопка была низкой, а теперь высокой, вы знаете, что она была нажата. Вы можете отреагировать в этот момент. Вам не нужно ждать, пока он перестанет подпрыгивать, чтобы отреагировать на это. но в этом случае реакция не является неправильной? потому что подпрыгивание - это случайная последовательность 0 и 1 до того, как придет настоящая 1 ... так что Programm отреагирует на эту серию? или нет ?, @sumer fattoum
Он просто реагирует на первый HIGH, который он получает. Неважно, что за этим стоит куча отскоков. Нет никакой другой причины, по которой вы бы читали ВЫСОКИЙ, за исключением того, что кто-то нажал кнопку., @Delta_G
ахсо..да теперь все ясно...большое спасибо, @sumer fattoum
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Одно слово: прыгать., @Majenko
«Я хочу переключать светодиоды» ... вы не объяснили, как вы хотите, чтобы программа работала, @jsotola
вы не понимаете, что loop() повторяется 10000 раз в секунду .... вы проверяете, нажата ли кнопка, что происходит снова и снова .... вам нужно дождаться «перехода» между «не нажато» и "нажал"....что происходит только один раз при нажатии на кнопку, @jsotola
хорошо...помогло...спасибо, @sumer fattoum
да правильно, так что во второй раз, когда кнопка нажата, он пытается включить и выключить светодиод в ту же секунду, @sumer fattoum