Работа с кнопками

Arduino
Автор темы, Сержант
Сержант
Аватара
Arduino
Автор темы, Сержант
Сержант
Сообщения: 64
Зарегистрирован: 19 апреля 2017
С нами: 6 лет 11 месяцев

#1 Arduino » 4 января 2018, 18:24

Ардуино и кнопка.

Кнопка – простейшее электромеханическое устройство. Кнопки бывают двух видов.
1.Кнопки (переключатели) с фиксированным положением.
2.Так называемые тактовые кнопки (которые возвращаются в исходное положение).

С первыми все ясно, а вот как работать со вторыми ?

В этой статье я расскажу, как правильно подключить кнопку к МК и как работать с ней программно. Так же расскажу, как подключить несколько кнопок к одному пину МК.

Обычно, самый первый раз, кнопку пытаются подключить вот так.
Это НЕ ПРАВИЛЬНОЕ подключение.
Это НЕ ПРАВИЛЬНОЕ подключение.jpg
Это НЕ ПРАВИЛЬНОЕ подключение
Это НЕ ПРАВИЛЬНОЕ подключение.jpg (16.43 КБ) 1474 просмотра

Дело в том, что пин МК (в режиме входа) должен иметь заранее известное состояние (1или 0).
В «подвешенном» состоянии будет собирать внешние наводки (статические, электрические и электромагнитные излучения).
Чтобы привести пин в заранее известное состояние и используют подтягивающие резисторы.
Они бывают двух видов, верхние и нижние подтяжки.
Верхние (pull-up) подключаются к плюсу питания и нижние (pull-down) к минусу.
В ардуино есть встроенные подтягивающие резисторы (pull-up) которые можно включить программно, но я не советую их использовать.

ПРАВИЛЬНОЕ подключение кнопки.
ПРАВИЛЬНОЕ подключение кнопки..jpg
ПРАВИЛЬНОЕ подключение кнопки
ПРАВИЛЬНОЕ подключение кнопки..jpg (18.17 КБ) 1474 просмотра

В данном случае, когда кнопка отключена, пин будет подключен к земле через резистор, сопротивление которого заведомо меньше внутреннего сопротивления пина.
Поэтому наводка, попавшая на пин, стечет в землю. Если же подключен полезный сигнал (+5в) то он будет стекать в пин (незначительная часть сигнала стечет в землю через подтяжку).
В итоге, при нажатой кнопке, у нас будет стабильный сигнал (+5в), а при отпущенной кнопке будет стабильный ноль.
Рассмотрим несколько простых программных примеров.

Код: Выделить всё

void setup() 
 
{ 
 pinMode
(13, OUTPUT); 
 
} 

 void loop
() 
 
