Amateur Radio Station R9AL

      Продолжаем эксперименты с кнопкой. Используем схему с предыдущего урока, только теперь попробуем зажигать установленный на плате Ардуино светодиод L. Этот светодиод уже подключен к выводу 13.



Загружаем скетч:

boolean btn;
                          // Объявление переменной btn
void setup(){
   pinMode(8, INPUT);     // Программируем вывод D8 как вход
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}
 
void loop() {
  btn = digitalRead(8);   // Присваиваем переменной btn значение вывода D8
  digitalWrite(13, btn);  // Выводим переменную btn на вывод 13
}
После запуска программы светодиод L будет светиться, но если нажать на кнопку - светодиод погаснет.

Усложним задачу. Давайте сделаем так, чтобы при нажатии на кнопку, светодиод L менял бы свое состояние на противоположенное и оставался бы таким до следующего нажатия. Ну или говоря проще, нажали кнопку - светодиод зажегся, нажали еще раз - светодиод погас. Для этого, в программу нужно ввести еще одну переменные led, которая будет помнить состояние светодиода.

boolean btn;  //Объявление переменной кнопка
boolean led;  //Объявление переменной светодиод
                          
void setup(){
   pinMode(8, INPUT);     // Программируем вывод D8 как вход
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}

void loop() {
  btn = digitalRead(8);      // Присваиваем переменной btn значение вывода D8
  if (!btn)                  // если кнопка нажата, то...   
    {   		     // ...переменной led присвоить противоположенное 
      led=!led;              // значение  
      digitalWrite(13, led); // Выводим переменную led на вывод 13
	}
}


Кроме того, в программе появился условный оператор if, который проверяет истинно ли выражение в его скобках или нет, если истинно, то выполняются операторы, которые размещены в фигурных скобках, если ложно, то не выполняются. Синтаксис оператора if:
if (логическое выражение)
{
// выполнять действия
}
В данном случае, если кнопка нажата (btn=false), то выражение !btn (противоположенное значение btn, ели btn==false, то !btn==true) - истинно, а значит выполняются команды в фигурных скобках: переменная led меняет свое значение на противоположенное и теперь уже новое значение переменной led выводится на 13 вывод, к которому подключен светодиод.

Эту программу можно записать еще проще:
boolean led;

void setup(){
   pinMode(8, INPUT);     // Программируем вывод D8 как вход
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}

void loop() {
boolean btn = digitalRead(8);      // Присваиваем переменной btn значение вывода D8
  if (!btn) led=!led;              // ...переменной led присвоить противоположенное значение  
digitalWrite(13, led);             // Выводим переменную led на вывод 13
}
Фигурные скобки после оператора if могут быть опущены. Если так сделано, то только следующая строка (обозначенная точкой с запятой) становится оператором, выполняемым в операторе if. В данном случае, это оператор присвоения переменной led противоположенного значения, а оператор вывода переменной на 13 пин выполняется всегда, вне зависимости от условия, проверяемого оператором if.

Давайте загрузим эту программу и посмотрим как она работает.

Выясняется что она работает, но как-то не очень хорошо...

В чем же дело?

Все дело в том, что замыкание и размыкание пластин кнопки происходит не сразу, при сближении пластин, между пластинами возникают микроискры, что воспринимается как многократное замыкание и размыкание, пока зазор между пластинами полностью не исчезнет. При размыкании происходит похожий процесс, пока зазор между пластинами не станет достаточно большим. Этот эффект называется дребезгом (англ. bounce) и его нужно учитывать.



Можно практически исключить дребезг, подключив параллельно кнопке конденсатор ёмкостью 10-47 нФ



Но можно просто учесть эффект дребезга в нашей программе, все что нам нужно сделать - просто ввести еще одно условие:

boolean led;

void setup(){
   pinMode(8, INPUT);     // Программируем вывод D8 как вход
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}

void loop() 
{
  boolean btn = digitalRead(8);    // Присваиваем переменной btn значение вывода D8
  if (!btn)                        // Если кнопка нажата...
    {
     delay(10);
     boolean btn = digitalRead(8); // Присваиваем переменной btn значение вывода D8
     if (!btn) led=!led;           // если кнопка нажата, переменной led присвоить противоположенное значение  
     digitalWrite(13, led);        // Выводим переменную led на вывод 13
     delay(1000);                  // Ждем 1 секунду.
    }
}


Работает это так: При нажатии на кнопку, при появлении первого дребезгового импульса - сработает первое условие, в результате которого программа остановится на 10 миллисекунд. За это время все переходные процессы прекратятся и если кнопка действительно нажата - сработает второе условие и светодиод переключится в противоположенное состояние. Но у этой схемы есть один и весьма ощутимый недостаток (хотя в некоторых случаях можно это использовать) - если кнопка достаточно долго нажата, светодиод начнем мигать, с частотой примерно 1 раз в секунду, т.е. данная программа требует для правильной работы не слишком долгих нажатий. Можно ли этого избежать? Конечно! Нужно просто ввести еще одну переменную, которая будет отслеживать отпускалась ли кнопка после нажатия. Назовем её btnUp и перепишем еще раз нашу программу
boolean led;
boolean btnUp = true;     // была ли кнопка отпущена?

void setup(){
   pinMode(8, INPUT);     // Программируем вывод D8 как вход
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}

