Помощь по библиотеке GuverButton

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
Доброго времени суток форумчане!
Помогите, неразумному, где затык? Прописал код, но он не переключается с кнопки.

#define g2 10 //транзистор 1
#define g3 13 //транзистор 2

#include "GyverButton.h"
GButton butt1(3);
uint8_t flag = 1;

void setup() {
// put your setup code here, to run once:
pinMode(g2,OUTPUT);
pinMode(g3,OUTPUT);
digitalWrite(g2,LOW);
digitalWrite(g3,LOW);
}

void loop() {
butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться
if (butt1.isPress() && flag == 1){
// put your main code here, to run repeatedly:
butt1.tick();
flag = 0;
digitalWrite(g3,LOW);
}
if (flag == 1){
butt1.tick();
/*
digitalWrite(g2,HIGH);
delay(1);
digitalWrite(g2,LOW);
//delayMicroseconds(42900);
delay(4);*/
digitalWrite(g3,HIGH);
delay(1000);
digitalWrite(g3,LOW);
//delayMicroseconds(42900);
delay(1000);
butt1.tick();
}
if (butt1.isPress() && flag == 0){
flag = 1;
digitalWrite(g3,LOW);
butt1.tick();}

}
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Каша мягко сказано
1) 1 проход цикла должен соотв однму тику, а тут штуки 4 вроде
2) За один проход обрабатывается одно событие, находится сравнением
3) Что подключено на g2 ? подача высокого сигнала на 1 миллисекунду визуально не будет никак видно
 

kalobyte

★★★✩✩✩✩
1 Янв 2020
726
146
соглашусь с кашей
похоже автор перестраховался и вызывает тик на каждом чихе :LOL:
 

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
@Эдуард Анисимов, По сути она должна переключать состояние включения пульсации и выключения по требованию кнопки. Раз нажал - работает, второй - затухло. Я за комментировал блок с микропульсациями, дабы вкурить, как управлять этой глупой кнопкой адекватно работу импульсов через светодиод 13 пина. просто на будущее я хотел бы переключать пульсации одной кнопкой, так что думал флаги меня спасут. Но из-за того, что жирные макаронники (создатели Arduino) ушли в разработку клона Raspberry, вместо того, чтобы включить в среду разработки возможность построково просмотреть код и видеть состояния переменных (как в UnoArduSim, но создатель не хочет прописывать поддержку всех библиотек), было бы намного проще новичкам понять работу кода и находить ошибки, учиться, а самое главное не мучить добрых людей на форумах, что компилятор не выдал ошибку, а код все равно г.....
 

kostyamat

★★★★★★✩
29 Окт 2019
1,097
630
Библиотека не причем, вы все убили delay(), изучайте
https://www.arduino.cc/en/tutorial/BlinkWithoutDelay
И ещё, я бы обрабатывал клик на кнопку, а не нажатие. Потому как клик засчитывается как одиночное событие, а нажатие как длительное состояния. Программа просто не знает отпускали ли вы кнопку. Клик - делаем, ещё раз клик - не делаем. Нажали - делаем пока нажато, но не знаем в начале следующего цикла отпускали ли кнопку, или продолжаем удерживать полчаса.
 
Изменено:

kalobyte

★★★✩✩✩✩
1 Янв 2020
726
146
Я за комментировал блок с микропульсациями,
пульсации делаются при помощи библиотеки таймеров
https://alexgyver.ru/gyvertimers/

вместо того, чтобы включить в среду разработки возможность построково просмотреть код и видеть состояния переменных
это давно уже делает протеус
 
  • Лойс +1
Реакции: skynepdai

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
@kalobyte, Благодарю за ответ. Изучение протеуса займет пол жизни, ибо штука мощная и наскоком не берется. А по поводу пульсаций, не хотел использовать библиотеки, ибо импульсы должны быть ровными и милисекундном и микросекундном тике. а нагромождение библиотек могут вносить глюки. Хотел как проще. Значит вместо понимания процессов, просто тупо буду штудировать гайды, тырить строки кода и молиться, что-бы франкенштейн ожил.
 

