Debounce из книги

Trofim
Offline
Зарегистрирован: 07.10.2018

Поскажите пожалуйста. Почему при загрузке кода Debounce из книги Изучаем Ардуино сразу загорается светодиод, хотя кнопка не нажималась. По идее, вроде как светодиод должене загореться только после первого нажатия на кнопку.

const int LED=9;

const int BUTTON=2;

boolean lastButton = LOW;

boolean currentButton = LOW;

boolean ledOn = false;

void setup ()                 

{   

pinMode (BUTTON, INPUT);

pinMode (LED, OUTPUT);

}

 

/*

* Функция сглаживания дребезга

* принимает в качестве аргумента предыдущее состояние кнопки

* и выдает фактическое.

*/

 

boolean debounce(boolean last) 

{

boolean current = digitalRead(BUTTON);

if (last != current)

{

delay(5);

return current;

}

}

void loop()

{

currentButton = debounce(lastButton);

if (lastButton == LOW && currentButton == HIGH)

{

ledOn = !ledOn;

}

lastButton = currentButton;

digitalWrite(LED, ledOn);

}

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Trofim пишет:

Поскажите пожалуйста. 

Возможно, и "поскажем", но для начала, изучите правила этого форума, и вставьте код как положено. Заодно, и схема включения светодиода не помешает.

Trofim
Offline
Зарегистрирован: 07.10.2018
/* 
* 9 pin-светодиод, 2 pin-кнопка. 
*Функция сглаживания дребезга из книги Изучаем Ардуино
*/
const int LED=9; 
const int BUTTON=2; 
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;
void setup ()                  
{    
pinMode (BUTTON, INPUT);
pinMode (LED, OUTPUT);
} 

/*
* Функция сглаживания дребезга
* принимает в качестве аргумента предыдущее состояние кнопки
* и выдает фактическое.
*/

boolean debounce(boolean last)  
{
boolean current = digitalRead(BUTTON); 
if (last != current) 
{ 
delay(5);
return current;
}
}
void loop()
{
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)
{
ledOn = !ledOn;
}
lastButton = currentButton;
digitalWrite(LED, ledOn);
}

 

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

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кстати, программа, как я понимаю, из книги Блума? Причём из издания на русском языке. Правильно? Я вижу здесь одну из тех самых ошибок, о которых писал вот здесь.

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

Trofim
Offline
Зарегистрирован: 07.10.2018

Кнопка подключена через PULLDOWN резистор к pin 2. Таким образом вход pin 2 срабатывает от высокого уровня на кнопке. Приведенный мною код полностью соответствует коду из книги Джереми Блума на английском языке. Как ни странно симуляция этого кода на Tinkercard работает правильно, т.е. светодиод не загорается при включении, а в реальности, загорается. Непонятно.

sadman41
Offline
Зарегистрирован: 19.10.2016

Что должна возвращать функция debounce?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Что должна возвращать функция debounce?

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

ТС, Вы нашли архив со всеми скетчами из книги? Скачали? Разницу увидели?

Trofim
Offline
Зарегистрирован: 07.10.2018

Я смотрел урок Джереми Блума на английском языке в Youtube, где он пишет этот скетч на экране и у него при загрузке точно так же загорается светодиод. Хотя судя по программе этого не должно быть. Архив я не скачал.

sadman41
Offline
Зарегистрирован: 19.10.2016

Дак я не показываю ошибку,а намекаю куды смотреть. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Trofim пишет:

Архив я не скачал.

Ну, так, качайте и сравнивайте. Там элементарная опечатка.

kalapanga
Offline
Зарегистрирован: 23.10.2016

Да и в ролике на ютюбе Джереми функцию debounce без опечаток пишет. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

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

Trofim
Offline
Зарегистрирован: 07.10.2018

Не могли бы дать ссылку на архив. Я не могу найти. Тогда бы я и сравнил.

Trofim
Offline
Зарегистрирован: 07.10.2018

Посмотрел библиотеку. Здесь изначально в глобальной переменной задается 

int ledState = HIGH;

В предыдущем коде

ledOn = false. 

Как в процессе загрузки ledOn меняется на true мне непонятно. 

*/

 

// constants won't change. They're used here to set pin numbers:

const int buttonPin = 2;    // the number of the pushbutton pin

const int ledPin = 13;      // the number of the LED pin

 

// Variables will change:

int ledState = HIGH;         // the current state of the output pin

int buttonState;             // the current reading from the input pin

int lastButtonState = LOW;   // the previous reading from the input pin

 

// the following variables are unsigned longs because the time, measured in

// milliseconds, will quickly become a bigger number than can be stored in an int.

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled

unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

 

