Не меняется переменная

Darrel
Offline
Зарегистрирован: 17.08.2019

День (вечер-ночь-утро) добрый уважаемое сообщество!

Делаю мини-комп на велик (с кучей всего)
Теперь собственно вопрос.
- при зажатии клавиши переменная режима (mode) скачет туда-сюда
- не изменяется переменная меню экрана (screen), кнопки точно рабочие)

#include <GyverTimer.h>
GTimer_ms blinc;
GTimer_ms stopl;

#include <iarduino_RTC.h>
iarduino_RTC time(RTC_DS1302, 3, 9, 4);

#include <GyverButton.h>
GButton butt_r(10); //кнопка право
GButton butt_l(11); //кнопка лево
GButton butt_c(12); //кнопка центр
GButton butt_s(A2); //кнопка stop
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

#include <EEPROM.h>


unsigned long lastturn, time_press; //переменные хранения времени
float SPEED; //переменная хранения скорости в виде десятичной дроби
float DIST; //переменная хранения расстояния в виде десятичной дроби
float w_length = 2.060; //длина окружности колеса в метрах
byte light = 0; //режим работы габаритов
int screen = 0; //режим работы дисплея
bool mode = 0; //режим работы кнопок
bool alarm = 0; // сигнализация

void setup() {
  // настройки пинов
  pinMode(5, OUTPUT); //свет середина
  pinMode(6, OUTPUT); //свет право
  pinMode(7, OUTPUT); //свет центр
  pinMode(8, OUTPUT); //свет лево
  pinMode(13, OUTPUT); //свет лево контрол
  pinMode(A0, OUTPUT); //свет центр контрол
  pinMode(A1, OUTPUT); //свет право контрол
  pinMode(A3, OUTPUT); //зуммер

  time.begin();
  lcd.init();
  lcd.init();
  lcd.backlight();
  blinc.setInterval(777);
  stopl.setInterval(7777);

  Serial.begin(9600);  //открыть порт

  attachInterrupt(0, sens, RISING); //подключить прерывание на 2 пин при повышении сигнала

  //--------------
  DIST = (float)EEPROM.read(0) / 10.0; //вспоминаем пройденное расстояние при запуске системы (деление на 10 нужно для сохранения десятых долей расстояния, см. запись)
}

void sens() {
  if (millis() - lastturn > 80) { //защита от случайных измерений (основано на том, что велосипед не будет ехать быстрее 120 кмч)
    SPEED = w_length / ((float)(millis() - lastturn) / 1000) * 3.6; //расчет скорости, км/ч
    lastturn = millis(); //запомнить время последнего оборота
    DIST = DIST + w_length / 1000; //прибавляем длину колеса к дистанции при каждом обороте оного
  }
}

void loop() {
  // отработка кнопок
 Serial.print(screen); 
 Serial.println(mode);
  butt_l.tick();
  butt_c.tick();
  butt_r.tick();
  butt_s.tick();
  if (butt_l.isClick() && mode == 0) light = 1;
  if (butt_l.isClick() && mode == 1) {screen--;}
  if (butt_r.isClick() && mode == 0) light = 2;
  if (butt_r.isClick() && mode == 1) {screen++;}
  if (butt_c.isClick() && mode == 0) light = 3;
  if (butt_c.isDouble() && mode == 0) light = 4;
  if (butt_c.isHold()) mode = !mode;
  if (butt_s.isPress()) light = 5;
  if (butt_s.isRelease()) light = 0;

  // отработка кнопок

  // отработка габаритов
  switch (light) {
    case 0: off();
      break;
    case 1: left();
      break;
    case 2: right();
      break;
    case 3: stop_1();
      break;
    case 4: stop_2();
      break;
  }

  // отработка экрана
  switch (screen) {
    case 0: def();
      break;
    case 1: date();
      break;
    case 2: max_s();
      break;
    case 3: max_d();
      break;
    case 4: alrm();
      break;
  }
}

// функции габаритов
void off() {
  digitalWrite (5, 0);
  digitalWrite (6, 0);
  digitalWrite (7, 0);
  digitalWrite (8, 0);
  digitalWrite (A0, 0);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);
}
void left() {
  digitalWrite (8, 1);
  digitalWrite (7, 1);
  digitalWrite (13, 1);
  digitalWrite (5, 0);
  digitalWrite (6, 0);
  digitalWrite (A0, 0);
  digitalWrite (A1, 0);
  if (blinc.isReady()) {
    digitalWrite (8, !digitalRead(8));
  }
  if (butt_l.isDouble()) light = 0;
}
void right() {
  digitalWrite (6, 1);
  digitalWrite (7, 1);
  digitalWrite (A1, 1);
  digitalWrite (5, 0);;
  digitalWrite (8, 0);
  digitalWrite (A0, 0);
  digitalWrite (13, 0);
  if (blinc.isReady()) {
    digitalWrite (6, !digitalRead(6));
  }
  if (butt_r.isDouble()) light = 0;
}
void stop_1() {
  digitalWrite (8, 1);
  digitalWrite (6, 1);
  digitalWrite (5, 0);
  digitalWrite (7, 1);
  digitalWrite (A0, 1);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);
  if (butt_c.isTriple()) light = 0;
  }
