Сколько параметров нужно для функции?

junior_developer
Offline
Зарегистрирован: 27.11.2017

Пробую разобраться с простым примером https://www.arduino.cc/en/Tutorial/Debounce и не могу сообразить, как правильно вынести этот код обработки кнопки в отдельную функцию. Чтобы он подошел для нескольких кнопок.
Главное, чего я не понял, это сколько параметров нужно передать в функцию?

Например я создаю таким же образом функцию, называю её button_read ();
 Вопрос в том, какие праметры обязательно в неё передавать? Достаточно ли всего лишь номера пина?
то есть например при вызове для двух кнопок button_read (5); button_read (6);
или нужно ещё передавать предыдущее состояние кнопки button_read (5 , prev_button1_state); button_read (6 , prev_button2_state);
А сама функция должна возвращать только ноль или 1? то есть её можно записать как bool?

То есть так:

bool read_button(byte buttonPin, bool prev_state) {

  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState) {

    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    if (reading != buttonState) {
      buttonState = reading;

     
      if (buttonState == HIGH) {
        out_state = !out_state;
      }
    }
  }

 return out_state;

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

Помогите пожалуйста разобраться!

 

 

 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Если возникают такие вопросы, нужно переходить от процедурного программирования к ООП.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

andriano, скорее это примитивные предсталение о Си. Народ обычно путает Бейсик и Си. В Си можно сделать очень много трюков при помощи функции, включая что возвращать можно не только одну переменную. Да коллбэк тоже можно использовать. 

junior_developer
Offline
Зарегистрирован: 27.11.2017

ООП разве проще? Наверно, для такого как я, это вообще "темный лес"!
 Скетч я в общем уже переделал и он даже скомпилировался!  Получилось так:
 

const byte buttonPin_1 = 2;    // the number of the pushbutton pin
const byte buttonPin_2 = 3;    // the number of the pushbutton pin
const byte ledPin = 13;      // the number of the LED pin

// Variables will change:
bool ledState = HIGH;         // the current state of the output pin
bool button_1_state;             // the current reading from the input pin
bool button_2_state;             // the current reading from the input pin
bool lastButtonState_1 = LOW;   // the previous reading from the input pin
bool lastButtonState_2 = 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_1, INPUT);
  pinMode(buttonPin_2, INPUT);
  pinMode(ledPin, OUTPUT);
  // set initial LED state
  digitalWrite(ledPin, ledState);
}
bool read_button (byte button_pin, bool prev_state) {
  bool buttonState;
  // read the state of the switch into a local variable:
  bool reading = digitalRead(button_pin);

  // 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 != prev_state) {
    // 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) {
        return true;
      }
      else return false;
    }
  }

  // save the reading.
  prev_state = reading;
}
void turn_Led_on () {digitalWrite(ledPin, 1);}
void turn_Led_off() {digitalWrite(ledPin, 0);}

void loop() {
  if (read_button(buttonPin_1, lastButtonState_1)) turn_Led_on;
  if (read_button(buttonPin_2, lastButtonState_2)) turn_Led_off;
}

В основном цикле теперь только 2 строчки!

void loop() {
  if (read_button(buttonPin_1, lastButtonState_1)) turn_Led_on;
  if (read_button(buttonPin_2, lastButtonState_2)) turn_Led_off;
}

Интересно, можно ли было написать ещё проше?
 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Проще для кого? Если для лентяя, так проще вообще не писать ничего. Потому что так самое простое.  Проблема не в написании проще. Проблема найти такие куски кода, которые в дальшейшем не надо переписывать и они не будут конфликтовать когда их в коде будет море.

ПС: #4   Здесь в лупе практически ничего нет. :)

junior_developer
Offline
Зарегистрирован: 27.11.2017

Нет, дело в том, что я хочу разобраться, как это работает, чтобы самому написать функцию. Хотя со стороны может показаться, что "изобретаю велосипед". Мне кстати посоветовали (правда не здесь) взять библиотеку OneButton и не морочить голову!

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Что бы разобраться как ЭТО работает. Надо сначало разобраться зачем ЭТО надо. Вот ответьте на очень важный вопрос :зачем нужна кнопка. И только после этого вы поймете остальное.

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

junior_developer пишет:
Хотя со стороны может показаться, что "изобретаю велосипед".

Велосипед уже изобретён, вообще-то ))
Отличная, многофункциональная библа. И не морочьте голову )))

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

junior_developer пишет:

я хочу разобраться, как это работает, 