void setup() {

  pinMode(buttonPin, INPUT);

  pinMode(ledPin, OUTPUT);

 

  // set initial LED state

  digitalWrite(ledPin, ledState);

}

 

void loop() {

  // read the state of the switch into a local variable:

  int reading = digitalRead(buttonPin);

 

  // check to see if you just pressed the button

  // (i.e. the input went from LOW to HIGH), and you've waited long enough

  // since the last press to ignore any noise:

 

  // If the switch changed, due to noise or pressing:

  if (reading != lastButtonState) {

    // reset the debouncing timer

    lastDebounceTime = millis();

  }

 

  if ((millis() - lastDebounceTime) > debounceDelay) {

    // whatever the reading is at, it's been there for longer than the debounce

    // delay, so take it as the actual current state:

 

    // if the button state has changed:

    if (reading != buttonState) {

      buttonState = reading;

 

      // only toggle the LED if the new button state is HIGH

      if (buttonState == HIGH) {

        ledState = !ledState;

      }

    }

  }

 

  // set the LED:

  digitalWrite(ledPin, ledState);

 

  // save the reading. Next time through the loop, it'll be the lastButtonState:

  lastButtonState = reading;

}

Trofim
Offline
Зарегистрирован: 07.10.2018

*/

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }

  // set the LED:
  digitalWrite(ledPin, ledState);

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;
}

После нажатия кнопки ф-ция Debounce по идее должна возвратить новое состояние кнопки (current) те HIGH, с которым и сравнивается предыдущее состояние. Только после этого должен загореться светодиод. Но почему он загорается сразу после загрузки скетча? Ведь все переменные объявлены как LOW!!!

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

В строке 21+ ошибка - Вы правы!

kalapanga
Offline
Зарегистрирован: 23.10.2016

Уже какую-то библиотеку приплели, она тут причём?

https://www.exploringarduino.com/content/ch2/ внизу страницы большая кнопка Download, а ещё чуть ниже ссылка на гитхаб.

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

Trofim
Offline
Зарегистрирован: 07.10.2018

В строке 21 пробел. Где ошибка?

leks
Offline
Зарегистрирован: 22.10.2017

digitalWrite(LED, LOW); в 22 добавьте следом, может поможет.

leks
Offline
Зарегистрирован: 22.10.2017

int ledState = LOW; или в 8 заменить. 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

mykaida пишет:

В строке 21+ ошибка - Вы правы!

Это был сарказм по поводу того, что Вы неправильно вставили программу.  Но Вы очень быстро исправились. Приношу извинения и, посоветовавшись с коллегами, советую Вам сменить библиотеку.

Trofim
Offline
Зарегистрирован: 07.10.2018

Не помогает. 

leks
Offline
Зарегистрирован: 22.10.2017

Trofim пишет:

Не помогает. 

Тоесть светодиод не выключается?

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Trofim пишет:

Не помогает. 

Тогда начинаем изучать Serial.print()  и выдаем на консоль состояние всех переменных перед их использованием. Чудес не бывает бывает или неправильная схема или неправильная программа. Значит будем локализовать ошибку.

Trofim
Offline
Зарегистрирован: 07.10.2018

Как нам поможет Serial.print(), если все переменные забиты в памяти? Почему-то при загрузке Debounce происходит инверсия ledOn. И на выходе 9 pin сразу HIGH. Замерял мультиметром сразу после загрузки.

sadman41
Offline
Зарегистрирован: 19.10.2016

Наверное потому что не все переменные, объявлены как LOW. Можете убедиться в этом Serial.print-ом.

leks
Offline
Зарегистрирован: 22.10.2017

Trofim пишет:

Как нам поможет Serial.print(), если все переменные забиты в памяти? Почему-то при загрузке Debounce происходит инверсия ledOn. И на выходе 9 pin сразу HIGH. Замерял мультиметром сразу после загрузки.

А где у вас в скетче написано, что вначале должно быть LOW?

Trofim
Offline
Зарегистрирован: 07.10.2018

9 строчка

boolean ledOn = false;

leks
Offline
Зарегистрирован: 22.10.2017

Trofim пишет:

9 строчка

boolean ledOn = false;

Так это присвоение значения переменной, а не подача логического уровня на выход.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Trofim пишет:

Как нам поможет Serial.print(), если все переменные забиты в памяти? Почему-то при загрузке Debounce происходит инверсия ledOn. И на выходе 9 pin сразу HIGH. Замерял мультиметром сразу после загрузки.

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

Trofim
Offline
Зарегистрирован: 07.10.2018

Просто я не знаю как в данном случае использовать консоль. Если подскажите - буду благодарен.

Trofim
Offline
Зарегистрирован: 07.10.2018

