roboforum.ru

Технический форум по робототехнике.

чередование кнопкой

чередование кнопкой

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 еще срабатывание динамика...
при работе выяснилось, что когда срабатывает динамик кнопку хоть затыкайся но динамик продолжает работать.
вопрос как прервать цикл работы динамика и продолжить действие скетча дальше?

Re: чередование кнопкой

sergey2x » 25 янв 2018, 10:51

Здесь важно понимать, что второй режим выполняется примерно 3 секунды и в это время никакой реакции на кнопки не будет.
Чтобы выйти из второго режима надо:
-выждать более 3 секунд, чтобы сработал блок "если кнопка НЕ нажата"
-нажать кнопку и удерживать более 3 секунд для срабатывания блока "если кнопка нажата"

Re: чередование кнопкой

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

Re: чередование кнопкой

sergey2x » 25 янв 2018, 13:44

digitalRead(A0)
digitalRead(14)
A0 равно 14?

Re: чередование кнопкой

loox » 25 янв 2018, 19:33

Да
но это не обозначает, что его не надо определять как вход и потягивать к плюсу.
loox

Re: чередование кнопкой

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");
  }
}

Re: чередование кнопкой

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 уровнем соответственно.

Re: чередование кнопкой

Angel71 » 26 янв 2018, 20:47

https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
прерывание на изменение и посматривая на время можно как избавлятся от дребезга, так и проверять, сколько времени кнопка нажата ("должна быть нажата минимум ...", "столько-то нажата это быстрое нажатие, делаем то-то", "вот столько это уже долгое нажатие, делаем ещё чего").
если нужно что бы выполнение действий в "режимах" прерывалось, можно этому немного помочь, написав упрощённый delay - в цикле проверять время и какой "флаг", который в прерывании менять. хотя это тоже не сильно лучше, по хорошему желателено хотя бы простенькая машина состояний или планировщик задач. для ардуины гугля не так уж и мало выдаёт, если в запрос добавлять чтот на подобии "yield", "scheduler", "tasks", "threads",...


Rambler\'s Top100 Mail.ru counter