void stop_2() {
  digitalWrite (5, 0);
  digitalWrite (7, 0);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);  
  if (blinc.isReady()) {
    digitalWrite (8, !digitalRead(8));
    digitalWrite (6, !digitalRead(6));
    digitalWrite (A0, !digitalRead(A0));
  }
  if (butt_c.isTriple()) light = 0;
}

// функции экрана
void def() {
  lcd.setCursor(2, 1);
  lcd.print(time.gettime("H:i:s D"));
}
void date() {
  lcd.setCursor(3, 0);
  lcd.print(time.gettime("d-m-Y"));
  lcd.setCursor(2, 1);
  lcd.print(time.gettime("H:i:s D"));
}
void max_s() {
  lcd.setCursor(3, 0);
  lcd.print("MAX SPEED");
}
void max_d() {
  lcd.setCursor(3, 0);
  lcd.print("MAX DIST");
}
void alrm() {
  lcd.setCursor(3, 0);
  lcd.print("ALARM");
  lcd.setCursor(2, 1);
  lcd.print(alarm);
  if (butt_c.isClick()) alarm = !alarm;
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Да хрен его знает, что там в библиотеке гайвера накручено.

Darrel
Offline
Зарегистрирован: 17.08.2019

но с той же библиотекой переменная (light), отвечающая за габаритку, работает нормально

b707
Offline
Зарегистрирован: 26.05.2017

Darrel пишет:

но с той же библиотекой переменная (light), отвечающая за габаритку, работает нормально


Darrel , даже не надейтесь, копаться в коде Гайвера тут считается за западло,

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

при зажатии клавиши переменная режима (mode) скачет туда-сюда

Типа нажал и держишь и она срабатывает то нажата, то не нажата. Такое поведение?

Darrel
Offline
Зарегистрирован: 17.08.2019

b707 пишет:
Darrel пишет:

но с той же библиотекой переменная (light), отвечающая за габаритку, работает нормально

Darrel , даже не надейтесь, копаться в коде Гайвера тут считается за западло,

Мне кажется, что проблемя все-таки у меня в коде. какая-то глупая ошибка новичка.

Darrel
Offline
Зарегистрирован: 17.08.2019

BOOM пишет:

при зажатии клавиши переменная режима (mode) скачет туда-сюда

Типа нажал и держишь и она срабатывает то нажата, то не нажата. Такое поведение?

нет, при удерживании переменная менятся 0-1, а когда отпускаю, остается в последнем значении

nik182
Offline
Зарегистрирован: 04.05.2015

А как должна? 

Darrel
Offline
Зарегистрирован: 17.08.2019

nik182 пишет:

А как должна? 

Поменятся один раз.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Darrel пишет:

BOOM пишет:

при зажатии клавиши переменная режима (mode) скачет туда-сюда

Типа нажал и держишь и она срабатывает то нажата, то не нажата. Такое поведение?

нет, при удерживании переменная менятся 0-1, а когда отпускаю, остается в последнем значении

Я о том и говорю. Это хреновая реализация программного подавления дребезга контактов в библиотеке. 

nik182
Offline
Зарегистрирован: 04.05.2015

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

Darrel
Offline
Зарегистрирован: 17.08.2019

BOOM пишет:

Darrel пишет:

BOOM пишет:

при зажатии клавиши переменная режима (mode) скачет туда-сюда

Типа нажал и держишь и она срабатывает то нажата, то не нажата. Такое поведение?

нет, при удерживании переменная менятся 0-1, а когда отпускаю, остается в последнем значении

Я о том и говорю. Это хреновая реализация программного подавления дребезга контактов в библиотеке. 

Но ведь все остальное работает как часы!

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Darrel пишет:

Но ведь все остальное работает как часы!

Меньше надо бузову слушать. 

Darrel
Offline
Зарегистрирован: 17.08.2019

nik182 пишет:

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

Я новичек, очень громоздкий код. На три кнопки, на каждой минимум два варианта нажатия, на одной четыре.

Darrel
Offline
Зарегистрирован: 17.08.2019

BOOM пишет:

Darrel пишет:

Но ведь все остальное работает как часы!

Меньше надо бузову слушать. 

БГ и Аквариум, это все что я могу себе позволить)

Darrel
Offline
Зарегистрирован: 17.08.2019

nik182 пишет:

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

Чисто ради научного интереса, привесил на одну кнопку "титановый велосипед"

Все так же дохлый штиль и дохлая чайка на дохлом горизонте.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Хоть бы код приводили что и как делается....

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Darrel пишет:

какая-то глупая ошибка новичка.

Так и есть. Ошибка новичка проявилась в выборе библиотеки.

Darrel пишет:

Я новичек, очень громоздкий код. 

А кто ж его такой написал? Пиши короче и компактнее.

Darrel пишет:

Но ведь все остальное работает как часы!

Ну, раз так, то тебе остётся только одно - https://community.alexgyver.ru 

Только там тебе могут помочь.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Кстати, ТС запостил это же на ардуино.юа, и получил ответ

Цитата:

Гайвер?!

В сад! Все в сад!

https://www.youtube.com/watch?v=ix1YNPgWjKk

Парень, не сомневайся, тоже самое тебе скажут и на амперке. Единственное место, где тебе могут помочь - это https://community.alexgyver.ru

nik182
Offline
Зарегистрирован: 04.05.2015

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

Darrel
Offline
Зарегистрирован: 17.08.2019

BOOM пишет:

Хоть бы код приводили что и как делается....


#include <GyverTimer.h>
GTimer_ms blinc;
GTimer_ms stopl;

#include <iarduino_RTC.h>
iarduino_RTC time(RTC_DS1302, 3, 9, 4);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// класс титановый велосипед для тактовой кнопки.
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.

class BUTTON {
public:
//================================================================
static const byte bounce_              =   50; // длительность отслеживания дребезга.
static const byte doubleclick_         =  200; // длительность отслеживания двойного клика.
static const unsigned long timer_      = 5000; // длительность отслеживания неактивности.
static const unsigned int retention_   = 2000; // длительность отслеживания нажатия и удержания.
//================================================================
boolean click_down;
boolean click_up;
boolean doubleclick;
boolean timer;
boolean retention;
//=================================
unsigned long m;
boolean  p;
boolean  b;
boolean dc;
byte     c;
boolean  t;
boolean  r;
//=================================
byte _pb;
//=================================
BUTTON(byte pb) {
_pb = pb;
pinMode(_pb, INPUT_PULLUP);
digitalWrite(_pb, 1);
//====
click_down      = 0;
click_up        = 0;
doubleclick     = 0;
timer           = 0;
retention       = 0;
//====
m  =      millis();
p  = digitalRead(_pb);
b  =                0;
dc =                0;
c  =                0;
t  =                0;
r  =                0;
//====
}

void read() {
//=======================================================
unsigned long nm =      millis();
boolean       np = digitalRead(_pb);
//=================
boolean nb  = 0;
boolean ndc = 0;
boolean nt  = 0;
boolean nr  = 0;
//================
click_down  = 0;
click_up    = 0;
doubleclick = 0;
timer       = 0;
retention   = 0;
//=================
if (np != p) {p = np; m = nm; }
//=======================================================
if (nm - m > bounce_) {nb = 1;}
if (nm - m > doubleclick_) {ndc = 1;}
if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}
if (nb != b) {b = nb;
if (p == 0 && b == 0) {click_down = 1;
++c;      if (c == 2) {c = 0; doubleclick = 1;}
}
if (p == 1 && b == 1) {click_up = 1;}
}
//=======================================================
if (nm - m > timer_) {nt = 1;}
if (nt != t) {t = nt;
if (p == 1 && t == 1) {timer = 1;}
}
//=======================================================
if (nm - m > retention_) {nr = 1;}
if (nr != r) {r = nr;
if (p == 0 && r == 1) {retention = 1;}
}
//=======================================================
}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BUTTON butt_r(10);
BUTTON butt_l(11);
BUTTON butt_c(12);
BUTTON butt_s(A2);

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

#include <EEPROM.h>

unsigned long lastturn, time_press; //переменные хранения времени
float SPEED; //переменная хранения скорости в виде десятичной дроби
float DIST; //переменная хранения расстояния в виде десятичной дроби
float w_length = 2.060; //длина окружности колеса в метрах
byte light = 0; //режим работы габаритов
int screen = 0; //режим работы дисплея
bool mode = 0; //режим работы кнопок
bool alarm = 0; // сигнализация

void setup() {
  // настройки пинов
  pinMode(5, OUTPUT); //свет середина
  pinMode(6, OUTPUT); //свет право
  pinMode(7, OUTPUT); //свет центр
  pinMode(8, OUTPUT); //свет лево
  pinMode(13, OUTPUT); //свет лево контрол
  pinMode(A0, OUTPUT); //свет центр контрол
  pinMode(A1, OUTPUT); //свет право контрол
  pinMode(A3, OUTPUT); //зуммер

  time.begin();
  lcd.init();
  lcd.init();
  lcd.backlight();
  blinc.setInterval(777);
  stopl.setInterval(7777);

  Serial.begin(9600);  //открыть порт

  attachInterrupt(0, sens, RISING); //подключить прерывание на 2 пин при повышении сигнала

  //--------------
  DIST = (float)EEPROM.read(0) / 10.0; //вспоминаем пройденное расстояние при запуске системы 
}