Да, но если мы не написали команду digitalWrite (9, HIIH); (а мы этого не делали), то высокий уровень там не должен появиться. А он появляется.

sadman41
Offline
Зарегистрирован: 19.10.2016

Trofim пишет:

9 строчка

boolean ledOn = false;

Обсуждается самый последний скетч, а не тот, о котором Вы думаете.

Trofim
Offline
Зарегистрирован: 07.10.2018

Мы же инвертируем ledOn только после нажатия кнопки и после того подаем на 9pin обратное значение ledOn те TRUE

Trofim
Offline
Зарегистрирован: 07.10.2018

Изначально мы говорили о скетче из книги (самый первый). В котором для меня и происходят непонятные явления с зажиганием LED без нажатия кнопки сразу после загрузки. Вот это длz меня и не понятно тк изначально объявлен статус светодиода FALSE

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Trofim пишет:

Просто я не знаю как в данном случае использовать консоль. Если подскажите - буду благодарен.

Вот тут могу помочь Вам. Например перед 21 строчкой написать Serial.print("ledstate: "); Serial.println(ledState);

И так при любом изменении пинов.

sadman41
Offline
Зарегистрирован: 19.10.2016

Trofim пишет:

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

В нём есть опечатка, которая и приводит к странным явлениям.

leks
Offline
Зарегистрирован: 22.10.2017

Trofim пишет:

Да, но если мы не написали команду digitalWrite (9, HIIH); (а мы этого не делали), то высокий уровень там не должен появиться. А он появляется.

А вы попробуйте написать digitalWrite (9, LOW); и если высокий уровень появится то завтра я попробую на Ардуине проверить сам :) 

Trofim
Offline
Зарегистрирован: 07.10.2018

Можете указать на эту опечатку, потому что из логики написанного (если проанализировать код), так не должно происходить

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Trofim пишет:

Можете указать на эту опечатку, потому что из логики написанного (если проанализировать код), так не должно происходить

Когда-то мы с другом писали достаточно большую программу (где-то 2т строк). И она тоже делала не то, что казалось изначально. В  итоге мы локализовали эту ошибку. Я уверен, что в программе в 20 строк это можно сделать намного быстрее. Особенно, когда Вам дают дельные советы.

Trofim
Offline
Зарегистрирован: 07.10.2018

Пробовал много раз. В void setup() специально указывал digitalWrite (9, LOW); Все равно после загрузки LED горит. Причем если для проверки указывал дополнительно pinMode (10, OUTPUT); то на 10 pin устанавливалось после загрузки LOW как и положено. Похоже, что все дело в ф-ции Debounce. Почему то она инвертирует состояние светодиода.

leks
Offline
Зарегистрирован: 22.10.2017

Trofim пишет:

Пробовал много раз. В void setup() специально указывал digitalWrite (9, LOW); Все равно после загрузки LED горит. Причем если для проверки указывал дополнительно pinMode (10, OUTPUT); то на 10 pin устанавливалось после загрузки LOW как и положено. Похоже, что все дело в ф-ции Debounce. Почему то она инвертирует состояние светодиода.

Ну вот и эксперимент - венец истины :), значит дальше надо смотреть.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

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

leks
Offline
Зарегистрирован: 22.10.2017

:) на всякий случай в сетап поставьте делай секунд 10, ну чтоб окончательно убедиться что не горит сначала, а потом горит.

Trofim
Offline
Зарегистрирован: 07.10.2018

Единственное к какому выводу я пришел, что Debounce инвертирует состояние светодида (ledOn). Но почему так происходит мне не понять. Это значит, что логика работы ф-ции Debounce мне до конца непонятна.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Trofim пишет:

Не могли бы дать ссылку на архив. Я не могу найти. Тогда бы я и сравнил.

https://drive.google.com/open?id=0B9r7cRXQ4DU4XzVLeUVkNHdiaVU

 

Trofim
Offline
Зарегистрирован: 07.10.2018

Ставил. Принципиально никаких различий. Все то же самое.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Trofim пишет:

Единственное к какому выводу я пришел, что Debounce инвертирует состояние светодида (ledOn). Но почему так происходит мне не понять. Это значит, что логика работы ф-ции Debounce мне до конца непонятна.

Вам всё на тарелочке выложили в посте #6 подумайте в этом направлении.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ЕвгенийП пишет:

Вам всё на тарелочке выложили в посте #6 подумайте в этом направлении.

Евгений - опять всю интригу убили. Тут еще флуда страниц на пять было :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

И будет, куда денется. Если уж Сэдмен не убил, то куда мне!

А темка-то пятничная - только графа не хватает, а так уже "вся безумная больница" :)))