Правильно делаете! Лучше изобрести велосипед, чем нихрена не изобрести! Хотите освоиться - делайте и не слушайте советов "взять готовое". Учатся на задачах, а не на брании готового.

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

Таки, да - "...и если говнокод работает, то это не говнокод, а немного не оптимизированный код" (с) х.з

fogary
Offline
Зарегистрирован: 05.03.2016

junior_developer пишет:

 Вопрос в том, какие праметры обязательно в неё передавать? Достаточно ли всего лишь номера пина?
А сама функция должна возвращать только ноль или 1? то есть её можно записать как bool?

Пример из поваренной книги (кнопка притянута к земле):

/*
  Debounce sketch
  a switch connected to pin 2 lights the LED on pin 13
  debounce logic prevents misreading of the switch state
*/

const int inputPin = 2; // the number of the input pin
const int ledPin = 13; // the number of the output pin
const int debounceDelay = 10; // milliseconds to wait until stable

// debounce returns true if the switch in the given pin is closed and stable
boolean debounce(int pin)
{
  boolean state;
  boolean previousState;

  previousState = digitalRead(pin); // store switch state
  for(int counter=0; counter < debounceDelay; counter++)
  {
    delay(1); // wait for 1 millisecond
    state = digitalRead(pin); // read the pin
    if( state != previousState)
    {
      counter = 0; // reset the counter if the state changes
      previousState = state; // and save the current state
    }
  }
  // here when the switch state has been stable longer than the debounce period

  return state;
}

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

void loop()
{
  if(debounce(inPin))
  {
    digitalWrite(outPin, HIGH);
  }
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

Сама постановка вопроса странная. "Сколько параметров ДОЛЖНО БЫТЬ у функции?" - это ж ваша функция. Сколько вам для программы надо, столько и делайте...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

andriano, скорее это примитивные предсталение о Си. Народ обычно путает Бейсик и Си. В Си можно сделать очень много трюков при помощи функции, включая что возвращать можно не только одну переменную. Да коллбэк тоже можно использовать. 

Средствами С можно сделать абсолютно все, что можно сделать средствами ООП. Только в некоторых случаях это оказывается намного более муторным.

Следует выбирать средства под задачу, а не наоборот.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

OlegK пишет:

junior_developer пишет:
Хотя со стороны может показаться, что "изобретаю велосипед".

Велосипед уже изобретён, вообще-то ))
Отличная, многофункциональная библа. И не морочьте голову )))

Весьма категоричное заявление.

Как, например, эту "отличную, многофункциональную библиотеку" использовать, если кнопки подключены через 165 регистр, а не напрямую к пинам контроллера?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

andriano пишет:
Средствами С можно сделать абсолютно все, что можно сделать средствами ООП. Только в некоторых случаях это оказывается намного более муторным.

Следует выбирать средства под задачу, а не наоборот.

Не напоминает.

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

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

Serega66
Offline
Зарегистрирован: 23.03.2018

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

Serega66
Offline
Зарегистрирован: 23.03.2018

Да вы правы отсчет времени у МК один но у каждой кнопки должно быть свое начало и конец отсчета иначе при нажатии двух кнопок debounce отработает только на одной кнопке

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Разумется для этого надо для каждой кнопки завести переменную.  Вот в этой переменной записываются старые показания . А разница между текущими показаниями (millis()) и  старыми (переменная) и есть интервал который уже прошел. Вот из-за этой особенности всем сложно пересесть c delay() на millis(). delay()  не требует дополнительной переменной для вычисления разницы ... и delay() это все же "много таймеров".

Serega66
Offline
Зарегистрирован: 23.03.2018

Поэтому и ответ на вопрос в начале поста: Для того чтобы работала такая функция надо задать для каждой кнопки 3 параметра пин входа пин выхода и отсчет времени. А грузить человека если у него и так каша в голове совсем никчему.

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

andriano пишет:
Весьма категоричное заявление.

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Serega66, похоже и у вас тоже каша в голове. Ответьте зачем нужна кнопка в устройстве. И потом вы точно все поймете.

Serega66
Offline
Зарегистрирован: 23.03.2018

А вы вопрос на который отвечаете почитайте повнимательнее. или вы здесь так, от нечего делать?

Serega66
Offline
Зарегистрирован: 23.03.2018

Пробую разобраться с простым примером https://www.arduino.cc/en/Tutorial/Debounce и не могу сообразить, как правильно вынести этот код обработки кнопки в отдельную функцию. Чтобы он подошел для нескольких кнопок.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Serega66 пишет:

А вы вопрос на который отвечаете почитайте повнимательнее. или вы здесь так, от нечего делать?

Вы наверно не долго находитесь на форуме. Знаете есть такое высказывание, правильно поставленый вопрос это уже половина ответа. Но те кто открывают темы, и блин даже задают вопросы, на столько не в теме, что 100% задают именно не тот вопрос.  Вот и выходит, что отвечать на главный вопрос темы не нужно

Вопрос:Вы здесь так, от нечего делать?

ОТвет:Точно, именно так. Как и остальные здесь пишущие. Вот только не надо мне расказывать, что вас сюда наняли и вы получаете за это деньги.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Serega66 пишет:

Пробую разобраться с простым примером https://www.arduino.cc/en/Tutorial/Debounce и не могу сообразить, как правильно вынести этот код обработки кнопки в отдельную функцию. Чтобы он подошел для нескольких кнопок.

А здесь вопрос Ардуины и "домохозяйки". Если "домохозяйка" хочет поднять что она такая "крутая в программировании". То да примеры Ардуины для нее. "Опыт программирования домохозяйки" и "программирование как работа" это  совершено различные вещи. И не надо искать в "Мама мыла раму" как  начало в освоении космоса.  По цитате http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov

Serega66
Offline
Зарегистрирован: 23.03.2018

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

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

Serega66 пишет:

я просто как и многие здесь задал вопрос, на который пока никто не ответил

Какой именно вопрос Вы задали? Что-то пропустил, наверное. В каком посте?

Serega66
Offline
Зарегистрирован: 23.03.2018

На второй страничке форума по програмированию подписка MQTT  на половину своего вопроса я уже нашел ответ но вот решения проблемы пока нет.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Не могу понять причину очень странного глюка в  коде

const byte buttonPin_1 = 2;   // кнопка 1
const byte buttonPin_2 = 3;   // кнопка 2
const byte ledPin = 13;       // светодиод