kalobyte

★★★✩✩✩✩
1 Янв 2020
726
146
Изучение протеуса займет пол жизни, ибо штука мощная и наскоком не берется.
достаточно посмотреть 10 минут ролик
Хотел как проще.
библиотеки для этого и созданы, чтобы не изобретать велосипеды с квадратными колесами
 

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
@kalobyte, Вот, использовал библиотеки, избавился от delay. Но всё равно код исполняет мигание светодиодом от кнопки, но повторное нажатие не выключает его. И где затык не видно

#define g2 10 //транзистор 2
#define g3 13 //транзистор 2

#include "GyverButton.h"
GButton butt1(3);
uint8_t flag = 1;
#include "GyverTimer.h"
GTimer myTimer1(MS);
GTimer myTimer2(MS);
void setup() {
// put your setup code here, to run once:
pinMode(g2,OUTPUT);
pinMode(g3,OUTPUT);
digitalWrite(g2,LOW);
digitalWrite(g3,LOW);
myTimer1.setTimeout(300);
}

void loop() {
butt1.tick(); // обязательная функция отработки. Должна постоянно опрашиваться
if (butt1.isSingle() && flag == 1){
// put your main code here, to run repeatedly:
flag = 0;
}



if (butt1.isSingle() && flag == 0){
flag = 1;
}
if (flag == 1){
off();}
if (flag == 0){
on();}

}
void on()
{
butt1.tick();
/*
digitalWrite(g2,HIGH);
delay(1);
digitalWrite(g2,LOW);
//delayMicroseconds(42900);
delay(4);*/

if (myTimer1.isReady())
{digitalWrite(g3,LOW);
myTimer2.setTimeout(1000);}

if (myTimer2.isReady())
{digitalWrite(g3,HIGH);
myTimer1.setTimeout(1000);}

//delayMicroseconds(42900);


}

void off()
{

digitalWrite(g3,LOW);
}
 

kalobyte

★★★✩✩✩✩
1 Янв 2020
726
146
я малость протупил и дал не тот линк на таймеры, там аппаратные микросекундные таймеры, а тебе надо долгие
https://alexgyver.ru/gyvertimer/
там пример с кнопкой есть даже

когда постиш код, то оборачивай его в тег для кода, чтобы форматирование и подсветка была

если напишеш, что там твой скетч делать должен, то я попробую написать и смакетировать или в протеусе сделаю, как-то лень опять все барахло доставать
я тут генеральную уборку затеял в хате:eek:
 
  • Лойс +1
Реакции: skynepdai

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
@kalobyte, Спасибо, что отвечаешь, я не в курсе, как оборачивать в тэг.
@kalobyte, И я изучил протеус. Это просто эмулятор ардуино, А я говорил про понимание, как реагирует код на выполнение. Вот как это выглядит в UnoArduSim: https://drive.google.com/open?id=1SuvNIa51iZbASVcxyairxzgBGQbNch0Q
 

kalobyte

★★★✩✩✩✩
1 Янв 2020
726
146
А я говорил про понимание, как реагирует код на выполнение
это называется отлакда и для этого в протеус загружается .elf файл и там в меню надо выбрать окно отладки и тогда код будет виден

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

что твой код должен делать конкретно?
 

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
@kalobyte, Всё просто, он должен пульсировать с уровнем High 1 мс, и Low с предварительно обозначенным интервалом. И переключение режимов по нажатию кнопки. И спасибо за тэг


C#:
#define g2 10 //транзистор 2
#define g3 13 //транзистор 2

#include "GyverButton.h"
GButton butt1(3);
uint8_t flag = 1;
#include "GyverTimer.h"
GTimer myTimer1(MS);
GTimer myTimer2(MS);
void setup() {
  // put your setup code here, to run once:
pinMode(g2,OUTPUT);
pinMode(g3,OUTPUT);
digitalWrite(g2,LOW);
digitalWrite(g3,LOW);
myTimer1.setTimeout(300);
}

