Кнопка с залипанием.

ororoshka
Offline
Зарегистрирован: 14.11.2013

Начал разбирать код кнопки с залипанием: нажали загорелся LED, еще раз - потух.

Очень простая задачка, но для меня, новичка, разбор кода немного загнал в тупик. Для анализа использую следующий код из Getting Started with Arduino, который прокомментировал самостоятельно.

Не могу понять, что происходит и для чего мы должны сделать: old_val = val; // val is now old, let's store it

 

#define LED  13   // the pin for the LED
#define BUTTON 7  // the input pin where the
                  // pushbutton is connected
int val = 0;      // val will be used to store the state
                  // of the input pin
int old_val = 0;  // this variable stores the previous
                  // value of "val"
int state = 0;    // 0 = LED off and 1 = LED on

void setup() {
  pinMode(LED, OUTPUT);     // tell Arduino LED is an output
  pinMode(BUTTON, INPUT);   // and BUTTON is an input
}
void loop(){
  val = digitalRead(BUTTON); // Считаем состояние кнопки и запишем в переменную val
                             
   // Если переменная val получила значение HIGH (1), тоесть произошло нажатие кнопки и  условие стало истинно, то выполняем инверсию переменной state, которая отвечает за включение или выключение LED

  if ((val == HIGH) && (old_val == LOW)){
    state = 1 - state;
  }
   
   // - МЕСТО КОТОРОЕ ТРЕБУЕТ ПОЯСНЕНИЙ -

  old_val = val; 

   // В переменную old_val записываем значение val, которое при нажатии кнопки получило значение HIGH  
   // Все ли верно до этого места в рассуждениях?

   // Если после инверсии state будет иметь состояние логической истинны, то включаем либо выключаем LED

  if (state == 1) {
    digitalWrite(LED, HIGH); // turn LED ON
  } else {
    digitalWrite(LED, LOW);
  }
}

 

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

ororoshka пишет:

Не могу понять, что происходит и для чего мы должны сделать: old_val = val; // val is now old, let's store it

Ту так уберите эту строку и посмотрите что будет.

ororoshka
Offline
Зарегистрирован: 14.11.2013

maksim пишет:

ororoshka пишет:

Не могу понять, что происходит и для чего мы должны сделать: old_val = val; // val is now old, let's store it

Ту так уберите эту строку и посмотрите что будет.

 

Если убрать, схема ведет себя странно.

Мне сейчас важно разобрать логику всей программы, что бы понять как это работает. В том месте, я не могу понять если в old_val записывается HIGH от кнопки то как это будет снова работать при проверке блока if в цикле?

Возможно идет запись наборот в val пишеться значение old_val для обнуления, что бы при проверке выполнялось условие отжатой кнопки LOW. Но почему тогда там не написано, наоборот

val = old_val;

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

Почитайте http://arduino.ru/forum/programmirovanie/pomogite-s-knopkami-i-svetom-razobratsya, только не надо писать что там другая проблема, там именно такая же проблема - вы не понимаете что такое триггер и как он работает.

paf
Offline
Зарегистрирован: 25.01.2013

Возьмите лист бумаги и авторучку с синими чернилами*, напишите в строку val,  state,  old_val.   Сейчас мы будем с вами делать по настоящему крутые вещи!!!  Под именами будем ставить вертикальную черту если хай или единица, овал если лоу или ноль. 

Итак, перед нами лист и авторучка с синими чернилами*. Нажимаем кнопку авторучки и получаем лоу если до этого был хай.

Хай, если до этого был лоу.  Если вышел лоу, возьмите карандаш или еще раз нажмите кнопку. Нажали....

Теперь val стал хай, old_val никто из ноль не выводил и он лоу, а вот стэйт стал в хай потому, что выполнилось первое условие. И единица минус ноль будет хай.

И наконец МК плавно выпадает на строку old_val = val, а val у нас под прессом батона и равен хай! И теперь внимание! old_val стал тоже в хай. Ну и нехай так и стоит.  

