Последующий вопрос о кнопке и переключателе
ПОСТАНОВКА ПРОБЛЕМЫ:
- Контур измеряет различные параметры (температуру, влажность, д.) через постоянно подключенные к нему датчики.
- Когда кнопка нажимается и удерживается в течение 2 секунд между ними, Arduino должна войти в режим настройки. (Я использовал петлю IF и для этого используется функция millis() )
- В режиме настройки есть 6 экранов, которые появляются один за другим.
- После того, как Arduino войдет в режим настройки, должен появиться случай переключения 0 (экран 1) (для этого я использовал последовательный монитор).
- Теперь, если я нажму ту же кнопку и отпущу через мгновение, должен появиться следующий вариант Switch 1 (экран 2).
- Шаг 5 будет повторяться до случая переключения 5 (экран 6).
- После варианта Switch 5 цикл переходит к варианту Switch 0 (SCREEN1), затем к варианту Switch 1, варианту Switch 2 и т. д.
- Если в промежутке между вышеуказанным циклом Switch Case нажать кнопку и удерживать ее в течение 2 секунд, цикл Switch case должен завершиться, и Arduino должен вернуться к MAIN LOOP(), где он измеряет параметр датчика.
- Опять же, если кнопка нажата и удерживается в течение 2 секунд между процессом измерения, Arduino должен войти в режим настройки.
Соображения:
- Кнопка подключена к контакту 2 Arduino (АКТИВНЫЙ НИЗКИЙ)
- Вход на выводе 2 рассматривается как прерывание, поэтому Arduino предоставляет услуги в любой момент времени.
- Последовательный монитор Arduino используется для демонстрации выходных данных Screen1-Screen6.
- Конденсатор 0,1 мкФ используется на кнопке для устранения дребезга . И резистор 10K, 0,25 Вт подключен от VCC к Pin №2
- Код для определения параметров (температуры, влажности и т. д.) еще предстоит написать.
ДОСТИЖЕНИЕ: До пункта № 7 ПОСТАНОВЛЕНИЯ ПРОБЛЕМЫ код работает нормально.
ОШИБКА: Если я нажимаю кнопку в течение 2 секунд в цикле SWITCH CASE, Arduino выходит из SWITCH CASE и переходит в MAIN LOOP(), но снова возвращается в цикл SWITCH CASE(). Он должен снова попросить нажать кнопку в течение 2 секунд, чтобы войти в режим настройки.
const int btn = 2;
const int ledPin = 13;
int selector = 0;
boolean volatile wait = false;
const unsigned long event=2000;
unsigned long previous1=0;
unsigned long current1=0;
unsigned long sum1=0;
unsigned long previous2=0;
unsigned long current2=0;
unsigned long sum2=0;
bool buttonPress = false;
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(btn, INPUT);
attachInterrupt(digitalPinToInterrupt(btn),decoder,CHANGE);
}
void loop()
{
if (digitalRead(btn) ==LOW && !buttonPress)
{
previous1 = millis();
buttonPress = true;
}
else if (digitalRead(btn) == HIGH && buttonPress)
{
current1 = millis();
sum1=current1-previous1;
Serial.println(sum1);
Serial.println("SUM1");
if (sum1>=event)
{ BREAK1:
doSwitchCase();
selector++;
goto BREAK1;
if (selector >6)
{
selector = 0;
delay(500);
}
}
buttonPress = false;
}
wait = true;
interrupts();
}
void decoder()
{
noInterrupts();
wait = false;
}
void doSwitchCase()
{
switch(selector)
{
case 0:
Serial.println("SCREEN1");
while (digitalRead(btn)!=LOW) ;
previous2 =millis();
while (digitalRead(btn)!=HIGH) ;
current2=millis();
sum2=current2-previous2;
if(sum2>=event)
{
Serial.println(sum2);
loop();
}
break;
case 1:
Serial.println("SCREEN2");
while (digitalRead(btn)!=LOW) ;
previous2 =millis();
while (digitalRead(btn)!=HIGH) ;
current2=millis();
sum2=current2-previous2;
if(sum2>=event)
{
Serial.println(sum2);
loop();
}
break;
case 2:
Serial.println("SCREEN3");
while (digitalRead(btn)!=LOW) ;
previous2 =millis();
while (digitalRead(btn)!=HIGH) ;
current2=millis();
sum2=current2-previous2;
if(sum2>=event)
{
Serial.println(sum2);
loop();
}
break;
case 3:
Serial.println("SCREEN4");
while (digitalRead(btn)!=LOW) ;
previous2 =millis();
while (digitalRead(btn)!=HIGH) ;
current2=millis();
sum2=current2-previous2;
if(sum2>=event)
{
Serial.println(sum2);
loop();
}
break;
case 4:
Serial.println("SCREEN5");
while (digitalRead(btn)!=LOW) ;
previous2 =millis();
while (digitalRead(btn)!=HIGH) ;
current2=millis();
sum2=current2-previous2;
if(sum2>=event)
{
Serial.println(sum2);
loop();
}
break;
case 5:
Serial.println("SCREEN6");
while (digitalRead(btn)!=LOW) ;
previous2 =millis();
while (digitalRead(btn)!=HIGH) ;
current2=millis();
sum2=current2-previous2;
if(sum2>=event)
{
Serial.println(sum2);
loop();
}
break;
}
}
@swa8788, 👍0
1 ответ
Одно примечание перед тем, как НИКОГДА не использовать goto в C++, это плохой стиль и делает в объектно-ориентированном языке на 99,9% бессмысленным. Чтобы войти в регистр переключателя после двухсекундного нажатия, вам нужно всего лишь ввести одно утверждение в соответствии с исходным предложением. Я не читал ваш код, так как он становится нечитаемым, чем больше функций вы хотите добавить. Подумайте о его рефакторинге, иначе вам не повезет с помощью (поскольку никто не мучает себя каотичным чужим кодом:
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 < buttonPressLong && millis() - buttonPressStart > buttonPressDebounce && !inMenu) { // ЭТО ИЗМЕНЕНИЕ
Serial.print("First long 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(){...}// Остается таким же, как у вас
Я только что изменил 1 оператор (и 1 отладочное сообщение), чтобы получить то, что вы хотите увидеть // ВОТ ИЗМЕНЕНИЕ
- Как использовать SPI на Arduino?
- Библиотека DHT.h не импортируется
- Светодиоды: разница между общим анодом и общим катодом
- Как повторить кусок кода
- Почему необходимо использовать ключевое слово volatile для глобальных переменных при обработке прерываний в ардуино?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Как правильно использовать volatile переменные в Arduino?