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

17.08.2019
5
0
1
#1
День (вечер-ночь-утро) добрый уважаемое сообщество!
Для начала хотел бы сказать спасибо Александру, за его замечательный канал и за уроки по Ардуино, благодаря которым я увлекся самоделками.

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

Также буду рад любым советам по улучшению кода.

C++:
#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;
}
 
17.08.2019
5
0
1
#3
if (butt_c.isHold()) mode = !mode;
вот тут может быть собака. если кнопка нажата, то она отжата. и так в каждом лупе, но я не эксперт в GyverButton.h, не пробовал ни разу.
Точно! Подскажите, как сделать, чтобы срабатывало один раз?
 
#4
еще раз. может быть у Алекса есть что то встроенное в кнопку, я не знаю.

А обычно это решается флагом. при первой отработке флаг устанавливается в фальш итогда условие будет "если флаг и кнопка нажата то"... "и " но тут надо еще время смотреть, т.е. мало того, что бы условие сработало, надо что бы между сработанными условиями прошло сколько то времени.
Для программы нажатие 2 секунды и 9.1 секунды неотличимы, если ей не сказать об этом.

Подумал, что флаг менять и не надо. достаточно отработать через определенное время удержание. и пусть раз 2 секунды меняется режим.
 
17.08.2019
5
0
1
#5
еще раз. может быть у Алекса есть что то встроенное в кнопку, я не знаю.

А обычно это решается флагом. при первой отработке флаг устанавливается в фальш итогда условие будет "если флаг и кнопка нажата то"... "и " но тут надо еще время смотреть, т.е. мало того, что бы условие сработало, надо что бы между сработанными условиями прошло сколько то времени.
Для программы нажатие 2 секунды и 9.1 секунды неотличимы, если ей не сказать об этом.

Подумал, что флаг менять и не надо. достаточно отработать через определенное время удержание. и пусть раз 2 секунды меняется режим.
ок, один вопрос решен, большое спасибо.
 
17.08.2019
5
0
1
#7
Последнее редактирование:
#8
выведи после каждого изменения screen в монитор ее значение. с пояснением что бы было понятно что сработало

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++;
тут
}
 
17.08.2019
5
0
1
#9
выведи после каждого изменения screen в монитор ее значение. с пояснением что бы было понятно что сработало

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++;
тут
}
не изменяется вообще. поменял библиотеку, все заработало. Спасибо большое за помощь!
Код:
#include <GyverTimer.h>
GTimer_ms blinc;
GTimer_ms stopl;

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

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();
  if (butt_l.click_down && mode == 0) light = 1;
  if (butt_l.click_down && mode == 1) {screen--; lcd.clear();}
  if (butt_r.click_down && mode == 0) light = 2;
  if (butt_r.click_down && mode == 1) {screen++; lcd.clear();}
  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;
  }

  // отработка экрана
  if (screen > 4) screen = 0;
  if (screen < 0) screen = 4;
  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(5, 0);
  lcd.print("ALARM!");
  lcd.setCursor(6, 1);
  lcd.print("<" + String(alarm) + ">");
  if (butt_c.click_down) alarm = !alarm;
}