Наконец наш МК получает команду по второму условию - Абдулла, зажигай! 

С перепугу мы можем отпустить батон, но не сразу. МК пока дождется пока мы его отпустим успеет еще разок лупануть по коду.

И тут то его и ожидает засада! Смотрим, val - high, и... облом! old_val тоже хай, и безусловно хаянье продолжается! А стэйт? Он тоже машет Хай!  МК пофиг, хай значит поджигай и еще один факел летит в лед. Лед продолжает полыхать синим пламенем потому что чернила у нас синии и ручка в хай.

И вот до нас дошло! Батон в прессе. Депресс батону! И ага! val упал в лоу! стейт продолжает хаять, а олд получив подзатыльник от МК, летит к своему дружку Валу в лоу!

Приготовьте карандаш. Жмите ручку в лоу. Е-есть! val снова в хае, олд продолжает пускать пузыри в лоу, а стейт получает баранку! Вал тащит Олд из лоу в хай. Иф, от баранки стейта  в елсе тушит горящий лед!

Зе энд.

*если у вас только красные чернила то используйте IR led, а если черные то я не знаю, спросите Джолли Бибера.

vvadim
Offline
Зарегистрирован: 23.05.2012

В теме http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku много чего найдёте полезного для себя и сможете применить

ororoshka
Offline
Зарегистрирован: 14.11.2013

Спасибо за ответы, с этим разобрался, но наткнулся на код Jeremy Blum в котором он написал функцию для решения проблемы с дребезгом.

помогите разобраться, как же работает функция:

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

Не могу понять как объяснить запись: boolean debounce(boolean last) - что происходит в скобках, если переменная last объявляется только сейчас. Чему она равна изначально, что бы ее сравнивать в if?

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

Функции

А чтобы больше не было таких вопросов читайте весь раздел Программирование.

 

ororoshka
Offline
Зарегистрирован: 14.11.2013

maksim пишет:

Функции

А чтобы больше не было таких вопросов читайте весь раздел Программирование.

 

Читаю, но все равно не понятно чему равен last в сравнении. Кнопка при нажатии видимо дает true, почему тогда  нигде не прописано что last дает false.

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)

 

Zizilk
Offline
Зарегистрирован: 30.05.2013

last передаётс в функцию при вызове этой функции... прежде чем лезть в проганье лучше подучить азы хотя бы на паскале

ororoshka
Offline
Зарегистрирован: 14.11.2013

Zizilk пишет:

last передаётс в функцию при вызове этой функции... прежде чем лезть в проганье лучше подучить азы хотя бы на паскале

 

что же туда передается?

 if (last != current)

 last не равен current, а current это HIGH или LOW то как происходит сравнение, если last еще даже не имеет какого либо значения. Вы можете объяснить более подробно?

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

Вы вообще понимаете что такое функция?

ororoshka
Offline
Зарегистрирован: 14.11.2013

maksim пишет:

Вы вообще понимаете что такое функция?

Ящик с неким количеством входов и выходом. Внутри ящика, что-то происходит и на выходе получаем результат. Этот ящик можно подключать к другим ящиками и т.д. 

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

ororoshka пишет:

Ящик с неким количеством входов и выходом. 

Вот когда вы спрашиваете

ororoshka пишет:

что же туда передается?

Это все равно что спросить "Что на входе ящика?"

ororoshka
Offline
Зарегистрирован: 14.11.2013

maksim пишет:

ororoshka пишет:

Ящик с неким количеством входов и выходом. 

Что на входе ящика?

то, что в круглых скобках (boolean last) или http://arduino.ru/Reference/FunctionDeclaration

