Кнопки,Прерывания.

frielender
Offline
Зарегистрирован: 26.11.2014

Возможно ли к одному прерыванию подключить несколько кнопок, например 5 штук. И в прерывании определять какая из них была нажата?

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

Можно. Для этого нужно использовать логический элемент ИЛИ, который при упрощении можно свести к кучке диодов. Сигнал с каждой кнопки идет на вывод ардуины и через диод на вывод прерывания. А в прерывании мы проверяем выводы и находим активные.

 

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

аналоговую кнопку сделайте. Каждой кнопке на ножке будет соответстоввать свое напряжение. АЦП снимаете уровень. Хватит 1 ножки арудины

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Michal пишет:

аналоговую кнопку сделайте. Каждой кнопке на ножке будет соответстоввать свое напряжение. АЦП снимаете уровень. Хватит 1 ножки арудины

А прерывания куда?

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

NeiroN пишет:

Можно. Для этого нужно использовать логический элемент ИЛИ, который при упрощении можно свести к кучке диодов. Сигнал с каждой кнопки идет на вывод ардуины и через диод на вывод прерывания. А в прерывании мы проверяем выводы и находим активные.

Эту микросхему получится прикрутить?

74HC597

frielender
Offline
Зарегистрирован: 26.11.2014

1)Аналоговую клаву делал, только как к прерыванию ее "прикрепить"?

2)

Но как бороться с дребезгом, и что, если мне нужно много кнопок?

на каждую кнопку по выходу=расточительство

 

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

С дребезгом тригером Шмидта можно бороться.

frielender
Offline
Зарегистрирован: 26.11.2014

Все равно иногда бывает лишнее нажатие. Что я делаю не так)? Может как-то программно бороться можно?

Это просто пример, по которому я определяю был дребезг или нет.

01byte intPin = 0;  
02byte ledPin = 13;   
03volatile int x = 0;
04boolean LED=true;
05 
06void setup()
07{
08  attachInterrupt(intPin,pause,RISING);.
09  pinMode(ledPin, OUTPUT);
10  pinMode(7, INPUT);
11  pinMode(9, INPUT);
12  Serial.begin(9600);
13}
14 
15 
16void pause()
17{    
18int i=0;
19while(i <70) {i++; }           
20 
21     LED=!LED; // включаем/выключаем LED  
22    if ((digitalRead(7)==LOW)and(digitalRead(9)==HIGH))
23    {
24    x=x-1;
25    Serial.println(x);
26    } else
27    if ((digitalRead(7)==HIGH)and(digitalRead(9)==LOW))
28    {
29    x=x+1;
30    Serial.println(x);
31    }
32    if ((digitalRead(7)==HIGH)and(digitalRead(9)==HIGH))
33    {
34    Serial.println(x); 
35    }
36     
37 }
38 
39 void loop()
40{
41  digitalWrite(ledPin,LED);
42}

 

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

frielender, можно сделать прерывание по таймеру скажем раз в секунду, и в прерывании опрашивать кнопки. Тогда проблемы дребезга скорее всего не будет. Если с таймерами не очень дружите, то можно взять готовую библу типа timerOne.

frielender
Offline
Зарегистрирован: 26.11.2014

Спасибо за ответы, решил проблему с дребезгом. Но появилась другая проблемка...

Программа не выходит из прерывания(Это понятно  по светодиоду, который должен менять свое состояние в основной программе)

Я выяснил что это из-за части вывода меню на экран, если выводить что то в Serial, то все работает. В чем может быть проблема? И как мне выводить на экран через прерывание?

