Проблема с функциями

stechdoch
Offline
Зарегистрирован: 16.04.2017

Здравствуйте!

Раньше программил на PHP, но тут, хоть и синтаксис похож все по другом, в частности исполнение в loop, а не последовательно как в PHP, никак не могу привыкнуть)))

Поэтому прошу помощи.

Суть такая.

Есть некоторый код (я его максимально скоратил, чтобы не вдаваться в подробности):

 

uint32_t timeButton;

bool stateButtonUP;
  
void setup()
{
  Serial.begin(9600);
  Serial.println("Start...");

   pinMode(2, INPUT_PULLUP);
   pinMode(3, INPUT_PULLUP);
}

void loop(){

  testButton(2);
  //testButton(3); // !!!!если раскомментировать, то будут проблемы!!!!

}

int testButton(int PinButtonUP) { // Функция управления
   
    uint32_t timeNow    = millis();

      // Фиксируем нажатие кнопки UP // 
   if( digitalRead(PinButtonUP)  == HIGH && !stateButtonUP && ( timeNow - timeButton ) > 50 ){
      stateButtonUP      = true; 

      Serial.println(" "); 
      Serial.println(" "); 
      Serial.println("********");    
      Serial.println("Press Button on PIN number");
      Serial.println(PinButtonUP);    
   }

      // Фиксируем отпускание кнопки UP // 
   if( digitalRead(PinButtonUP) == LOW && stateButtonUP && ( timeNow - timeButton ) > 50  ){
      stateButtonUP      = false;  
      
      Serial.println("Realse Button");
      Serial.println("********");       
   }
   
}   


 
 
Так вот, если запустить его как есть, с одним выводом функции testButton(2) http://prntscr.com/ex3jaq , то все работает как нужно, то есть при нажатии на кнопку на пине 2 происходит единичный вывод следующих строк в монитор:
 
Start...
 
 
********
Press Button on PIN number
2
Realse Button
********
 
То есть фиксируется нажатие и отпускание кнопки, сколько кнопку не держи, вывод будет один раз.
 
Если же я раскомментирую второе использование функции testButton(3) http://prntscr.com/ex3jig , то у Ардуино едет крыша и при нажатии на кнопку один раз он выводит в монитор сразу кучу нажатий http://prntscr.com/ex3i5r
 
Я подозреваю, что проблема в том, что переменная bool stateButtonUP (состояние кнопки) задекларирована глобально и когда я раскомментирую вторую функцию, то она меняет ее состояние независимо от первой. Хотя могу и ошибаться.
 
Прошу помощи!
Заранее большое спасибо!
 

 

JasKo
Offline
Зарегистрирован: 21.11.2015

Оформи функцию как класс и проблем не будет.

stechdoch
Offline
Зарегистрирован: 16.04.2017

Уже подумал об этом, но с классами у меня вообще сложности))) Поэтому думал можно ли обойтись функциями. Или если бы могли помочь оформить на этом примере, был бы примного благодарен!

Logik
Offline
Зарегистрирован: 05.08.2014

Можна и одной обойтись. Но вместо переменных делать массив и обращатся к элементам по индексу - номеру пина. 

Но вообще пересмотрите лучше всю философию подхода. Не стоит так абстрагироватся. Эта часть опыта пыхи не актуальна. Кнопка не может быть на любом пине! Она только на том, к которому припаяна )))

stechdoch
Offline
Зарегистрирован: 16.04.2017

Logik пишет:

Можна и одной обойтись. Но вместо переменных делать массив и обращатся к элементам по индексу - номеру пина. 

Но вообще пересмотрите лучше всю философию подхода. Не стоит так абстрагироватся. Эта часть опыта пыхи не актуальна. Кнопка не может быть на любом пине! Она только на том, к которому припаяна )))

 

Так тоже уже думал, думал ввести в функцию ID этого вызова функции, например, но не понимаю, как реализовать это.

Прошу помощи, было бы отлично, если бы с примером. А дальше пойду сам.

 

Спасибо большое!

stechdoch
Offline
Зарегистрирован: 16.04.2017

JasKo пишет:

Оформи функцию как класс и проблем не будет.

Переписал на класс, эффект тот же... Явно делаю что-то не так...

class TestClass {

   private:
   uint32_t timeButton;
   bool stateButtonUP;
   int PinButtonUP;
   
   public:

   int testButton(int PinButtonUP) { // Функция управления
       
        uint32_t timeNow    = millis();
    
          // Фиксируем нажатие кнопки UP // 
       if( digitalRead(PinButtonUP)  == HIGH && !stateButtonUP && ( timeNow - timeButton ) > 50 ){
          stateButtonUP      = true; 
    
          Serial.println(" "); 
          Serial.println(" "); 
          Serial.println("********");    
          Serial.println("Press Button on PIN number");
          Serial.println(PinButtonUP);    
       }
     
          // Фиксируем отпускание кнопки UP // 
       if( digitalRead(PinButtonUP) == LOW && stateButtonUP && ( timeNow - timeButton ) > 50  ){
          stateButtonUP      = false;  
          
          Serial.println("Realse Button");
          Serial.println("********");       
       }
       
    }  

};

TestClass button;
  
void setup()
{
  Serial.begin(9600);
  Serial.println("Start...");

   pinMode(2, INPUT_PULLUP);
   pinMode(3, INPUT_PULLUP);
   
}

void loop(){
  
  button.testButton(2);
  button.testButton(3);
}
 