int myMultiplyFunction(int x, int y){
  int result;
  result = x * y;
  return result;

 

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

ororoshka пишет:

maksim пишет:

ororoshka пишет:

Ящик с неким количеством входов и выходом. 

Что на входе ящика?

то, что в круглых скобках (boolean last) или http://arduino.ru/Reference/FunctionDeclaration

int myMultiplyFunction(int x, int y){
  int result;
  result = x * y;
  return result;

 

Нет. То что в круглых скобках это и есть "входы", а не то что вы передаете.

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

И чему же будут равны x и y, когда произойдет вызов функции int myMultiplyFunction(int x, int y) в 10-й строке?

void setup(){
  Serial.begin(9600);
}

void loop{
  int i = 2;
  int j = 3;
  int k;

  k = myMultiplyFunction(i, j); // k содержит 6
  Serial.println(k);
  delay(500);
}

int myMultiplyFunction(int x, int y){
  int result;
  result = x * y;
  return result;
}

 

ororoshka
Offline
Зарегистрирован: 14.11.2013

Возможно я пытаюсь подойти к программированию как электрик, но что же тогда идет на вход, какое значение?

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

весь код программы:

int switchPin = 8;
int ledPin = 13;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup()
{
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void loop()
{
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = !ledOn;
  }
  lastButton = currentButton;
  
  digitalWrite(ledPin, ledOn);

}

 

ororoshka
Offline
Зарегистрирован: 14.11.2013

maksim пишет:

И чему же будут равны x и y, когда произойдет вызов функции int myMultiplyFunction(int x, int y) в 10-й строке?

void setup(){
  Serial.begin(9600);
}

void loop{
  int i = 2;
  int j = 3;
  int k;

  k = myMultiplyFunction(i, j); // k содержит 6
  Serial.println(k);
  delay(500);
}

int myMultiplyFunction(int x, int y){
  int result;
  result = x * y;
  return result;
}

Ничему, функция сейчас стоит как заготовка, если я верно понимаю. Вызов был выше, там она будет использоваться, что бы просчитать 2х3 и вернуть 6

 

 

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

Не верно. x будет равен i то есть двум, а y равен j то есть трем. Где выше? Где выше 10-й строки эта функция еще вызывается???

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

Когда в 26 строке произойдет вызов функции boolean debounce(boolean last)boolean last будет равна lastButton.

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

ororoshka пишет:

Возможно я пытаюсь подойти к программированию как электрик, но что же тогда идет на вход, какое значение?

На вход идет, то значение которое вы передаете.

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

ororoshka пишет:

Zizilk пишет:

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

что же на щупах вольтметра?

...

Что у вас на вольтметре зависит от того куда вы тыкаете его щупы.

Zizilk
Offline
Зарегистрирован: 30.05.2013

Вместо того, чтобы подходить к делу как кто-то, а не программист выучите матчасть. И потренируйтесь на более простых языках. И вопросов глупых не будет

ororoshka
Offline
Зарегистрирован: 14.11.2013

Zizilk пишет:

Вместо того, чтобы подходить к делу как кто-то, а не программист выучите матчасть. И потренируйтесь на более простых языках. И вопросов глупых не будет

Именно для изучения азов программирования и занимаюсь с Arduino. Любой язык будет сложен, если есть вопросы и нет ответов. Возможно мои вопросы очень глупые, но именно такими они и могут быть на данном этапе моего изучения. Думаю, что форум открыт для любого уровня пользователей.

 

Zizilk
Offline
Зарегистрирован: 30.05.2013

Глупая идея, так как в случае с ардуино могут накладываться дополнительные железные факторы. Если инетересно программирование само по себе, то начинать лучше с простого (в Ардуино вроде как близкий к С синтаксис).

Лучше взять самоучитель по тому же паскалю и принять во внимание то, что тут называется функциями там идёт под названием процедуры. Потом можно будет взть что-то ещё. Не с того обучение в общем начинаете.

Форум открыт для вопросов, но для вас же будет лучше если  пойдёте изучать программирование как все а не будете изобрать велосипед.

ororoshka
Offline
Зарегистрирован: 14.11.2013

Zizilk пишет:

Глупая идея, так как в случае с ардуино могут накладываться дополнительные железные факторы. Если инетересно программирование само по себе, то начинать лучше с простого (в Ардуино вроде как близкий к С синтаксис).

Лучше взять самоучитель по тому же паскалю и принять во внимание то, что тут называется функциями там идёт под названием процедуры. Потом можно будет взть что-то ещё. Не с того обучение в общем начинаете.

Форум открыт для вопросов, но для вас же будет лучше если  пойдёте изучать программирование как все а не будете изобрать велосипед.

Мне удобнее с железом, у меня есть конкретные задачи, знаком электроникой, но никогда не занимался программированием. Спасибо за наводку на Паскаль. 

vvadim
Offline
Зарегистрирован: 23.05.2012

Внимательно почитайте http://arduino.ru/Reference. Поиграйтесь с кнопками http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-no..., светодиодами , сервами. У вас сразу отпадёт куча вопросов. Перед тем как задавать вопросы на форуме погуглите в сети и поищите темы на форуме а уже потом и вопрос задавайте с примером своего кода и корректным описанием проблемы. Здесь вас никто программерству учить же не будет. Подскажут, посоветуют, ну может пример какой нибудь приведут

madteez
Offline
Зарегистрирован: 05.01.2016
int switchPin = 8;
int ledPin = 13;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup()
{
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
    return current;
  }
}

void loop()
{
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = !ledOn;
  }
  lastButton = currentButton;
  
  digitalWrite(ledPin, ledOn);

}