void loop() {
  butt1.tick();  // обязательная функция отработки. Должна постоянно опрашиваться
   if (butt1.isSingle() && flag == 1){
  // put your main code here, to run repeatedly:
 flag = 0;
  }

 

if (butt1.isSingle() && flag == 0){
  flag = 1;
}
if (flag == 1){
    off();}
if (flag == 0){
  on();}
 
    }
void on()
{
   butt1.tick();
    /*
digitalWrite(g2,HIGH);
delay(1);
digitalWrite(g2,LOW);
//delayMicroseconds(42900);
delay(4);*/

if (myTimer1.isReady())
{digitalWrite(g3,LOW);
myTimer2.setTimeout(1000);}

if (myTimer2.isReady())
{digitalWrite(g3,HIGH);
myTimer1.setTimeout(1000);}

//delayMicroseconds(42900);

 
}

void off()
{

  digitalWrite(g3,LOW);
  }
 

kostyamat

★★★★★★✩
29 Окт 2019
1,097
630
@skynepdai,
C++:
GButton butt1(3);
GTimer myTimer1(MS);
// GTimer myTimer2(MS);   // этот таймер лишний

bool flag = false;                  // для двух состояний проще использовать булевый флаг, а не инт


void setup() {
  pinMode(g2, OUTPUT);
  pinMode(g3, OUTPUT);
  digitalWrite(g2, LOW);
  digitalWrite(g3, LOW);
  myTimer1.setTimeout(300);
}



void loop() {
  butt1.tick();  // обязательная функция отработки. Должна постоянно опрашиваться


  if (butt1.isClick()) {                  // обрабатываем клик на кнопку
    // put your main code here, to run repeatedly:
    flag = !flag;                         // и меняем состояние флага на противоположное - ТИК-ТАК
  }

  if (flag) {                             // если флаг TRUE то выполняем включение
    on();
  } else {                                // иначе (флаг FALSE) - выключение
    off();
  }

}



void on() {
  if (digitalRead(g3) and myTimer1.isReady()) // если состояние пина g3 высокое и таймер избежал,
  {
    digitalWrite(g3, LOW);   // устанавливаем пин в низкое состояние и
    myTimer1.setTimeout(1000);   // взводим таймер для низкого сотояния
  }

  if (!digitalRead(g3) and myTimer1.isReady()) // если все еще состояние низкого уровня, но таймер для него избежал
  {
    digitalWrite(g3, HIGH);    // то снова устанавливаем высокое состояние
    myTimer1.setTimeout(1000); // но уже для высокого состояния пина. Так получаем ТИК-ТАК логику, и второй таймер не нужен
  }
}



void off()
{

  digitalWrite(g3, LOW);
}
Читайте мои примечания к коду

Еще один вариант функции on() он лучше тем, что не теряет время на чтение состояния пина. Но плох тем, что при следующем включении начнет с места остановки

C++:
void on() {
  static bool on_off; // статические переменные не стираются между вызовами функции
  
  if (on_off) and myTimer1.isReady()) // если переменная on_off true и таймер избежал,
  {
    digitalWrite(g3, LOW);   // устанавливаем пин в низкое состояние и
    myTimer1.setTimeout(1000);   // взводим таймер для низкого сотояния
    on_off = false;             
  }

  if (!on_off and myTimer1.isReady()) // если on_off == false, но таймер этого этапа избежал
  {
    digitalWrite(g3, HIGH);    // то снова устанавливаем высокое состояние
    myTimer1.setTimeout(1000); // но уже для высокого состояния пина. Так получаем ТИК-ТАК логику, и второй таймер не нужен
    on_off = true;
  }
}
 
Изменено:

skynepdai