void sens() {
  if (millis() - lastturn > 80) { //защита от случайных измерений 
    SPEED = w_length / ((float)(millis() - lastturn) / 1000) * 3.6; //расчет скорости, км/ч
    lastturn = millis(); //запомнить время последнего оборота
    DIST = DIST + w_length / 1000; //прибавляем длину колеса к дистанции при каждом обороте оного
  }
}

void loop() {
  // отработка кнопок
 Serial.print(screen); 
 Serial.println(mode);
  if (butt_l.click_down && mode == 0) {light = 1;}
  if (butt_l.click_down && mode == 1) {screen--;}
  if (butt_r.click_down && mode == 0) {light = 2;}
  if (butt_r.click_down && mode == 1) {screen++;}
  if (butt_c.click_down && mode == 0) {light = 3;}
  if (butt_c.doubleclick && mode == 0) {light = 4;}
  if (butt_c.retention) {mode = !mode;}
  if (butt_s.click_down) {light = 5;}
  if (butt_s.click_up) {light = 0;}

  // отработка габаритов
  switch (light) {
    case 0: off();
      break;
    case 1: left();
      break;
    case 2: right();
      break;
    case 3: stop_1();
      break;
    case 4: stop_2();
      break;
  }

  // отработка экрана
  switch (screen) {
    case 0: def();
      break;
    case 1: date();
      break;
    case 2: max_s();
      break;
    case 3: max_d();
      break;
    case 4: alrm();
      break;
  }
}

// функции габаритов
void off() {
  digitalWrite (5, 0);
  digitalWrite (6, 0);
  digitalWrite (7, 0);
  digitalWrite (8, 0);
  digitalWrite (A0, 0);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);
}
void left() {
  digitalWrite (8, 1);
  digitalWrite (7, 1);
  digitalWrite (13, 1);
  digitalWrite (5, 0);
  digitalWrite (6, 0);
  digitalWrite (A0, 0);
  digitalWrite (A1, 0);
  if (blinc.isReady()) {
    digitalWrite (8, !digitalRead(8));
  }
  if (butt_l.doubleclick) light = 0;
}
void right() {
  digitalWrite (6, 1);
  digitalWrite (7, 1);
  digitalWrite (A1, 1);
  digitalWrite (5, 0);;
  digitalWrite (8, 0);
  digitalWrite (A0, 0);
  digitalWrite (13, 0);
  if (blinc.isReady()) {
    digitalWrite (6, !digitalRead(6));
  }
  if (butt_r.doubleclick) light = 0;
}
void stop_1() {
  digitalWrite (8, 1);
  digitalWrite (6, 1);
  digitalWrite (5, 0);
  digitalWrite (7, 1);
  digitalWrite (A0, 1);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);
  if (butt_c.timer) light = 0;
  }
void stop_2() {
  digitalWrite (5, 0);
  digitalWrite (7, 0);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);  
  if (blinc.isReady()) {
    digitalWrite (8, !digitalRead(8));
    digitalWrite (6, !digitalRead(6));
    digitalWrite (A0, !digitalRead(A0));
  }
  if (butt_c.timer) light = 0;
}

// функции экрана
void def() {
  lcd.setCursor(2, 1);
  lcd.print(time.gettime("H:i:s D"));
}
void date() {
  lcd.setCursor(3, 0);
  lcd.print(time.gettime("d-m-Y"));
  lcd.setCursor(2, 1);
  lcd.print(time.gettime("H:i:s D"));
}
void max_s() {
  lcd.setCursor(3, 0);
  lcd.print("MAX SPEED");
}
void max_d() {
  lcd.setCursor(3, 0);
  lcd.print("MAX DIST");
}
void alrm() {
  lcd.setCursor(3, 0);
  lcd.print("ALARM");
  lcd.setCursor(2, 1);
  lcd.print(alarm);
  if (butt_c.click_down) alarm = !alarm;
}

может я что-то упускаю, но теперь вообще перестали работать все кнопки.

Darrel
Offline
Зарегистрирован: 17.08.2019

Я уже убрал библиотеку Гайвера.

nik182
Offline
Зарегистрирован: 04.05.2015

button.read надо в вначало loop вставить для каждой кнопки. И если screen вдруг станет больше 4 что будет? 

Darrel
Offline
Зарегистрирован: 17.08.2019

Все работает, спасибо большое всем за помощь.

Еще два вопроса:

- Как реализовать тройное нажатие кнопки?

- Как сделать чтобы кнопка реагиравала конкретно на клик (нажал-отпустил) и на холд раздельно?

#include <GyverTimer.h>
GTimer_ms blinc;
GTimer_ms stopl;

#include <iarduino_RTC.h>
iarduino_RTC time(RTC_DS1302, 3, 9, 4);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// класс титановый велосипед для тактовой кнопки.
// фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.

