Корпус кнопки и переключателя
Я разрабатываю проект для своего колледжа.
ПЛАН ПРОЕКТА: Есть 3 датчика (температура, акселерометр и влажность), которые будут непрерывно считывать соответствующие параметры. в промежутке, если я нажимаю кнопку «PushButton1» в течение 2 секунд, Arduino должен войти в режим программирования.
Режим программирования имеет 6 случаев переключения. Каждое дело выбирается одно за другим, даже когда кнопка «PushButton1» нажимается на короткое время.
Также, если я снова нажму кнопку «PushButton1» на 2 секунды в режиме программирования, Arduino должен выйти из режима программирования.
ПРОБЛЕМА: В моем текущем скетче мне нужно нажать кнопку «PushButton1» в течение 2 секунд в режиме программирования в течение 2 секунд, чтобы изменить регистр. Также я не понимаю, как выйти из цикла Switch Case.
Скетч прилагается к этой теме.
const int btn = 2;
const int ledPin = 13;
int selector = 0;
boolean volatile wait = false;
const unsigned long event=2000;
unsigned long a=0;
unsigned long b=0;
unsigned long c=0;
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(btn, INPUT);
attachInterrupt(digitalPinToInterrupt(btn),decoder,CHANGE);
}
void loop()
{
while(wait) { }
if (digitalRead(btn) == LOW) {
a = millis();
}
else
{
b = millis();
c=b-a;
Serial.println(c);
if (c>=event)
{
doSwitchStatement();
selector++;
if (selector >6)
{
selector = 0;
delay(500);
}
}
}
wait = true;
interrupts();
}
void decoder()
{
noInterrupts();
wait = false;
}
void doSwitchStatement()
{
switch(selector)
{
case 0:
Serial.println("Case 0");
break;
case 1:
Serial.println("Case 1");
break;
case 2:
Serial.println("Case 2");
break;
case 3:
Serial.println("Case 3");
break;
case 4:
Serial.println("Case 4");
break;
case 5:
Serial.println("Case 5");
break;
case 6:
Serial.println("Case 6");
break;
}
}
@swa8788, 👍0
Обсуждение1 ответ
Лучший ответ:
Я бы сделал это как простое состояние без блокировки while определить два логических значения
bool buttonPress = false;
bool inMenu = false;
и добавьте его в петлю.
Чтобы различать разные длины нажатия, вам нужно определить их. Нет ничего лучше «автоматического» распознавания короткого нажатия. Также используйте переменные, которые «говорят», облегчая чтение кода другими.
const unsigned long buttonPressLong = 2000; // 2 секунды
const unsigned long buttonPressShort = 250; // 0,25 секунды выполнимо
const unsigned long buttonPressDebounce = 50;
// устранение дребезга при слишком коротком нажатии. Спасибо, Эдгар Боне.
unsigned long buttonPressStart = 0;
Приведенная ниже программа делает то, что вам нужно (проверено в моей тестовой лаборатории uno).
Как уже прокомментировал Эдгар Боне, вам также следует отменить дребезг кнопки (поищите в WiKi), чтобы исключить нежелательные эффекты. Время, которое я использую, является практичным для моего оборудования, поэтому вы можете поиграть, глядя на монитор последовательного порта.
const int btn = 2;
const int ledPin = 13;
int selector = 0;
const unsigned long buttonPressLong = 2000; // 2 секунды
const unsigned long buttonPressShort = 250; // 0,25 секунды выполнимо
const unsigned long buttonPressDebounce = 50; // устранение дребезга при слишком коротком нажатии. Спасибо, Эдгар Боне.
unsigned long buttonPressStart = 0;
bool buttonPress = false;
bool inMenu = false;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(btn, INPUT);
}
void loop() {
if (digitalRead(btn) == LOW && !buttonPress ) {
buttonPressStart = millis();
buttonPress = true;
}
// Подпрограмма запускается только в том случае, если имело место предыдущее нажатие, в противном случае она игнорируется
else if (digitalRead(btn) == HIGH && buttonPress) {
if (millis() - buttonPressStart > buttonPressLong && millis() - buttonPressStart > buttonPressDebounce && inMenu) {
Serial.print("Long press: ");
Serial.println(millis() - buttonPressStart);
buttonPress = false;
inMenu = false;
}
if (millis() - buttonPressStart < buttonPressShort && millis() - buttonPressStart > buttonPressDebounce && !inMenu) {
Serial.print("First short press ");
inMenu = true;
}
if (millis() - buttonPressStart < buttonPressShort && millis() - buttonPressStart > buttonPressDebounce && inMenu) {
Serial.print("Short press: ");
Serial.println(millis() - buttonPressStart);
doSwitchStatement();
selector++;
if (selector > 6) {
selector = 0;
delay(500);
}
buttonPress = false;
}
}
// Здесь вы можете делать другие вещи, так как это не блокирует
}
doSwitchStatement(){...}// Остается таким же, как у вас
Посмотрите на используемый код, так как он не блокирует (конечно, есть возможности для улучшения), но может служить отправной точкой для ваших дальнейших экспериментов...
Большое спасибо за такую большую помощь. Я снова помещаю всю свою тему проекта., @swa8788
Пожалуйста, отметьте как принятое и спасибо за отзыв, @Codebreaker007
- Как использовать SPI на Arduino?
- Библиотека DHT.h не импортируется
- Светодиоды: разница между общим анодом и общим катодом
- Как повторить кусок кода
- Почему эта программа на C++ не может прочитать Serial.write() моего arduino?
- Как изменить переменную при нажатии кнопки, подключенной к контакту 2
- Отображение двоичных данных на светодиодах
- GSM-модуль IOT-GA6 Arduino + ошибка CME 58
Использование блокирующего оператора while в вашем цикле и прерывания - это уродливый способ выполнить то, что вы пытаетесь сделать. Ваша реализация заморозит приложение в этом цикле while(wait) за исключением случаев, когда состояние кнопки изменяется, что означает, что вы не можете ничего делать, кроме как реагировать на изменения состояния кнопки., @Duncan C
Где ваш код для чтения и отображения значений датчика?, @Duncan C