001<div>
002#include <Wire.h>
003#include <LiquidCrystal_I2C.h>
004byte intPin = 0;     // Номер прерывания, которое будет вызыватся.Контакт которому соответствует прерывание 2.
005byte ledPin = 13;    // Светодиод
006volatile int x = 0;  // volotile означает возможность внезапного, для основной программы, изменения переменной.
007                     // В данном случае изменение произойдет в прерывании
008volatile int y = 0;                    
009volatile int A = 10;                     
010boolean LED=true;    //Состояние светодиода
011// Set the LCD address to 0x27 for a 16 chars and 2 line display
012LiquidCrystal_I2C lcd(0x27, 16, 2);
013 
014void setup()
015{
016  attachInterrupt(intPin,pause,RISING);
017  pinMode(ledPin, OUTPUT);
018  pinMode(7, INPUT);
019  pinMode(9, INPUT);
020  Serial.begin(9600);
021  lcd.begin();
022  lcd.backlight();
023  lcd.setCursor(4,0);
024  lcd.print("WELCOME!");
025        
026}
027 
028 
029void pause()
030{    
031int i=0;
032while(i <70) {i++; }           
033 
034    if ((digitalRead(7)==LOW)&&(digitalRead(9)==HIGH))// OK
035    { if((A==10)||(A==20)) A++;
036      else
037      if((A==11)||(A==21)) A--;
038      Serial.println(A);
039    }
040    if ((digitalRead(7)==HIGH)&&(digitalRead(9)==LOW))// -
041    {
042      if(A==20) {A=10;}
043      if(A==11){ x--;}
044      if(A==12){ y--;}
045      Serial.println(A);
046    }
047    if ((digitalRead(7)==HIGH)&&(digitalRead(9)==HIGH))// +
048    {
049      if(A==10) {A=20;}
050      if(A==11){ x++;}
051      if(A==12){ y++;}
052      Serial.println(A);
053    }
054//////////////////////////////////////////////////////////////////////// Не выходит из прерывания из- за этой части, именно вывода на экран
055if (A==10)
056{ lcd.clear();
057  lcd.print("Main Menu");
058  lcd.setCursor(13,0);
059  lcd.print(">1<");
060  lcd.setCursor(0,1);
061  lcd.print("Speed");
062 
063}
064if(A==20)
065{ lcd.clear();
066  lcd.print("Main Menu");
067  lcd.setCursor(13,0);
068  lcd.print(">2<");
069  lcd.setCursor(0,1);
070  lcd.print("Animation");
071}
072if(A==11)
073{ lcd.clear();
074  lcd.print("Speed=");
075  lcd.setCursor(7,0);
076  lcd.print(x);
077  lcd.setCursor(4,1);
078  lcd.print("-  OK  +");
079}
080if(A==11)
081{ lcd.clear();
082  lcd.print("Animation#");
083  lcd.setCursor(11,0);
084  lcd.print(y);
085  lcd.setCursor(4,1);
086  lcd.print("-  OK  +"); 
087}
088 
089////////////////////////////////////////////////////////////////////////
090}
091 
092void loop()
093{
094digitalWrite(ledPin,HIGH);
095delay(1000);
096digitalWrite(ledPin,LOW);
097delay(1000);
098 
099}
100 
101 
102</div>
 
maksim
Offline
Зарегистрирован: 12.02.2012

frielender пишет:

Возможно ли к одному прерыванию подключить несколько кнопок, например 5 штук. И в прерывании определять какая из них была нажата?

PCINT

frielender пишет:

Может как-то программно бороться можно?

Не только можно, а нужно.

frielender пишет:

И как мне выводить на экран через прерывание?

 

frielender
Offline
Зарегистрирован: 26.11.2014

Получается,если у меня в loop  программа выполняется 20 сек, то мне придется ждать эти 20 секунд перед обновлением информации выводимой на экран?

maksim
Offline
Зарегистрирован: 12.02.2012

Просто не нужно блокировать основной цикл на 20 секунд.
Да и вообще ну сделали вы вывод на дисплей в фоновом режиме, и что дальше? Вот вы изменили скорость чего то там, ну и когда эти измения вступят в силу, если у вас основной цикл длится 20 секунд?

frielender
Offline
Зарегистрирован: 26.11.2014

Через 20 секунд вступят в силу мои изменения. Но ведь не раз в 20 секунд  экран обновляться будет. Тогда моджно "целый час " что-то настраивать, перемещаясь по меню. Я вероятно что-то не понимаю, но мне казалось что обновление экрана должно быть в момент  нажатия на кнопку, а не после выполнения основного цикла. Иначе экран теряет свою актуальность вообще.

bwn
Offline
Зарегистрирован: 25.08.2014

frielender пишет:

Через 20 секунд вступят в силу мои изменения. Но ведь не раз в 20 секунд  экран обновляться будет. Тогда моджно "целый час " что-то настраивать, перемещаясь по меню. Я вероятно что-то не понимаю, но мне казалось что обновление экрана должно быть в момент  нажатия на кнопку, а не после выполнения основного цикла. Иначе экран теряет свою актуальность вообще.

А это уже зависит от алгоритма, который вы накодите. Здесь, каждый сам кузнец своего счастья.

frielender
Offline
Зарегистрирован: 26.11.2014

Накодил) только не работает вывод на экран через прерывание.

bwn
Offline
Зарегистрирован: 25.08.2014

frielender пишет:

Накодил) только не работает вывод на экран через прерывание.

А вывод на экран через прерывание, это знаете ли моветонс. В прерываниях делаются минимально необходимые операции, а уже обсчет, экран и прочие действия в loop()/

bwn
Offline
Зарегистрирован: 25.08.2014

В целом это у вас и сделано, только если loop()20 секунд, то как выведет дисплей?

Ошибся, сделано не у вас, у maksim.

Делать по этому же принципу, только дисплей должен выводить информацию регулярно с минимально допустимым интервалом.

bwn
Offline
Зарегистрирован: 25.08.2014

и еще, вы упомянули "меню". Конкретизируйте, на каком этапе для вас становится критичной частота вывода на экран?

frielender
Offline
Зарегистрирован: 26.11.2014

Как вообще делается меню на устройстве, мб я координально что то делаю не так?

Сейчас вот так, но если программа в loop() будет длинной, и долгой в исполнении , то общение с экраном будет через большие промежутки времени,что не есть хорошо.

 

bwn
Offline
Зарегистрирован: 25.08.2014

Честно говоря, вы там начали делать жуткие вещи, мало что загнали в цикл, так еще и печатать оттуда пытаетесь. Пример правильного прерывания вам дал maksim, там необходимый минимум.

По уму, вам надо в прерывании определять сработку кнопки, а все остальное вне его.

frielender
Offline
Зарегистрирован: 26.11.2014

Да , я могу наделать ужасных вещей) только начал разбираться в этом.

Да вроде нету у меня цикла в прерывании...

Так тоже не правильно?

Для наглядности, по такому принципу организовано перемещение по меню.

bwn
Offline
Зарегистрирован: 25.08.2014

А что у вас делает строка 33? 033    int i=0; while(i <70) {i++; }

В целом лучше, но if-ы тоже не есть хорошо.

И еще, вы с кнопками на прерываниях заморочились для тренировки или есть некий сакральный смысл?

 

frielender
Offline
Зарегистрирован: 26.11.2014

*33 строчка, это я нашел на этом форуме, так советовали с дребезгом бороться, но так как у меня уже стоит тригер шмитта, это уже не нужно.

*А как же без ифов определить какая из кнопок нажата?

*И как возможно без прерывания? Если у меня в loop( ) будут выполняться какие-то действия, то нажатия на кнопки контроллер не "увидит".

bwn
Offline
Зарегистрирован: 25.08.2014

frielender пишет:

*33 строчка, это я нашел на этом форуме, так советовали с дребезгом бороться, но так как у меня уже стоит тригер шмитта, это уже не нужно.

*А как же без ифов определить какая из кнопок нажата?

*А как возможно без прерывания? Если у меня в loop( ) будут выполняться какие-то действия, то нажатия на кнопки контроллер не "увидит".

При нормальном loop() кнопки будут определятся без проблем. Прерывания обычно используют для быстротекущих процессов, нажатие кнопки к ним не относится. Не используйте delay(), входите в функции обработки по мере надобности (тайминги)  и цикл будет проходить быстро.

bwn
Offline
Зарегистрирован: 25.08.2014

Сейчас по вашей логике получается, что при каждом проходе loop() вы запрыгиваете в меню. Зачем? Меню это отдельная функция и должна вызыватся по какому то действию (пара кнопок нажато, длинное нажатие и т.д.). Если кнопки будут использоватся только для меню, то и исходите из этого. loop() отдельно, меню отдельно. Когда работаете с меню, loop() все равно стоит. Многозадачность это конечно круто, но вряд ли реализуемо.