Прошу помощи((((
JasKo
Offline
Зарегистрирован: 21.11.2015

Попробуй так

class TestClass {

   private:
   uint32_t timeButton;
   bool stateButtonUP;
   int PinButtonUP;
   
   public:
   TestClass(int pin){
    PinButtonUP = pin;
    pinMode(PinButtonUP, INPUT_PULLUP);
   }

   void Update() { // Функция управления
       
        uint32_t timeNow    = millis();
    
          // Фиксируем нажатие кнопки UP // 
       if( digitalRead(PinButtonUP)  == HIGH && !stateButtonUP && ( timeNow - timeButton ) > 50 ){
          stateButtonUP      = true; 
    
          Serial.println(" "); 
          Serial.println(" "); 
          Serial.println("********");    
          Serial.println("Press Button on PIN number");
          Serial.println(PinButtonUP);    
       }
     
          // Фиксируем отпускание кнопки UP // 
       if( digitalRead(PinButtonUP) == LOW && stateButtonUP && ( timeNow - timeButton ) > 50  ){
          stateButtonUP      = false;  
          
          Serial.println("Realse Button");
          Serial.println("********");       
       }
       
    }  

};

TestClass button1(2);
TestClass button2(3);

  
void setup()
{
  Serial.begin(9600);
  Serial.println("Start...");

   
}

void loop(){
  
  button1.Update();
  button2.Update();
}

 

JasKo
Offline
Зарегистрирован: 21.11.2015

Останется тебе понять когда ты назначаешь timeButton и зачем она тебе нужна?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

stechdoch пишет:

Здравствуйте!

Раньше программил на PHP, но тут, хоть и синтаксис похож все по другом, в частности исполнение в loop, а не последовательно как в PHP, никак не могу привыкнуть)))

Поэтому прошу помощи.

По Вашему коду чтобы понять в чем проблема.
У Вас на кнопках включена подтяжка - значит при не нажатых кнопках на пине 1
Лооп постоянно крутится покругу, Нажали кнопку - в функцию передали 0
функция отработала и программа вернулась в лооп а там идет проверка следующего пинна на котором - подтяжка
и в функцию передается 1, и получается что кнопку Вы отпустили хотя отпущена не вторая а третья 
stechdoch
Offline
Зарегистрирован: 16.04.2017

vosara пишет:

stechdoch пишет:

Здравствуйте!

Раньше программил на PHP, но тут, хоть и синтаксис похож все по другом, в частности исполнение в loop, а не последовательно как в PHP, никак не могу привыкнуть)))

Поэтому прошу помощи.

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

 

Спасибо за комментарий! Сложно, но пытаюсь понять.

А как решить это, вот вопрос?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Решение Вам дали в #6 я просто объяснил Вашу проблему.

Logik
Offline
Зарегистрирован: 05.08.2014

stechdoch пишет:

Logik пишет:

Можна и одной обойтись. Но вместо переменных делать массив и обращатся к элементам по индексу - номеру пина. 

Но вообще пересмотрите лучше всю философию подхода. Не стоит так абстрагироватся. Эта часть опыта пыхи не актуальна. Кнопка не может быть на любом пине! Она только на том, к которому припаяна )))

 

Так тоже уже думал, думал ввести в функцию ID этого вызова функции, например, но не понимаю, как реализовать это.

Прошу помощи, было бы отлично, если бы с примером. А дальше пойду сам.

 

Спасибо большое!

Попробуем. Дело в том что не тестированый пример - плохое дело, но гдето так

uint8_t stateButtonsUP; //8 бит до 8 кнопок
uint8_t PinKeys[8]={3,4,5,6,A0,A1,A2,A3};  //массив задействованых под кнопки пинов 


void setup() {
 for(byte i=0;i<sizeof(PinKeys);i++)   //в цикле инициализируем пины
  {pinMode(PinKeys[i], INPUT_PULLUP);}

}

void Update(uint8_t t)
{
  static uint8_t timeButton;
  if(t-timeButton>50)  //занимаемся кнопками не чаще 50мсек
  {
    for(byte i=0;i<sizeof(PinKeys);i++)  //в цикле перебираем пины
    {
     if(digitalRead(PinKeys[i])==HIGH)   //высокий - знач не нажата кнопка
     {
       if((stateButtonsUP & _BV(i))==0) //проверяем что был низкий значить отпустили
       {
         stateButtonsUP|=_BV(i);  // теперь будет высокий
         Serial.println("Realse Button");
       }
     }
     else // не высокий - знач низкий и кнопка нажата
     {
       if((stateButtonsUP & _BV(i))!=0) //проверяем что был высокий, значить нажатие
       {
         stateButtonsUP&=~_BV(i);  //теперь будет низкий
         Serial.println("Press Button on PIN number");
         Serial.println(i);   
       }
     }
    }
    timeButton=t;
  }
}

void loop() {

 uint8_t t=millis();  //сохраним время тут, может еще для чего пригодится
 Update(t);
}

Поддержка до восьми кнопок, ограничение через stateButtonsUP, она 8 бит, по биту на кнопку. Таким образом она как масивчик работает;) PinKeys думаю понятно, задает соответствие ID кнопки 0..7 и номера пина. Это позволяет инитить и обрабатывать все в цикле по ID. Проверку нажатий нет смысла делать часто, 50мсек вполне оптимально, у Вас в коде такая проверка по сути тоже есть, делать проверку времени для каждой кнопки - вредное излишество. Или все или не одна. Дальше почти ваш код с учетом хитроделаности stateButtonsUP и того факта, что если не digitalRead(PinKeys[i])==HIGH , то это LOW.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Если поменять встрочках 13 и 42 uint8_t на uint32_t то работает