class BUTTON {
public:
//================================================================
static const byte bounce_              =   50; // длительность отслеживания дребезга.
static const byte doubleclick_         =  200; // длительность отслеживания двойного клика.
static const unsigned long timer_      = 5000; // длительность отслеживания неактивности.
static const unsigned int retention_   = 2000; // длительность отслеживания нажатия и удержания.
//================================================================
boolean click_down;
boolean click_up;
boolean doubleclick;
boolean timer;
boolean retention;
//=================================
unsigned long m;
boolean  p;
boolean  b;
boolean dc;
byte     c;
boolean  t;
boolean  r;
//=================================
byte _pb;
//=================================
BUTTON(byte pb) {
_pb = pb;
pinMode(_pb, INPUT_PULLUP);
digitalWrite(_pb, 1);
//====
click_down      = 0;
click_up        = 0;
doubleclick     = 0;
timer           = 0;
retention       = 0;
//====
m  =      millis();
p  = digitalRead(_pb);
b  =                0;
dc =                0;
c  =                0;
t  =                0;
r  =                0;
//====
}

void read() {
//=======================================================
unsigned long nm =      millis();
boolean       np = digitalRead(_pb);
//=================
boolean nb  = 0;
boolean ndc = 0;
boolean nt  = 0;
boolean nr  = 0;
//================
click_down  = 0;
click_up    = 0;
doubleclick = 0;
timer       = 0;
retention   = 0;
//=================
if (np != p) {p = np; m = nm; }
//=======================================================
if (nm - m > bounce_) {nb = 1;}
if (nm - m > doubleclick_) {ndc = 1;}
if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}}
if (nb != b) {b = nb;
if (p == 0 && b == 0) {click_down = 1;
++c;      if (c == 2) {c = 0; doubleclick = 1;}
}
if (p == 1 && b == 1) {click_up = 1;}
}
//=======================================================
if (nm - m > timer_) {nt = 1;}
if (nt != t) {t = nt;
if (p == 1 && t == 1) {timer = 1;}
}
//=======================================================
if (nm - m > retention_) {nr = 1;}
if (nr != r) {r = nr;
if (p == 0 && r == 1) {retention = 1;}
}
//=======================================================
}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BUTTON butt_r(10);
BUTTON butt_l(11);
BUTTON butt_c(12);
BUTTON butt_s(A2);

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

#include <EEPROM.h>

unsigned long lastturn, time_press; //переменные хранения времени
float SPEED; //переменная хранения скорости в виде десятичной дроби
float DIST; //переменная хранения расстояния в виде десятичной дроби
float w_length = 2.060; //длина окружности колеса в метрах
byte light = 0; //режим работы габаритов
int screen = 0; //режим работы дисплея
bool mode = 0; //режим работы кнопок
bool alarm = 0; // сигнализация

void setup() {
  // настройки пинов
  pinMode(5, OUTPUT); //свет середина
  pinMode(6, OUTPUT); //свет право
  pinMode(7, OUTPUT); //свет центр
  pinMode(8, OUTPUT); //свет лево
  pinMode(13, OUTPUT); //свет лево контрол
  pinMode(A0, OUTPUT); //свет центр контрол
  pinMode(A1, OUTPUT); //свет право контрол
  pinMode(A3, OUTPUT); //зуммер

  time.begin();
  lcd.init();
  lcd.init();
  lcd.backlight();
  blinc.setInterval(777);
  stopl.setInterval(7777);

  Serial.begin(9600);  //открыть порт

  attachInterrupt(0, sens, RISING); //подключить прерывание на 2 пин при повышении сигнала

  //--------------
  DIST = (float)EEPROM.read(0) / 10.0; //вспоминаем пройденное расстояние при запуске системы 
}

void sens() {
  if (millis() - lastturn > 80) { //защита от случайных измерений 
    SPEED = w_length / ((float)(millis() - lastturn) / 1000) * 3.6; //расчет скорости, км/ч
    lastturn = millis(); //запомнить время последнего оборота
    DIST = DIST + w_length / 1000; //прибавляем длину колеса к дистанции при каждом обороте оного
  }
}

void loop() {
  // отработка кнопок
  butt_r.read();
  butt_l.read();
  butt_c.read();
  butt_s.read();
 Serial.print(screen); 
 Serial.println(mode);
  if (butt_l.click_down && mode == 0) {light = 1;}
  if (butt_l.click_down && mode == 1) {screen--;}
  if (butt_r.click_down && mode == 0) {light = 2;}
  if (butt_r.click_down && mode == 1) {screen++;}
  if (butt_c.click_down && mode == 0) {light = 3;}
  if (butt_c.doubleclick && mode == 0) {light = 4;}
  if (butt_c.retention) {mode = !mode;}
  if (butt_s.click_down) {light = 5;}
  if (butt_s.click_up) {light = 0;}

  // отработка габаритов
  switch (light) {
    case 0: off();
      break;
    case 1: left();
      break;
    case 2: right();
      break;
    case 3: stop_1();
      break;
    case 4: stop_2();
      break;
  }

  // отработка экрана
  switch (screen) {
    case 0: def();
      break;
    case 1: date();
      break;
    case 2: max_s();
      break;
    case 3: max_d();
      break;
    case 4: alrm();
      break;
  }
}