bool button_1_state;           
bool button_2_state;             
bool lastButtonState_1 = HIGH;
bool lastButtonState_2 = HIGH;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void setup() {
  pinMode(buttonPin_1, INPUT_PULLUP);
  pinMode(buttonPin_2, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
 
  digitalWrite(ledPin, LOW); // светодиод выкл.
}
bool read_button (byte button_pin, bool prev_state) {
 

  bool lastButtonState = prev_state;
  bool buttonState = digitalRead(button_pin);
 
  if (buttonState != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

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

    if (buttonState != lastButtonState) {
      buttonState = lastButtonState;
      
    if (buttonState == LOW) return 1;
        else return 0;
      }
    }
   prev_state = buttonState;  // save the reading.
 }

void loop() {
   button_1_state = (read_button(buttonPin_1, lastButtonState_1));
   button_2_state = (read_button(buttonPin_2, lastButtonState_2));
   if (button_1_state) digitalWrite(ledPin, HIGH);
   if (button_2_state) digitalWrite(ledPin, LOW);
}

По идее клик по первой кнопке должен включать светодиод, а по второй - выключать его. Я пробовал в симуляторе, и получается, что при удержании первой кнопки, когда она нажата, светодиод не горит, а при отпускании загорается. На вторую кнопку он не реагирует вообще!
и очень странно, что он зажигается сразу же после включения, потому что в SETUP написано:

digitalWrite(ledPin, LOW); // светодиод выкл.

Код компилируется нормально - компилятор никаких одибок не находит!
В чём может быть причина? Кто разбирается, подскажите пожалуйста!

Serega66
Offline
Зарегистрирован: 23.03.2018

Уважаемый Junior_... я сам начинающий в этом деле и мне сложно посмотреть на код и найти ошибки но я хочу порекомендовать очень хорошие видео уроки от Jeremy Blum на ютубе он там очень подробно разжевывает и приводит примеры с кнопками и функцией дебоунс (https://www.youtube.com/watch?v=bO_jN0Lpz3Q&list=PLFdiWF2j2KnVHR0RbQxDeo...)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

/**/
unsigned long mill;// переменная для millis()
typedef void (*pDo)() ;// тип -функция обработчик
//--------------- Cl_Btn---------
//класс кнопка подключ на землю с программной подтяжкой
class Cl_Btn {
  protected:
    byte pin; // номер ноги на кнопке
    pDo Do;// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    /* конструктор класса*/
    Cl_Btn( byte p , pDo Do_): pin(p), Do(Do_) {}
    // метод init()
    void init() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // метод run()
    void run() {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//--------------компоновка------------
const byte ledPin = 13; // светодиод
void Do_Btn1() {
  digitalWrite(ledPin, HIGH);
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/Do_Btn1);
void Do_Btn2() {
  digitalWrite(ledPin, LOW);
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/Do_Btn2);
//------------main()--------------
void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); // светодиод выкл.
  Btn1.init();
  Btn2.init();
}
void loop() {
  mill = millis();
  Btn1.run();
  Btn2.run();
}
/*Скетч использует 1302 байт (4%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 33 байт (1%) динамической памяти, оставляя 2015 байт для локальных переменных. Максимум: 2048 байт.
*/

ПС:функция read_button по вашей логике должна вернуть 3 положения 1 - кнопка нажата 0 кнопка не нажата и ничего не вернуть если надо подождать дребезг.  При этом функция использует один lastDebounceTime на две кнопки. Что тоже глючно.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

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

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

Попытайтесь реализовать на С полиформизм. Как бы Вы хорошо не знали С, на нем это будет сделать намного муторное, чем на С++.

На FORTRAN IV тоже делали обработку текстов, хотя там начисто отсутствовал не просто символьный тип данных, но даже тип данных, который бы по размеру совпадал с символьным, не говоря о строках. Так и хранили по 4 символа в одной целой переменной.

Поддержка определенных парадигм программирования со стороны языка - это большое дело.

junior_developer
Offline
Зарегистрирован: 27.11.2017

qwone пишет:

ПС:функция read_button по вашей логике должна вернуть 3 положения 1 - кнопка нажата 0 кнопка не нажата и ничего не вернуть если надо подождать дребезг.  При этом функция использует один lastDebounceTime на две кнопки. Что тоже глючно.

  Если я Вас правильно понял, функция должна обязательно что то возвращать при кажом вызове? Если она не относится к типу void, верно?

И ещё мне нужно завести переменную для отслеживания времени нажатия каждой из кнопок.
назвать их например lastDebounceTime_1, lastDebounceTime_2. Эти переменные должны быть глобальными?

Serega66
Offline
Зарегистрирован: 23.03.2018

junior_develope Вот рабочий код на одну кнопку с функцией дебоунс. Посмотрите видео Блюма на Ютубе и у вас пропадут все вопросы ссылка в 30 сообщении

int switchPin = 3;
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);

}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

junior_developer , если настаивайте на своем варианте, то надо писать по 1 функции на каждую кнопку. И возвращать единицу если кнопка была только что нажата в этом цикле loop()

/**/
//----светодиод-----------------
const byte ledPin = 13;       // светодиод
//----кнопка1-----------------
const byte buttonPin_1 = 2;   // кнопка 1
bool button_1_state;
bool lastButtonState_1 = HIGH;
unsigned long lastDebounceTime_1 = 0;
const unsigned long debounceDelay = 50;
bool read_button_1 () {}; /*вернуть единицу если кнопка только что 1->0*/
//-----кнопка2----------------
const byte buttonPin_2 = 3;   // кнопка 2
bool button_2_state;
bool lastButtonState_2 = HIGH;
unsigned long lastDebounceTime_2 = 0;
bool read_button_2 () {}; /*вернуть единицу если кнопка только что 1->0*/
//--------------------------------
void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); // светодиод выкл.
  pinMode(buttonPin_1, INPUT_PULLUP);
  pinMode(buttonPin_2, INPUT_PULLUP);
}
void loop() {
  if (read_button_1 ()) digitalWrite(ledPin, HIGH);
  if (read_button_2 ()) digitalWrite(ledPin, LOW);
}

 

Serega66
Offline
Зарегистрирован: 23.03.2018

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

junior_developer
Offline
Зарегистрирован: 27.11.2017

К сожалению, я не могу сообразить, как сделать, чтобы функция возвращала 1 (то есть TRUE) только при нажатии? То есть:
если нет нажатия - вернуть 0;
если дребезг контактов - вернуть 0;
если нажатие  - вернуть 1;
Что мне для этого нужно? Добавить в свой код ещё одну строку return 0;

Serega66
Offline
Зарегистрирован: 23.03.2018