{ 
 digitalWrite
(13,analogRead(14)); //состояние входа равно состоянию выхода 
 

Это самый простой пример. Немного усложним его

Код: Выделить всё

void setup() 
 
{ 
 pinMode
(13, OUTPUT); 
 
} 

 void loop
() 
 
{ 
 if
(digitalRead(14)==HIGH)//если кнопка нажата ... 
 { 
 digitalWrite
(13,HIGH);//включаем светодиод 
 } 
 else
//если не нажата... 
 { 
 digitalWrite
(13,LOW);//выключаем 
 } 
 
}

Этот пример можно инвертировать. Когда кнопка не жата светодиод горит, когда нажата – нет. Идем дальше.

Код: Выделить всё

void setup()     
 
{         
      pinMode
(13, OUTPUT);                    
 
} 

 void loop
() 
 
{ 
      if
(digitalRead(14)==HIGH)//если кнопка нажата ... 
      { 
      digitalWrite
(13,!digitalRead(13));//инвертируем состояние пина 

      delay(500);//небольшая защита от "дребезга" контактов кнопки 
      }           
 
}

Если удерживать кнопку, то получим мерцание светодиода с частотой заданной функией delay.
А если нам нужно включить что то по удержанию кнопки?
Для этого введем переменную val.

Код: Выделить всё

int val=0; 

 void setup
()     
 
{      
      pinMode
(13, OUTPUT);                   
 
} 

 void loop
() 
 
{ 
      if
(digitalRead(14)==HIGH)//если кнопка нажата ... 
      { 
        val
++;// прибавляем к переменной 1 при каждой смене цикла.       
      delay(500);//небольшая защита от "дребезга" контактов кнопки 
      } 
      else 
      
{ 
        val
=0; 
      
}      
      if
(val>=5) 
      
{ 
        digitalWrite
(13,!digitalRead(13));//инвертируем состояние пина 
        val=0; 
      
}          
 
} 

Здесь я использовал простейший «самодельный» таймер. Рассмотрим пример с более сложным таймером.

Код: Выделить всё

long previousMillis = 0; 
 int val
=0; 

 void setup
()    
 
{     
     pinMode
(13, OUTPUT);                 
 
} 

 void loop
() 
 
{ 
     if
(digitalRead(14)==HIGH)//если кнопка нажата ... 
     {       
      if 
(millis() -previousMillis >500)    
     
{ 
        previousMillis 
= millis();     
        val
++; 
     
} 
     
} 
     else 
     
{ 
       val
=0; 
     
}    
     if
(val>=5) 
     
{ 
       digitalWrite
(13,!digitalRead(13));//инвертируем состояние пина 
       val=0; 
     
}        
 
} 

Основной плюс этого таймера это то, что он не использует паразитную функцию delay и, соответственно, не тормозит программу.
Очень не советую использовать функцию pulseIn для данных целей (да и вообще не советую).
Потому что эта функция использует все программные таймеры ардуино.
С функцией pulseIn НЕ будут работать
Tone()
Millis()
analogWrite()

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

Код: Выделить всё

int flag=0; 

void setup
()    
{   
    pinMode
(13, OUTPUT);               
} 

void loop
() 
{     
     if
(digitalRead(14)==HIGH&&flag==0)//если кнопка нажата    
     // и перемення flag равна 0 , то ... 
     {     
       digitalWrite
(13,!digitalRead(13)); 
       flag
=1; 
        
//это нужно для того что бы с каждым нажатием кнопки 
        //происходило только одно действие 
        // плюс защита от "дребезга"  100% 
     } 
        
      if
(digitalRead(14)==LOW&&flag==1)//если кнопка НЕ нажата 
     //и переменная flag равна - 1 ,то ... 
     {      
        flag
=0;//обнуляем переменную flag 
     } 
}

Алгоритм такой. Нажали кнопку – загорелся светодиод, удерживаем кнопку – ничего не происходит (светодиод горит). Отпустили кнопку – светодиод горит.
Для того чтобы погасить светодиод нужно повторно нажать кнопку.
Т.е. нажали – горит, отпустили, нажали – не горит.
Можно инвертировать действие вот так

Код: Выделить всё

int flag=0; 

 void setup
()   
 
{  
    pinMode
(13, OUTPUT);             
 
} 

 void loop
() 
 
{    
     if
(digitalRead(14)==HIGH&&flag==0)//если кнопка нажата   
     // и перемення flag равна 0 , то ... 
     {   
       flag
=1; 
        
//это нужно для того что бы с каждым нажатием кнопки 
        //происходило только одно действие 
        // плюс защита от "дребезга"  100% 
     } 
       
      if
(digitalRead(14)==LOW&&flag==1)//если кнопка НЕ нажата 
     //и переменная flag равна - 1 ,то ... 
     { 
         digitalWrite
(13,!digitalRead(13)); 
        flag
=0;//обнуляем переменную flag 
     } 
 
}

Нажали – ничего, отпустили – горит. Повторно нажали, отпустили – не горит.
Теперь сделаем небольшое меню.
Меню будет содержать четыре режима (можно сколько угодно, но для примера хватит и четырех).
Меню будет управлять двумя светодиодами.
Введем еще одну переменную – regim.

Код: Выделить всё

int regim=1; 
 int flag
=0; 

 void setup
()   
 
{ 
    pinMode
(10,OUTPUT);    
 pinMode
(9,OUTPUT);      
 
} 

 void loop
() 
 
{     
     if
(digitalRead(14)==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
(9,LOW);//выключаем все светодиоды 
      digitalWrite(10,LOW); 
      
//здесь может быть любое ваше действие 
    } 
    if
(regim==2)//второй режим 
    { 
      digitalWrite
(10,HIGH);//включае красный светодиод 
      digitalWrite(9,LOW);  
      
//здесь может быть любое ваше действие 
    } 
      
    if
(regim==3)//третий режим 
    { 
      digitalWrite
(9,HIGH);//включае зеленый светодиод 
      digitalWrite(10,LOW); 
      
//здесь может быть любое ваше действие 
    } 
      
    if
(regim==4)//четвертый режим 
    {    
      digitalWrite
(9,HIGH);//включаем светодиоды одновременно 
      digitalWrite(10,HIGH); 
      
//здесь может быть любое ваше действие 
    }     
 
}


  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Программирование»

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 4 гостя