// функции габаритов
void off() {
  digitalWrite (5, 0);
  digitalWrite (6, 0);
  digitalWrite (7, 0);
  digitalWrite (8, 0);
  digitalWrite (A0, 0);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);
}
void left() {
  digitalWrite (8, 1);
  digitalWrite (7, 1);
  digitalWrite (13, 1);
  digitalWrite (5, 0);
  digitalWrite (6, 0);
  digitalWrite (A0, 0);
  digitalWrite (A1, 0);
  if (blinc.isReady()) {
    digitalWrite (8, !digitalRead(8));
  }
  if (butt_l.doubleclick) light = 0;
}
void right() {
  digitalWrite (6, 1);
  digitalWrite (7, 1);
  digitalWrite (A1, 1);
  digitalWrite (5, 0);;
  digitalWrite (8, 0);
  digitalWrite (A0, 0);
  digitalWrite (13, 0);
  if (blinc.isReady()) {
    digitalWrite (6, !digitalRead(6));
  }
  if (butt_r.doubleclick) light = 0;
}
void stop_1() {
  digitalWrite (8, 1);
  digitalWrite (6, 1);
  digitalWrite (5, 0);
  digitalWrite (7, 1);
  digitalWrite (A0, 1);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);
  if (butt_c.timer) light = 0;
  }
void stop_2() {
  digitalWrite (5, 0);
  digitalWrite (7, 0);
  digitalWrite (A1, 0);
  digitalWrite (13, 0);  
  if (blinc.isReady()) {
    digitalWrite (8, !digitalRead(8));
    digitalWrite (6, !digitalRead(6));
    digitalWrite (A0, !digitalRead(A0));
  }
  if (butt_c.timer) light = 0;
}

// функции экрана
void def() {
  lcd.setCursor(2, 1);
  lcd.print(time.gettime("H:i:s D"));
}
void date() {
  lcd.setCursor(3, 0);
  lcd.print(time.gettime("d-m-Y"));
  lcd.setCursor(2, 1);
  lcd.print(time.gettime("H:i:s D"));
}
void max_s() {
  lcd.setCursor(3, 0);
  lcd.print("MAX SPEED");
}
void max_d() {
  lcd.setCursor(3, 0);
  lcd.print("MAX DIST");
}
void alrm() {
  lcd.setCursor(3, 0);
  lcd.print("ALARM");
  lcd.setCursor(2, 1);
  lcd.print(alarm);
  if (butt_c.click_down) alarm = !alarm;
}

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

А в соседнем форуме ТС написал

Цитата:
Спасибо, вопрос решен заменой библиотеки.

Т.е. таки выбросил гивера-то :)

Darrel
Offline
Зарегистрирован: 17.08.2019

Ворота пишет:

А в соседнем форуме ТС написал

Цитата:
Спасибо, вопрос решен заменой библиотеки.

Т.е. таки выбросил гивера-то :)

Я умею признавать свои ошибки)

Может будут еще советы по оптимизации кода?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Darrel пишет:

Я умею признавать свои ошибки)

Возможно, но каким-то своим, особым образом.

Ибо в посте #21 читаем

Darrel пишет:

Я уже убрал библиотеку Гайвера.

А через 17 минут в посте #23 вдруг видим

Darrel пишет:

#include <GyverTimer.h>
...