дебоунс работает так: если кнопка нажата а до этого была отпущена начать отсчет 5 миллисекунд а потом опять посмотреть если нажата то вернуть 1. Посмотрите видео там очень грамотно обьясняют

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
//----светодиод-----------------
const byte ledPin = 13;       // светодиод
//----кнопка1-----------------
const byte buttonPin_1 = 2;   // кнопка 1
bool button_1_state;
bool bounce1 = 0;
bool lastButtonState_1 = HIGH;
unsigned long lastDebounceTime_1 = 0;
const unsigned long debounceDelay = 50;
bool read_button_1 () { /*вернуть единицу если кнопка только что 1->0*/
  bool tmp = digitalRead(buttonPin_1);
  if (tmp != lastButtonState_1) {
    lastDebounceTime_1 = millis();
    bounce1 = 1;
  }
  if (bounce1 == 1 && millis() - lastDebounceTime_1 >= debounceDelay ) {
    bounce1 = 0;
    if (tmp == 0) return 1;
  }
  return 0;
};
//-----кнопка2----------------
const byte buttonPin_2 = 3;   // кнопка 2
bool button_2_state;
bool bounce2 = 0;
bool lastButtonState_2 = HIGH;
unsigned long lastDebounceTime_2 = 0;
bool read_button_2 () { /*вернуть единицу если кнопка только что 1->0*/
  bool tmp = digitalRead(buttonPin_2);
  if (tmp != lastButtonState_2) {
    lastDebounceTime_2 = millis();
    bounce2 = 1;
  }
  if (bounce2 == 1 && millis() - lastDebounceTime_1 >= debounceDelay ) {
    bounce2 = 0;
    if (tmp == 0) return 1;
  }
  return 0;
}
//--------------------------------
void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); // светодиод выкл.
  pinMode(buttonPin_1, INPUT_PULLUP);
  pinMode(buttonPin_2, INPUT_PULLUP);
}
void loop() {
  if (read_button_1 ()) digitalWrite(ledPin, HIGH);
  if (read_button_2 ()) digitalWrite(ledPin, LOW);
}
/*Скетч использует 1166 байт (3%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 19 байт (0%) динамической памяти, оставляя 2029 байт для локальных переменных. Максимум: 2048 байт.
*/

В программировании от домохозяек используется delay(5).

Serega66
Offline
Зарегистрирован: 23.03.2018

ну вот опять флуд ну поставьте миллис. помоему если играть кнопочками то можно и дилей 5 миллисекунд это не критично.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Я всё таки хочу разобраться с возвращением правильного значения из функции, которую написал. Подскажите в моем коде просто нужно удалить else return 0, а добавить  в конец функции read_button return 0;?
И функция будет всегда возвращать 0, если кнопка не нажата? Я верно рассуждаю?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Точно теперь у "знающего человека" "знания" поперли. Залейте в скеч и убедитесь. И не надо на симуляторах гонять.

junior_develope. Нет, неверно . Что у вас означает вернуть 0 и что означает вернуть 1 абстрагируясь от чисел. 

junior_developer
Offline
Зарегистрирован: 27.11.2017

значит нужно  писать TRUE и FALSE, а не 1 и 0? Если функция типа bool. Верно?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

1 0  или HIGH LOW или true false все это для удобства программиста и не больше.  Что бы реальный мир засунуть в компьютер надо его .... отцифровать . Программисты  вместо отцифровки используют абстрагирование, что где-то одно и тоже.

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

andriano пишет:

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

Это Вы либо что-то подзабыли, либо у Вас была неполная реализация. В родном фортране 4 от IBM всё было. Вот и в описании 4-ого фортрана, вроде есть всё что нужно. Они, конечно именно так и запихивались по 4, как Вы говорите, но тип-то был!

junior_developer
Offline
Зарегистрирован: 27.11.2017

qwone, большое Вам спасибо за подсказки! Я дописал в код ещё несколько строчек

lastButtonState_1 = tmp;
и...
lastButtonState_2 = tmp;

И ещё несколько строчек для отладки через порт! В итоге получилось так:

/**/
//----светодиод-----------------
const byte ledPin = 13;       // светодиод
//----кнопка1-----------------
const byte buttonPin_1 = 2;   // кнопка 1
bool button_1_state;
bool bounce1 = 0;
 bool lastButtonState_1 = HIGH;