void loop() 
{
  boolean btn = digitalRead(8);    // Присваиваем переменной btn значение вывода D8
  if (!btn && btnUp)               // Если кнопка нажата, но до этого была отпущена
    {
     delay(10);
     boolean btn = digitalRead(8); // Присваиваем переменной btn значение вывода D8
     if (!btn) led=!led;           // если кнопка нажата, переменной led присвоить противоположенное значение  
     digitalWrite(13, led);        // Выводим переменную led на вывод 13
     delay(1000);                  // Ждем 1 секунду.
    }
  btnUp = btn;                     // запоминаем последнее состояние кнопки для нового цикла
}



В этой программе первое условие изменилось, теперь мы проверяем истинность выражения (!btn && btnUp), то есть теперь мы требуем соблюдение истинности сразу двух событий, и кнопка должна быть нажата и до того как она нажата она должна быть отпущена. Только в этом случае у нас сработает первое условие, а после выполнения второго условия значение переменной btnUp станет ложным и будет таким пока кнопка нажата, что запретит срабатывания первого условия. Как только кнопка будет отпущена - переменная btnUp примет истинное значение и программа станет готова к следующему нажатию.

Рассмотрим еще одну схему:



Здесь у нас уже две кнопки, одна по прежнему подключена к выводу 8, вторую подключим, например к выводу 7. Оба вывода имеют подтяжку к плюсу питания. Теперь напишем программу, которая позволит нажатием одной кнопки включать светодиод L, а второй кнопкой - его выключать. Программа получилось очень простая:
int led;
void setup(){
   pinMode(7, INPUT);     // Программируем вывод D8 как вход
   pinMode(8, INPUT);     // Программируем вывод D8 как вход
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}

void loop() 
{                               
  if (!digitalRead(7)) led=1;
  if (!digitalRead(8)) led=0;  
  digitalWrite(13, led);
}
Попробуйте самостоятельно разобраться как она работает.

if...else

Конструкция if..else предоставляет больший контроль над процессом выполнения кода, чем базовый оператор if, который мы рассмотрели выше, позволяя осуществлять несколько проверок, объединенных вместе. Например, аналоговый вход может быть проверен и выполнено одно действие, если на входе меньше 500, или другое действие, если на входе 500 или больше. Код при этом может выглядеть так:
if (pin_analog_input < 500)
{
  // действие A
}
else
{
  // действие B
}
Else позволяет делать отличную от указанной в if проверку, чтобы можно было осуществлять сразу несколько взаимоисключающих проверок. Каждая проверка позволяет переходить к следующему за ней оператору не раньше, чем получит логический результат ИСТИНА. Когда проверка с результатом ИСТИНА найдена, запускается вложенный в нее блок операторов, и затем программа игнорирует все следующие строки в конструкции if..else. Если ни одна из проверок не получила результат ИСТИНА, по умолчанию выполняется блок операторов в else, если последний присутствует, и устанавливается действие по умолчанию.

Конструкция else if может быть использована без заключительного else. А вот число переходов else if может быть неограничено.
if (pin_analog_input < 500)
{
  // выполнять действие A
}
else if (pin_analog_input >= 1000)
{
  // выполнять действие B
}
else
{
  // выполнять действие  C
}

Оператор Switch...case

Подобно конструкции if, switch...case управляет процессом выполнения программы, позволяя программисту задавать альтернативный код, который будет выполняться при разных условиях. В частности, оператор switch сравнивает значение переменной со значением, определенном в операторах case. Когда найден оператор case, значение которого равно значению переменной, выполняется программный код в этом операторе.

Ключевое слово break является командой выхода из оператора case и обычно используется в конце каждого case. Без оператора break оператор switch будет продолжать вычислять следующие выражения, пока не достигнет break или конец оператора switch.
switch (var) {
    case 1:
      //выполняется, когда var равно 1
      break;
    case 2:
      //выполняется, когда  var равно 2
      break;
    default:
      // выполняется, если не выбрана ни одна альтернатива
      // default необязателен
  }

Оператор For

Конструкция for используется для повторения блока операторов, заключенных в фигурные скобки некоторое количество раз. Заголовок цикла for состоит из трех частей:
for (initialization; condition; increment) {операторы выполняющиеся в цикле}
Инициализация (Initialization) выполняется самой первой и один раз. Каждый раз в цикле проверяется условие (condition), если оно верно, выполняется блок операторов в фигурных скобках и приращение (increment), затем условие проверяется вновь. Когда логическое значение условия становится ложным, цикл завершается.

Рассмотрим следующий код:
void setup()
{
   pinMode(13, OUTPUT);   // Программируем вывод D13 как выход
}
 
void loop()
{
   for (int i=0; i < 5; i++)  // цикл for будет выполняться пока i < 5
   {                          
      digitalWrite(13, 1);
      delay(500);
      digitalWrite(13, 0);
      delay(500);
   }
  delay(10000);
}
Начинается цикл когда i=0. Так как i < 5, произойдет выполнение команд в фигурных скобках, а именно произойдет включение светодиода L на полсекунды, затем светодиод будет погашен на полсекунды, и значение i будет увеличено на 1, и цикл повторится, и будет повторяться пока соблюдается условие i < 5. Как только i станет равной 5 произойдет выход из цикла и после 10-ти секундной паузы всё начнется с начала.





Copyright © R9AL 2021 Все права защищены

Рейтинг@Mail.ru Яндекс цитирования