✩✩✩✩✩✩✩
9 Мар 2020
19
0
@kostyamat, Блин, круто! Работает. Есть правда маленький вопрос: я не спроста сделал флаг числовым, дабы была возможность переключать режимы (т.е. наращивать любое количество режимов с переключением по одной кнопке)
 

kostyamat

★★★★★★✩
29 Окт 2019
1,097
630
я не спроста сделал флаг числовым, дабы была возможность переключать режимы (т.е. наращивать любое количество режимов с переключением по одной кнопке)
Ну, можно и так, к примеру
C++:
#define g2 10 //транзистор 2
#define g3 13 //транзистор 2

#include "GyverButton.h"
#include "GyverTimer.h"


GButton butt1(3);
GTimer myTimer1(MS);
// GTimer myTimer2(MS);

byte mode = 0;   // переменная для номера режима работы


void setup() {
  pinMode(g2, OUTPUT);
  pinMode(g3, OUTPUT);
  digitalWrite(g2, LOW);
  digitalWrite(g3, LOW);
  myTimer1.setTimeout(300);
}



void loop() {
  butt1.tick();  // обязательная функция отработки. Должна постоянно опрашиваться


  if (butt1.isClick()) {                  // обрабатываем клик на кнопку
    // put your main code here, to run repeatedly:
    mode += 1;                         // и приращиваем переменную на единицу
  }

  switch mode {                        // селектор по значению переменной mode
  case 1:                              // если значение переменной 1, то
    on(1000, 2000);                    // запускаем функцию on() передавая ей два параметра - значение таймера для состояния HIGH и для состояния LOW
      break;                           // выходим в loop, если break убрать, то сравнение значения переменной и селектора пойдет дальше по селектору (иногда такое поведение уместно)

    case 2:                            // аналогично тому что выше
      on(500, 1000);                   // только значения для таймеров другое
      break;

    default:                           // если количество нажатий перескочило за задуманное нами количество режимов
      off();                           // выключаем все
      mode = 0;                        // сбрасываем номер режима в ноль
      break;
  }

}



void on(static uint32_t timerHigh, static uint32_t timerLow) {
  static bool on_off;

  if (on_off) and myTimer1.isReady()) // если состояние пина g3 высокое и таймер избежал,
  {
    digitalWrite(g3, LOW);   // устанавливаем пин в низкое состояние и
    myTimer1.setTimeout(timerLow);   // взводим таймер для низкого сотояния
    on_off = false;
  }

  if (!on_off and myTimer1.isReady()) // если все еще состояние низкого уровня, но таймер для него избежал
  {
    digitalWrite(g3, HIGH);    // то снова устанавливаем высокое состояние
    myTimer1.setTimeout(timerHigh); // но уже для высокого состояния пина. Так получаем ТИК-ТАК логику, и второй таймер не нужен
    on_off = true;
  }
}



void off()
{

  digitalWrite(g3, LOW);
}
Upd: немного поправил пример. Так как функция on() получилась как callback (вызывается каждый проход loop и каждый раз продолжая работу, а не начиная сызнова) то нужно бы сохранять переданные ей параметры, поэтому объявляем передаваемые ей параметры как static, чтобы значения не протухали между вызовами. В принципе, если этого не сделать, то компилятор сам подставит параметры вызова из каждого case. Но если вместо константных значение передавать результаты каких либо расчетов, то работать не будет. Так что лучше сразу предостеречься от ошибки, и объявить входные переменные timerHigh, timerLow как static.
 
Изменено:

kalobyte

★★★✩✩✩✩
1 Янв 2020
726
146
@kostyamat,
чего там сложного? вот я помню давно никак не мог понять, что такое функции обратного вызова и почему в нее нельзя передавать параметры и не пишутся скобки как обычно
вся сложно была в том, что не было нормальных источников инфы, которые бы поясняли это в 2х словах
сейчас я это все понял и могу в 2х словах пояснить
поэтому ничего сложного там нет, просто не надо читать ботанские гавнакниги