ARDUINO Почему код работает неправильно

Fompi

✩✩✩✩✩✩✩
7 Июл 2022
17
0
Всем здравствуйте, делал автономное устройство. В котором есть датчики, энкодер, работает все на батарейках, и в дело пошла библиотека Gyverpower,. Но я столкнулся с проблемой, после сна энкодер (или ардуино), тупят и на пин Arduino идет постоянно low-сигнал (будто бы кнопка зажата). Скрипт довольно большой, но я вырезал все что не касается проблемы и выделил ключевые моменты:
P.S. заметил, что если выходить из функции (return, и заного заходить (сбрасывать весь код, то проблема остается)

Инициализация:
//-------ПИНЫ---------
#define S1 10
#define S2 4
#define KEY 2
//-------ПИНЫ---------

//-------БИБЛИОТЕКИ---------
#include <EncButton2.h>
//-------БИБЛИОТЕКИ---------

EncButton2<EB_ENCBTN> enc(INPUT_PULLUP, S1, S2, KEY);

void setup() {
  Serial.begin(9600);
  power.hardwareEnable(PWR_ALL);
  power.calibrate(8000);
  power.correctMillis(true);
  // power.autoCalibrate();
  newTimer(Timer1);
  pinMode(SEN_VCC, OUTPUT);
  digitalWrite(SEN_VCC, 1);
  randomSeed(analogRead(0));
}

void loop() {
    // в ней нет ничего такого, что касалось бы текущей проблемы
}
Сам процесс:
#define powerOff() \
  lcd.noBacklight(); \
  lcd.noDisplay(); \
  digitalWrite(SEN_VCC, 0); \
  bitSet(powerFlags, powerSave)

#define powerOn() \
  lcd.display(); \
  lcd.backlight(); \
  digitalWrite(SEN_VCC, 1); \
  bitClear(powerFlags, powerSave)

#define DisablePins() \
  detachInterrupt(1)

#define EnablePins() \
  attachInterrupt(1, btnTick, FALLING)

#define powerSave 0
#define disControl 1
#define powerFlag1 2
#define powerFlag2 3
#define powerFlag3 4
#define OptiFlag 5

#define Tupdate(x) x=millis()
#define check(x, y) if(millis() - x >= y)
#define newTimer(x) uint32_t x = millis()

byte workModePow(byte globMode) {
  lcd.clear();
  newTimer(Timer1);
  newTimer(Timer2);
  newTimer(Timer3);
  newTimer(OptiTimer);
  uint16_t randomTime = random(10, 30);
  byte randomAlert = random(0, randomAlertTime);
  digitalWrite(RED, 0);
  uint16_t RepeatedTimer = 10;
  uint16_t WorkTimer;
  uint8_t PerNow1 = 0;
  uint16_t RtimeL0 = 0;
  uint16_t RtimeL = 0;
  uint16_t FtimeL0 = 0;
  uint16_t FtimeL = 0;
  switch (globMode) {
    case 0:
      if (Timers.Wtime < 0) {
        Timers.Wtime = ReminderOnline;
        RepeatedTimer = RepeatedReminderOnline;
      } else if (Timers.Wtime > 50) RepeatedTimer = Timers.Wtime * 0.2;
      WorkTimer = Timers.Wtime + randomAlert;
      PerNow1 = Timers.Wtime / 100;
      break;
    case 1:
      if (Timers.Rtime < 0) {
        Timers.Rtime = ReminderRelax;
        RepeatedTimer = RepeatedReminderRelax;
      } else if (Timers.Rtime > 50) RepeatedTimer = Timers.Rtime * 0.2;
      WorkTimer = Timers.Rtime + randomAlert;
      PerNow1 = Timers.Rtime / 100;
      break;
    case 2:
      Timers.STimeEE = 0;
      Timers.STimeEERep = 0;
      if (Timers.Ftime < 0) {
        Timers.Ftime = ReminderOff;
        RepeatedTimer = RepeatedReminderOff;
      } else if (Timers.Ftime > 50) RepeatedTimer = Timers.Ftime * 0.2;
      WorkTimer = Timers.Ftime + randomAlert;
      PerNow1 = Timers.Ftime / 100;
      break;
  }
  static byte hours[3], mins[3], secs[3];
  byte arrowPosition = 0;
  bool missed = false; 
  byte secCounter = 0;
  bool flag = 1;
  int8_t mode = 0;
  uint16_t timeL = 0;
  bool mode_check = 1;
  bool mode_time = 0;
  bool arrow = 0;
  // bool powerSave = 0;
  // bool disControl = 0;
  byte powerFlags = 0;
  bitSet(powerFlags, powerFlag3);
  bitSet(powerFlags, OptiFlag);
  Tupdate(Timer1);
  Tupdate(Timer3);
  while (1) {
    noTone(BUZ);
    byte customChar[8] = { B00000, B00000, B01110, B10101, B10101, B10001, B01110, B00000 };
    switch (globMode) {
      case 0:
        switch (secCounter % 4) {
          case 0:
            customChar[4] = B10101;
            customChar[5] = B10001;
            break;
          case 1:
            customChar[4] = B10111;
            customChar[5] = B10001;
            break;
          case 2:
            customChar[4] = B10101;
            customChar[5] = B10101;
            break;
          case 3:
            customChar[4] = B11101;
            customChar[5] = B10001;
            break;
        }
        break;
      case 1:
        switch ((secCounter % 8) / 2) {
          case 0:
            customChar[4] = B10101;
            customChar[5] = B10001;
            break;
          case 1:
            customChar[4] = B10111;
            customChar[5] = B10001;
            break;
          case 2:
            customChar[4] = B10101;
            customChar[5] = B10101;
            break;
          case 3:
            customChar[4] = B11101;
            customChar[5] = B10001;
            break;
        }
        break;
      case 2:
        switch (secCounter % 2) {
          case 0:
            customChar[3] = B10001;
            customChar[4] = B10101;
            break;
          case 1:
            customChar[3] = B10001;
            customChar[4] = B10001;
            break;
        }
        break;
    }

    if (bitRead(powerFlags, OptiFlag) && !bitRead(powerFlags, powerSave)) {
      bitClear(powerFlags, OptiFlag);
      Tupdate(OptiTimer);
      switch (mode) {
        case 0:
          mode_check = 1;
          switches(globMode, 0, hours[globMode], mins[globMode], secs[globMode], customChar);
          break;
        case 1:
          mode_check = 1;
          switches(globMode, 1, hours[globMode], mins[globMode], secs[globMode], customChar);
          break;
        case 2:
          graphs(0, &mode_check, &mode_time, &arrow, arrowPosition);
          break;
        case 3:
          graphs(1, &mode_check, &mode_time, &arrow, arrowPosition);
          break;
        case 4:
          graphs(2, &mode_check, &mode_time, &arrow, arrowPosition);
          break;
        case 5:
          graphs(3, &mode_check, &mode_time, &arrow, arrowPosition);
          break;
        case 6:
          graphs(4, &mode_check, &mode_time, &arrow, arrowPosition);
          break;
      }
    }
    Serial.print(bitRead(powerFlags, disControl));
    Serial.println(bitRead(powerFlags, powerSave));
    if (!missed) digitalWrite(RED, 0);
    bool flag1 = 1;
    if (bitRead(powerFlags, disControl)) {
      uint16_t howManySleep = millis() - Timer1;
      if (howManySleep < 1000) power.sleepDelay(1000 - howManySleep);        // вот тут ложимся спать менее, чем на секунду
    } else {

      delay(10);            // delay, потому что без него почему-то не успевает обработать сигнал с энкодера библиотека
      if (redbtn.tick() || yellowbtn.tick()) {        // это отдельные кнопки, (без энкодера), они работает нормально
        switch (globMode) {
          case 0:
            if (redbtn.click()) return 13;
            if (yellowbtn.click()) return 12;
            break;
          case 1:
            if (redbtn.click()) return 11;
            if (yellowbtn.click()) return 13;
            break;
          case 2:
            if (redbtn.click()) return 12;
            if (yellowbtn.click()) return 11;
            break;
        }
        if (redbtn.held() && yellowbtn.held()) return 99;
        redbtn.resetState();
        yellowbtn.resetState();
      }
      delay(10);
      if(enc.tick()) {
      Serial.println(enc.tick());        // вот здесь выводит после сна постоянно 7 (step, т.е. кнопка всегда зажата, но это не так), на любые движения энкодером не реагирует. До сна все нормально. Иногда бывает ничего не выводит, т.е. будто бы с энкодером ничего не происходит
      if (!mode_time && enc.right()) {
        autoOff = 0;
        mode++;
        mode = mode % 7;
        mode_check = 1;
      }
      if (!mode_time && enc.left()) {
        autoOff = 0;
        if (mode == 0) mode = 6;
        else
          mode--;
        mode_check = 1;
      }
      if (mode == 1 && enc.click()) {
        autoOff = 0;
        numberDrinks++;
      }
      if (mode == 1 && enc.held()) {
        numberDrinks = 0;
        autoOff = 0;
      }
      if (mode >= 2 && enc.held()) {
        autoOff = 0;
        WTime[EEPcounter] = Timers.WTimeEE;
        RTime[EEPcounter] = Timers.RTimeEE;
        FTime[EEPcounter] = Timers.FTimeEE;
        missedW[EEPcounter] = missedNowW;
        missedF[EEPcounter] = missedNowF;
        Wmore[EEPcounter] = WmoreNow;
        Rmore[EEPcounter] = RmoreNow;
        Fmore[EEPcounter] = FmoreNow;
        drink[EEPcounterDrink] = numberDrinks;
        EEPcounter++;
        EEPcounter = EEPcounter % 4;
        EEPcounterDrink++;
        EEPcounterDrink = EEPcounterDrink % 7;
        EEPROM.put(5, WTime);
        EEPROM.put(13, RTime);
        EEPROM.put(21, FTime);
        EEPROM.put(29, missedW);
        EEPROM.put(33, missedF);
        EEPROM.put(37, Wmore);
        EEPROM.put(45, Rmore);
        EEPROM.put(53, Fmore);
        EEPROM.put(61, drink);
        EEPROM.put(68, EEPcounter);
        EEPROM.put(69, EEPcounterDrink);
        lcd.clear();
        lcd.setCursor(2, 0);
        lcd.print("Data saved!");
        delay(1000);
      }
      if (!mode_time && mode >= 2 && enc.rightH()) {
        autoOff = 0;
        arrowPosition++;
        arrowPosition = arrowPosition % 5;
        mode_check = 1;
      }
      if (!mode_time && mode >= 2 && enc.leftH()) {
        autoOff = 0;
        if (arrowPosition == 0) arrowPosition = 4;
        else
          arrowPosition--;
        mode_check = 1;
      }
      if (!mode_time && mode >= 2 && enc.click()) {
        autoOff = 0;
        mode_time = 1;
        mode_check = 1;
      } else if (mode_time && enc.click()) {
        autoOff = 0;
        mode_time = 0;
        mode_check = 1;
      }
      if (mode_time && mode == 2 && enc.leftH()) {
        autoOff = 0;
        if (arrowPosition != 4) FTime[arrowPosition] = FTime[arrowPosition] - 10;
        else
          Timers.FTimeEE = Timers.FTimeEE - 10;
      }
      if (mode_time && mode == 2 && enc.rightH()) {
        autoOff = 0;
        if (arrowPosition != 4) FTime[arrowPosition] = FTime[arrowPosition] + 10;
        else
          Timers.FTimeEE = Timers.FTimeEE + 10;
      }
      if (mode_time && mode == 3 && enc.leftH()) {
        autoOff = 0;
        if (arrowPosition != 4) {
          if (!arrow) WTime[arrowPosition] = WTime[arrowPosition] - 10;
          else
            RTime[arrowPosition] = RTime[arrowPosition] - 10;
        } else {
          if (!arrow) Timers.WTimeEE = Timers.WTimeEE - 10;
          else
            Timers.RTimeEE = Timers.RTimeEE - 10;
        }
      }
      if (mode_time && mode == 3 && enc.rightH()) {
        autoOff = 0;
        if (arrowPosition != 4) {
          if (!arrow) WTime[arrowPosition] = WTime[arrowPosition] + 10;
          else
            RTime[arrowPosition] = RTime[arrowPosition] + 10;
        } else {
          if (!arrow) Timers.WTimeEE = Timers.WTimeEE + 10;
          else
            Timers.RTimeEE = Timers.RTimeEE + 10;
        }
      }
      if (mode_time && mode == 6 && enc.leftH()) {
        autoOff = 0;
        if (arrowPosition != 7) {
          drink[arrowPosition] = drink[arrowPosition] - 1;
        } else {
          numberDrinks = numberDrinks - 1;
        }
      }
      if (mode_time && mode == 6 && enc.rightH()) {
        autoOff = 0;
        if (arrowPosition != 7) {
          drink[arrowPosition] = drink[arrowPosition] + 1;
        } else {
          numberDrinks = numberDrinks + 1;
        }
      }
      enc.resetState();
    }
    
    }

    if (missed && (millis() - Timer2 >= 1000)) {
      digitalWrite(RED, flag = !flag);
      Tupdate(Timer2);
    }
    check(Timer3, 1000) {
      Timer3 = Timer3 + 1000;
      secs[globMode]++;
      secCounter++;
      autoOff++;
      if (autoOff == 255) autoOff = 120;
      if (secs[globMode] >= 60) {
        secs[globMode] = secs[globMode] % 60;
        mins[globMode]++;
        timeL++;
        switch (globMode) {
          case 0:
            Timers.WTimeEE++;
            Timers.STimeEE++;
            break;
          case 1:
            Timers.RTimeEE++;
            Timers.STimeEE++;
            RtimeL++;
            break;
          case 2:
            Timers.FTimeEE++;
            FtimeL++;
            break;
        }
        if (missed) Timers.STimeEERep++;
        if (missed) WmoreNow++;
      }
      if (mins[globMode] >= 60) {
        mins[globMode] = mins[globMode] % 60;
        hours[globMode]++;
      }
      if (hours[globMode] >= 10) hours[globMode] = 0;
    }
    if(!bitRead(powerFlags, OptiFlag) && millis() - OptiTimer >= 1000) {
      bitSet(powerFlags, OptiFlag);
    }
    if (bitRead(powerFlags, powerFlag1) && autoOff >= 60) {        // здесь происходит условия, когда уже можно выключать мк, если устройство "бездействует"
      bitClear(powerFlags, powerFlag1);
      bitSet(powerFlags, powerFlag3);
      bitSet(powerFlags, disControl);
      EnablePins();
    } else if (bitRead(powerFlags, powerFlag2) && autoOff >= 120) {
      bitClear(powerFlags, powerFlag2);
      bitSet(powerFlags, powerFlag3);
      powerOff();
    } else if (bitRead(powerFlags, powerFlag3) && autoOff < 60) {
      bitSet(powerFlags, powerFlag1);
      bitSet(powerFlags, powerFlag2);
      bitClear(powerFlags, powerFlag3);
      bitClear(powerFlags, disControl);
      DisablePins();
      powerOn();
    }
  }
}

void btnTick(void) {
  if (!digitalRead(REDBUT) || !digitalRead(KEY)) autoOff = 0;        // т.к. мк спит, я подключил прерывание, чтобы будить мк и сбрасывать счетсчик бездействия
}
Меня интересует только проблема с энкодером, остальные недоделки скрипта меня не интересуют, да, я буду благодарен вашим замечаниям, но проект готов, вполне меня устраивает, кроме этого косяка со сном =)