unsigned long lastDebounceTime_1 = 0;
const unsigned long debounceDelay = 50;
bool read_button_1 () { /*вернуть единицу если кнопка только что 1->0*/
  bool tmp = digitalRead(buttonPin_1);
  if (tmp != lastButtonState_1) {
    lastDebounceTime_1 = millis();
    bounce1 = 1;
  }
  if (bounce1 == 1 && millis() - lastDebounceTime_1 >= debounceDelay ) {
    bounce1 = 0;
    if (tmp == 0) return 1;
  }
 
 lastButtonState_1 = tmp; 
  return 0; 
}
//-----кнопка2----------------
const byte buttonPin_2 = 3;   // кнопка 2
bool button_2_state;
bool bounce2 = 0;
 bool lastButtonState_2 = HIGH;
unsigned long lastDebounceTime_2 = 0;
bool read_button_2 () { /*вернуть единицу если кнопка только что 1->0*/
  bool tmp = digitalRead(buttonPin_2);
  if (tmp != lastButtonState_2) {
    lastDebounceTime_2 = millis();
    bounce2 = 1;
  }
  if (bounce2 == 1 && millis() - lastDebounceTime_2 >= debounceDelay ) {
    bounce2 = 0;
    if (tmp == 0) return 1;
  }
  
 lastButtonState_2 = tmp;
 return 0; 
}
//--------------------------------
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH); // светодиод вкл.
  pinMode(buttonPin_1, INPUT_PULLUP);
  pinMode(buttonPin_2, INPUT_PULLUP);
}
void loop() {
  if (read_button_1 ()) {digitalWrite(ledPin, HIGH); Serial.println("Press key_1");}
  if (read_button_2 ()) {digitalWrite(ledPin, LOW); Serial.println("Press key_2");}
}

Казалось бы, функции абсолютно идентичны, но дело в том, что первая кнопка срабатывала нормально (однократно), а вот вторая выдавала значения через Serial постоянно с очень небольшим интервалом! Очень долго думал, КАК такое может быть?

И в итоге нашел - ошибка была в сроке 37! Заменил

lastDebounceTime_1   на   lastDebounceTime_2  

Теперь работает нормально! Однако если проанализировать код с неправильно указанной переменной, то вот этот кусочек разве должен срабатывать многократно? Там же переменная bounce2 обнуляется, а чтобы условие сработало, нужно 1, а не ноль! Верно?
 

 if (bounce2 == 1 && millis() - lastDebounceTime_1 >= debounceDelay ) {
    bounce2 = 0;

    if (tmp == 0) return 1;
  }


 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

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

Это Вы либо что-то подзабыли, либо у Вас была неполная реализация. В родном фортране 4 от IBM всё было. Вот и в описании 4-ого фортрана, вроде есть всё что нужно. Они, конечно именно так и запихивались по 4, как Вы говорите, но тип-то был!

Ну да, тип был.

                    CHARACTER            literals:     4HJOHN
                                                       6HR CASH
                                                       'JOHNNY CASH'   -- note, not ASA standard 

но того, что в третьей строке - не было.

А может - я что-то и пордзабыл. Например, пользуясь компилятором FORTRAN IV, читал документацию к FORTRAN II.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Подскажите пожалуйста, как расшифровывается эта строчка
 

typedef void (*pDo)() ;// тип -функция обработчик

в этом коде
 

/**/
unsigned long mill;// переменная для millis()
typedef void (*pDo)() ;// тип -функция обработчик
//--------------- Cl_Btn---------
//класс кнопка подключ на землю с программной подтяжкой
class Cl_Btn {
  protected:
    byte pin; // номер ноги на кнопке
    pDo Do;// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    /* конструктор класса*/
    Cl_Btn( byte p , pDo Do_): pin(p), Do(Do_) {}
    // метод init()
    void init() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // метод run()
    void run() {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//--------------компоновка------------
const byte ledPin = 13; // светодиод
void Do_Btn1() {
  digitalWrite(ledPin, HIGH);
}
Cl_Btn Btn1(/*пин*/2,/*обработчик*/Do_Btn1);
void Do_Btn2() {
  digitalWrite(ledPin, LOW);
}
Cl_Btn Btn2(/*пин*/3,/*обработчик*/Do_Btn2);
//------------main()--------------
void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); // светодиод выкл.
  Btn1.init();
  Btn2.init();
}
void loop() {
  mill = millis();
  Btn1.run();
  Btn2.run();
}
/*Скетч использует 1302 байт (4%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 33 байт (1%) динамической памяти, оставляя 2015 байт для локальных переменных. Максимум: 2048 байт.
*/

Зачем там звездочка в этой строке? Это какой то специальный тип функции?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

создать новый тип данных - указатель на функцию http://purecodecpp.com/archives/2301