Технический форум по робототехнике.
andrys » 25 янв 2018, 09:13
пытаюсь понять алгоритм работы с кнопкой...
идея у меня такая - вывести на экран показания с датчиков температуры, давления и т.д. с возможностью кнопкой поочередного листания этих данных на экране.
решил для начала попрактиковаться на динамиках с двумя тонами.
- Код: Выделить всё • Развернуть
int regim = 1;
int flag = 0;
int buzzer1 = 9;
int buzzer2 = 10;
void setup()
{
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(buzzer1, OUTPUT); //объявляем пин как выход1
pinMode(buzzer2, OUTPUT); //объявляем пин как выход2
}
void loop()
{
if (digitalRead(A0) == HIGH && flag == 0) //если кнопка нажата
// и перемення flag равна 0 , то ...
{
regim++;
flag = 1;
//это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие
// плюс защита от "дребезга" 100%
if (regim > 4) //ограничим количество режимов
{
regim = 1; //так как мы используем только одну кнопку,
// то переключать режимы будем циклично
}
}
if (digitalRead(14) == LOW && flag == 1) //если кнопка НЕ нажата
//и переменная flag равна - 1 ,то ...
{
flag = 0; //обнуляем переменную "knopka"
}
if (regim == 1) //первый режим
{
digitalWrite(11, LOW); //выключаем все светодиоды
digitalWrite(12, LOW);
//здесь может быть любое ваше действие
}
if (regim == 2) //второй режим
{
digitalWrite(12, HIGH); //включае красный светодиод
digitalWrite(11, LOW);
tone (buzzer1, 261); //включаем на 261 Гц
delay(500); //на 500 миллисекунд
noTone(buzzer1); //выключаем динамик на 1 секунду
delay(1000);
tone(buzzer1, 493); //включаем на 493 Гц
delay(500); //на 500 миллисекунд
noTone(buzzer1);//выключаем динамик на 1 секунду
delay(1000);
//здесь может быть любое ваше действие
}
if (regim == 3) //третий режим
{
digitalWrite(11, HIGH); //включае зеленый светодиод
digitalWrite(12, LOW);
//здесь может быть любое ваше действие
}
if (regim == 4) //четвертый режим
{
digitalWrite(11, HIGH); //включаем светодиоды одновременно
digitalWrite(12, HIGH);
//здесь может быть любое ваше действие
}
}
нашел два скетча в интернете и соединил их. то есть добавил в скетч со светодиодами regim2 еще срабатывание динамика...
при работе выяснилось, что когда срабатывает динамик кнопку хоть затыкайся но динамик продолжает работать.
вопрос как прервать цикл работы динамика и продолжить действие скетча дальше?
sergey2x » 25 янв 2018, 10:51
Здесь важно понимать, что второй режим выполняется примерно 3 секунды и в это время никакой реакции на кнопки не будет.
Чтобы выйти из второго режима надо:
-выждать более 3 секунд, чтобы сработал блок "если кнопка НЕ нажата"
-нажать кнопку и удерживать более 3 секунд для срабатывания блока "если кнопка нажата"
loox » 25 янв 2018, 11:24
Andrus
1. Вы наверняка не полностью прописали условия входа\выхода в условии if... Для нахождения ошибки пропишите в каждом или в ошибочном режиме строку Serial.println( здесь перечислите условия входа\ выхода из режима) и по этим значениям увидите какая из переменных мешает Вам выйти из режима.
2. Изменение режима возможно только при нажатии кнопки и flag ==0. Это условие у Вас только при включении и нажатии кнопки 1 раз. После этого программа не будет реагировать на кнопку, т.к flag = 1
Вам рекомендации:
- при работе с кнопками всегда проверяйте : если нажата , то дождитеcь когда она будет отпущена и только после этого переходите дальше. Среднее время дребезга кнопки 20-25 mc
if (нажата)
{
delay(25);
if (нажата) {}
далее по тексту
}
Будьте внимательны, прописываете все очень точно - цифровые входы Вы прописали на вход и выходб а вывод - А0 у Вас ни как не определен. Не зависимо от того, что написано в аннотациях или уроках по arduino прописывайте все очень скурпулезно и точно. Версии компиляторов по разному реагируют на формальное определение pin и в особенности на определение переменных.
Пока все. О результате отпишитесь
loox
Добавлено спустя 25 минут 49 секунд:
Да, обязательно подтяните вход с кнопкой либо резистором 5-10ком к плюсу или прграммно pullup
sergey2x » 25 янв 2018, 13:44
digitalRead(A0)
digitalRead(14)
A0 равно 14?
loox » 25 янв 2018, 19:33
Да
но это не обозначает, что его не надо определять как вход и потягивать к плюсу.
loox
andrys » 26 янв 2018, 10:19
указал, что кнопка А0 и является выходом.
int button = A0;
pinMode(button, INPUT);
__прописал после каждого действия сериал принт... в мониторе порта еще раз подтвердилось, что переменная цикла бузера при нажатии кнопки не прекращается.
__по пункту 2 не совсем понял... как все таки изменить режим? ведь у меня и так указано flag ==0
__кнопка подключена через резистор 10к.
digitalRead(A0)
digitalRead(14)
__ошибочка исправил.
- Код: Выделить всё • Развернуть
int regim = 1;
int flag = 0;
int button = A0;
int buzzer1 = 9;
void setup()
{
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(buzzer1, OUTPUT); //объявляем пин как выход1
pinMode(button, INPUT);
Serial.begin(9600);
}
void loop()
{
if (digitalRead(A0) == HIGH && flag == 0) //если кнопка нажата
// и перемення flag равна 0 , то ...
{
regim++;
flag = 1;
if (regim > 4) //ограничим количество режимов
{
regim = 1; //так как мы используем только одну кнопку,
// то переключать режимы будем циклично
}
}
if (digitalRead(A0) == LOW && flag == 1) //если кнопка НЕ нажата
//и переменная flag равна - 1 ,то ...
{
flag == 0; //обнуляем переменную "knopka"
}
if (regim == 1) //первый режим
{
digitalWrite(11, LOW); //выключаем все светодиоды
digitalWrite(12, LOW);
Serial.println ("led 1 2 off");
//здесь может быть любое ваше действие
}
if (regim == 2) //второй режим
{
digitalWrite(12, HIGH); //включае красный светодиод
digitalWrite(11, LOW);
Serial.println ("led1 off");
tone (buzzer1, 261); //включаем на 261 Гц
delay(300); //на 500 миллисекунд
Serial.println ("buz1 on");
noTone(buzzer1); //выключаем динамик на 1 секунду
delay(1000);
Serial.println ("buz1 off");
tone(buzzer1, 493); //включаем на 493 Гц
delay(300); //на 500 миллисекунд
Serial.println ("buz2 on");
noTone(buzzer1);//выключаем динамик на 1 секунду
delay(1000);
Serial.println ("buz2 off");
//здесь может быть любое ваше действие
}
if (regim == 3) //третий режим
{
digitalWrite(11, HIGH); //включае зеленый светодиод
digitalWrite(12, LOW);
Serial.println ("led2 on");
//здесь может быть любое ваше действие
}
if (regim == 4) //четвертый режим
{
digitalWrite(11, HIGH); //включаем светодиоды одновременно
digitalWrite(12, HIGH);
//здесь может быть любое ваше действие
Serial.println ("led 1 2 on");
}
}
Scorpio » 26 янв 2018, 20:03
Кнопка обязательно сработает, если ее держать нажатой более 3х секунд )))
Попадая во второй режим, программа все время висит на delay, выскакивая из него на микроскопическое время, чтобы проверить состояние кнопки. Именно в этот момент кнопка д.б. нажата, чтобы переключиться на следующий режим. Попробуйте использовать для кнопки прерывания, либо счетчики для пауз + delay(100), чтобы постоянно проверять состояние кнопки.
Или решить проблему так:
- Код: Выделить всё • Развернуть
void setup()
{
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(buzzer1, OUTPUT); //объявляем пин как выход1
pinMode(button, INPUT);
Serial.begin(9600);
}
void loop()
{
if (digitalRead(A0) == HIGH && flag == 0) //если кнопка нажата
// и перемення flag равна 0 , то ...
{
regim++;
flag = 1;
if (regim > 4) //ограничим количество режимов
{
regim = 1; //так как мы используем только одну кнопку,
// то переключать режимы будем циклично
}
}
if (digitalRead(A0) == LOW && flag == 1) //если кнопка НЕ нажата
//и переменная flag равна - 1 ,то ...
{
flag == 0; //обнуляем переменную "knopka"
//}!!!!
if (regim == 1) //первый режим
{
digitalWrite(11, LOW); //выключаем все светодиоды
digitalWrite(12, LOW);
Serial.println ("led 1 2 off");
//здесь может быть любое ваше действие
}
if (regim == 2) //второй режим
{
digitalWrite(12, HIGH); //включае красный светодиод
digitalWrite(11, LOW);
Serial.println ("led1 off");
tone (buzzer1, 261); //включаем на 261 Гц
delay(300); //на 500 миллисекунд
Serial.println ("buz1 on");
noTone(buzzer1); //выключаем динамик на 1 секунду
delay(1000);
Serial.println ("buz1 off");
tone(buzzer1, 493); //включаем на 493 Гц
delay(300); //на 500 миллисекунд
Serial.println ("buz2 on");
noTone(buzzer1);//выключаем динамик на 1 секунду
delay(1000);
Serial.println ("buz2 off");
//здесь может быть любое ваше действие
}
if (regim == 3) //третий режим
{
digitalWrite(11, HIGH); //включае зеленый светодиод
digitalWrite(12, LOW);
Serial.println ("led2 on");
//здесь может быть любое ваше действие
}
if (regim == 4) //четвертый режим
{
digitalWrite(11, HIGH); //включаем светодиоды одновременно
digitalWrite(12, HIGH);
//здесь может быть любое ваше действие
Serial.println ("led 1 2 on");
}
}//!!!!!
}
Вариантов много.
Сама кнопка аппаратно тоже выполнена не правильно. Резистор 10к д.б. подключен между входным портом и + питания (либо использовать pinMode(X,INPUT_PULLUP)). А кнопкой соединять вход с минусом питания. В этом случае исключаются наводки на болтающуюся в воздухе входную ногу. Нажатие кнопки будет определяться LOW уровнем соответственно.
Angel71 » 26 янв 2018, 20:47
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/прерывание на изменение и посматривая на время можно как избавлятся от дребезга, так и проверять, сколько времени кнопка нажата ("должна быть нажата минимум ...", "столько-то нажата это быстрое нажатие, делаем то-то", "вот столько это уже долгое нажатие, делаем ещё чего").
если нужно что бы выполнение действий в "режимах" прерывалось, можно этому немного помочь, написав упрощённый delay - в цикле проверять время и какой "флаг", который в прерывании менять. хотя это тоже не сильно лучше, по хорошему желателено хотя бы простенькая машина состояний или планировщик задач. для ардуины гугля не так уж и мало выдаёт, если в запрос добавлять чтот на подобии "yield", "scheduler", "tasks", "threads",...