Здравствуйте, получается в 26 строчке я обращаюсь к функции debounce, после запускается тело этой функции с параметрами логической функции last(тут пока не известно тру или фолс) в 13 строчке, потом считываю значение для current. Теперь непонятная часть для меня, в 14 строчке я сравниваю значение last и current, значение current с сигнала, оно тру или фолс, а значение last до сих пор не известно, как мне кажется. Соответственно, когда я в первый раз обращаюсь с сравнением и не знаю точного значения last, то оно в этот раз будет просто противоположным значению current? Все остальные значение ласт будут противоположными? 

Alexino
Offline
Зарегистрирован: 29.12.2015

madteez пишет:
а значение last до сих пор не известно, как мне кажется.
Почему неизвестно ? Срока №3 - инициализация переменной lastButton. Её значение и передаётся в debounce.

А вот в функции debounce непонятки.
Во первых. Есть вариант, когда ничего из функции не вернётся.
Во вторых. Зачем 2 раза читать значение ПИНа в переменную ?

madteez
Offline
Зарегистрирован: 05.01.2016

Сегодня утром такая же мудрая мысль пришла ко мне, спасибо :) это скетч из курса джереми блума для нажатий кнопки, когда мы читаем значение второй раз, то это надо для более точной информации, т.к сиглал колебается какое-то время. А когда ничего не получаю, то кнопка не нажата.

Tranzizo
Offline
Зарегистрирован: 08.03.2016

ororoshka, я тоже долго искал ответ на ваш вопрос.

Попробуйте слово "last" заменить на "lastButton" и все сразу встанет на свои места.

Ниже привожу код с некоторыми пояснениями.

int switchPin = 8;
int ledPin = 13;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup()
{
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

boolean debounce(boolean lastButton)                     //значение функции debounce (true или false) зависит от значения функции lastButton
{
  boolean current = digitalRead(switchPin);              //чтение состояния кнопки
  if (lastButton != current)                             //если найдены отличия
  {
    delay(5);                                            //ждем 5мс
    current = digitalRead(switchPin);                    //читаем снова
  }
  return current;                                        //возвращаем текущее состояние
}

void loop()
{
  currentButton = debounce(lastButton);                  //чтение состояния debounce
  if (lastButton == LOW && currentButton == HIGH)        //если было нажатие
  {
    ledOn = !ledOn;                                      //переключить значение ledOn на противоположное
  }
    lastButton = currentButton;
  digitalWrite(ledPin,ledOn);
}