Наступает когнитивный диссонанс :(

Darrel пишет:

Может будут еще советы по оптимизации кода?

Да, пожалуй, нет :(

Darrel
Offline
Зарегистрирован: 17.08.2019

Я убрал <GyverButton.h>,которая отвечала за кнопки.

Сейчас избавляюсь от <GyverTimer.h>

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ТС, держи обработчик кнопок. Конструктор+функции+пример использования

Целых 255 вариантов нажатия.

Реализовывал кодовый замок на одной кнопке с этой библиотекой

 

class multiKey//создадим класс кнопок
{public://общие функции и переменные
    //конструктор класса
    multiKey(byte pin,byte state,byte val);   
    byte read();//функция обработчика нажатий
private://личные переменные и функции класса
    //локальные переменные обьекта номер пина/тип сигнала/количество кликов
 byte _pin,_state,_val;
 uint32_t start_press;//переменная времени нажатия кнопки
 uint32_t pressTime;//переменная длительности нажатия кнопки
 uint32_t double_press;//переменная времени между нажатиями
 boolean pressFlag;//переменная флага нажатия
 byte press_one;//переменная количества нажатий
//переменные состояния/временного состояния/нажатия кнопки
 byte num,_num,button; 
};

//Функция чтения кнопки
byte multiKey::read(){ 
!_state?button=digitalRead(_pin):button=!digitalRead(_pin);//в зависимости от того, что в конструкторе настраиваем кнопку
	if(!button){num=0;}//если кнопка отпущена, выдаем результат 0
	if(button&&!pressFlag)//если кнопка нажата и флаг опущен
	{pressTime=millis()-start_press;//считаем время нажатия кнопки
		if(pressTime>=1500){//если длительность нажатия больше 1,5 сек
			pressFlag=1;//поднимаем флаг
num=255;//значение кнопки long
pressTime=0;//сбрасываем длительность нажатия
		}		}
	if(!button){//если кнопка отпущена
 start_press=millis();//сбрасываем время нажатия
pressFlag=0;//опускаем флаг
}

	if(!button&&!pressFlag){//если кнопка и флаг отпущены
		if(pressTime>50&&pressTime<1500)//а время нажатия больше 50мс, но меньше 1,5сек
		{press_one++;//увеличиваем счетчик количества нажатий
 if(press_one>_val)press_one=_val;//ограничиваем значение счетчика
 pressTime=0;//сбрасываем длительность нажатия
 double_press=millis();//запускаем таймер ожидания следующего нажатия
    }}
if(press_one){//если было короткое нажатие
if(millis()-double_press>=300){//ждем 0,3сек
pressTime=0;//сбрасываем длительность нажатия
num=press_one;//значение кнопки приравниваем к количеству нажатий
press_one=0;//сбрасываем количество нажатий
  }}
_num=num;//для одиночного вывода результата, используем временную переменную
num=0;//обнудяем основную переменную значения кнопки
	return _num;//возвращаем значение кнопки
}
//функция конструктора класса
/*в конструкторе указываем:
номер пина
тип сигнала (лог0/лог1)
максимальное количество отслеживаемых кликов*/
multiKey::multiKey(byte pin,byte state,byte val)
{_pin = pin;//передаем внутренней переменной номер пина
//!state?_state=2:_state=0;//в зависимости от выбранного типа сигнала меняем значение переменной
_state=state;
_val=val;//передаем внутренней переменной количество кликов
 pinMode(pin,_state);//конфигурируем пин согласно типа сигнала
 }
 
 boolean led1,led2;
  multiKey myBtn(9,0,2);//вот так создаём кнопку(пин,отслеживаемый уровень,максимальное количество кликов)
  
 void setup(){
 pinMode(11,1);
 pinMode(13,1);
 }
 void loop(){
byte btn_state=myBtn.read();//а вот так читаем кнопку
switch(btn_state){
case 0:break;
case 1: led1=!led1;digitalWrite(11,led1);break;
case 2: led2=!led2;digitalWrite(13,led2);break;
}
 }

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Немного привел код в удобочитаемый вид (для меня).

class multiKey {                              // создадим класс кнопок
  public:                                     // общие функции и переменные
    multiKey(byte pin, byte state, byte val); // конструктор класса
    byte read();                              // функция обработчика нажатий
private:                                      // личные переменные и функции класса

    byte _pin, _state, _val;                  // локальные переменные обьекта номер пина/тип сигнала/количество кликов
    uint32_t start_press;                     // переменная времени нажатия кнопки
    uint32_t pressTime;                       // переменная длительности нажатия кнопки
    uint32_t double_press;                    // переменная времени между нажатиями
    boolean pressFlag;                        // переменная флага нажатия
    byte press_one;                           // переменная количества нажатий
    byte num, _num,button;                    // переменные состояния/временного состояния/нажатия кнопки
};

//Функция чтения кнопки
byte multiKey::read(){ 
  !_state?button = digitalRead(_pin):button = !digitalRead(_pin); // в зависимости от того, что в конструкторе настраиваем кнопку
  if(!button) {                                                   // если кнопка отпущена
    num = 0;                                                      // выдаем результат 0
  }
  if(button && !pressFlag) {                                      // если кнопка нажата и флаг опущен
    pressTime = millis() - start_press;                           // считаем время нажатия кнопки
    if(pressTime >= 1500) {                                       // если длительность нажатия больше 1,5 сек
      pressFlag = 1;                                              // поднимаем флаг
      num = 255;                                                  // значение кнопки long
      pressTime = 0;                                              // сбрасываем длительность нажатия
    }   
  }
  if(!button){                                                    // если кнопка отпущена
    start_press = millis();                                       // сбрасываем время нажатия
    pressFlag = 0;                                                // опускаем флаг
  }

  if(!button && !pressFlag) {                                     // если кнопка и флаг отпущены
    if(pressTime > 50 && pressTime < 1500) {                      // а время нажатия больше 50мс, но меньше 1,5сек
      press_one++;                                                // увеличиваем счетчик количества нажатий
      if(press_one > _val) {
        press_one = _val;                                         // ограничиваем значение счетчика
      }
      pressTime = 0;                                              // сбрасываем длительность нажатия
      double_press = millis();                                    // запускаем таймер ожидания следующего нажатия
    }
  }
  if(press_one){                                                  // если было короткое нажатие
    if (millis() - double_press >= 300) {                         // ждем 0,3сек
      pressTime = 0;                                              // сбрасываем длительность нажатия
      num = press_one;                                            // значение кнопки приравниваем к количеству нажатий
      press_one = 0;                                              // сбрасываем количество нажатий
    }
  }
  _num = num;                                                     // для одиночного вывода результата, используем временную переменную
  num = 0;                                                        // обнуляем основную переменную значения кнопки
  return _num;                                                    // возвращаем значение кнопки
}

//функция конструктора класса
/*  в конструкторе указываем:
      1. номер пина
      2. тип сигнала (лог0/лог1)
      3. максимальное количество отслеживаемых кликов
 */

multiKey::multiKey(byte pin,byte state,byte val) {
  _pin = pin;                                                     // передаем внутренней переменной номер пина
  //!state?_state=2:_state=0;                                     // в зависимости от выбранного типа сигнала меняем значение переменной
  _state = state;
  _val = val;                                                     // передаем внутренней переменной количество кликов
  pinMode(pin,_state);                                            // конфигурируем пин согласно типа сигнала
}
//================================ 
/*  Описание класса окончено.
    Далее идет пример использования.
 */

boolean led1, led2;                                               /* Как я понял - флаги управления светодиодами. Одно нажатие - меняем состояние первого светодиода,
                                                                     если же произошло двойное нажатие - меняем состояние второго светодиода. */
multiKey myBtn(9, 0, 2);                                          // вот так создаём кнопку("пин", "отслеживаемый уровень", "максимальное количество кликов")
  
void setup(){

  pinMode(11,1);
  pinMode(13,1);
}

void loop(){

  byte btn_state = myBtn.read();                                  // а вот так читаем кнопку
  switch (btn_state) {
    case 0: break;                                                // Если кнопка НЕ нажата - ничего не делаем (???)
    case 1: led1 = !led1;                                         // Если нажали один раз - меняем состояние первого диода
            digitalWrite(11, led1);
            break;
    case 2: led2 = !led2;                                         // Если было двойное нажатие - меняем состояние второго диода
            digitalWrite(13,led2);
            break;
  }
}

Вопрос возник - в строке 30 дублирование условия строки 19, их может объеденить? Или в этом имеется какой-то "тайный смысл"? :-)

Еще строку 18 конвертните в длинную запись из короткой, не могу сообразить что там происходит...

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Да , безусловно строки 19 и 30 можно написать как одну. Но все дело в том, что как таковая функция у меня уже давно удалена и все оформлено в виде библиотеки. То что тут представлено скомпоновано из разных файлов и проверено только на правильность компиляции.

А в строке 30 идёт тренарная операция по проверке состояния кнопки. Если в конструкторе указано , что при срабатывании сигнал кнопки лог1 то одно переменная принимает одно значение, если лог0 то противоположное. Это позволяет сконфигурировать кнопки при их обьявлении на разные рабочие уровни сигналов, не меняя остальной код.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Вот собственно ссылка на саму библиотеку с примером и ка выглядит код при использовании библиотекиhttps://drive.google.com/file/d/10V0SJX-UkJGBIcpP3zpRdZxZ3CFHlkLe/view?usp=drivesdk

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Наверное речь про 18 строку, а не 30ю.

Ещё вопрос - значение 255 означает долгое нажатие, как я понимаю? Или я не прав? Как длинное нажатие обозначается?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Да, долгое нажатие 255

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Понятно. Данная библиотека будет работать с триггером Шмитта? (SN74HC14N)

Kakmyc
Offline
Зарегистрирован: 15.01.2018

А при чем тут библиотека ?

Для пояснения:
Библиотека обрабатывает нажатия по принципу, одно нажатие одно событие. Т.е. если у нас просто короткое нажатие, то оно так и отрабатывает, если длинное, то после проверки времени функция возвращает результат, сбрасывает флаги и ждёт, когда отпустят кнопку, возвращает при этом результат false. При мультикликах считает время после последнего клика и возвращает количество нажатий в тот момент, когда проходит время отведенное на задержку между кликами.

Как использовать совместно с триггером Шмитта, это уже вопрос реализации самого триггера и схемы его подключения

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Собственно вопрос про триггер в том, что SN74HC14N - инвертирующий триггер. То есть низкий уровень на входе дает высокий уровень на выходе. Вот я о чем.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Ну вроде есть же в конструкторе объекта выбор логического уровня, для отслеживания сигнала

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А вот теперь все сложилось в одну единую цепочку! Большое спасибо. 

Morroc
Offline
Зарегистрирован: 24.10.2016

К чему вам этот триггер или у вас не кнопка, а что то другое ?