Проблема с функциями
- Войдите на сайт для отправки комментариев
Вс, 16/04/2017 - 19:00
Здравствуйте!
Раньше программил на 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 (состояние кнопки) задекларирована глобально и когда я раскомментирую вторую функцию, то она меняет ее состояние независимо от первой. Хотя могу и ошибаться.
Прошу помощи!
Заранее большое спасибо!
Оформи функцию как класс и проблем не будет.
Уже подумал об этом, но с классами у меня вообще сложности))) Поэтому думал можно ли обойтись функциями. Или если бы могли помочь оформить на этом примере, был бы примного благодарен!
Можна и одной обойтись. Но вместо переменных делать массив и обращатся к элементам по индексу - номеру пина.
Но вообще пересмотрите лучше всю философию подхода. Не стоит так абстрагироватся. Эта часть опыта пыхи не актуальна. Кнопка не может быть на любом пине! Она только на том, к которому припаяна )))
Можна и одной обойтись. Но вместо переменных делать массив и обращатся к элементам по индексу - номеру пина.
Но вообще пересмотрите лучше всю философию подхода. Не стоит так абстрагироватся. Эта часть опыта пыхи не актуальна. Кнопка не может быть на любом пине! Она только на том, к которому припаяна )))
Так тоже уже думал, думал ввести в функцию ID этого вызова функции, например, но не понимаю, как реализовать это.
Прошу помощи, было бы отлично, если бы с примером. А дальше пойду сам.
Спасибо большое!
Оформи функцию как класс и проблем не будет.
Переписал на класс, эффект тот же... Явно делаю что-то не так...
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); }Попробуй так
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(); }Останется тебе понять когда ты назначаешь timeButton и зачем она тебе нужна?
Здравствуйте!
Раньше программил на PHP, но тут, хоть и синтаксис похож все по другом, в частности исполнение в loop, а не последовательно как в PHP, никак не могу привыкнуть)))
Поэтому прошу помощи.
Здравствуйте!
Раньше программил на PHP, но тут, хоть и синтаксис похож все по другом, в частности исполнение в loop, а не последовательно как в PHP, никак не могу привыкнуть)))
Поэтому прошу помощи.
Спасибо за комментарий! Сложно, но пытаюсь понять.
А как решить это, вот вопрос?
Решение Вам дали в #6 я просто объяснил Вашу проблему.
Можна и одной обойтись. Но вместо переменных делать массив и обращатся к элементам по индексу - номеру пина.
Но вообще пересмотрите лучше всю философию подхода. Не стоит так абстрагироватся. Эта часть опыта пыхи не актуальна. Кнопка не может быть на любом пине! Она только на том, к которому припаяна )))
Так тоже уже думал, думал ввести в функцию 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.
Если поменять встрочках 13 и 42 uint8_t на uint32_t то работает