Сохранение переменной без изменений после первого получения данных

Всем добра! Суть проблемы заключается в переменной в которую я получаю текущее время. Это калькулятор. Но не простой а узкопрофильный. Которые рассчитывает параметры работы звена газодымозащитной службы при тушении пожара. Мне для моего проекта требуется вычислить будущее время, скачем когда текущее время 13:30 я прибавляю ко времени 45 минут, на выходе получаю сумму и вывожу на LED TM1637 полученный результат тоже в часах и минутах.
В проекте использую библиотеки:
<Keypad.h>
<TM1637Display.h>
“RTClib.h”
При удержании клавиши на клавиатуре “С” не менее 2 секунд выполняется код

          if (flag_Sum_dT == true) {
            DateTime now = rtc.now();
            int displaytime = (now.hour() * 100) + now.minute();
            DateTime future(now + TimeSpan(0, 0, dT, 0));  // тут я прибавлю минуты из переменной dT которые рассчитываются по формуле dT = (Pmaxpad * Vbal) / 45;
            String hour_string = String(future.hour()); // тут я получаю значение часов и перевожу в строку
            String minute_string = String(future.minute()); // тут я получаю значение минут и перевожу в строку
            minute_string = hour_string + minute_string; // тут я объединяю строки часов и минут

            //int hour_int = hour_string.toInt(); // пока не использую потому, что нужно разобраться с минутами, да и в принципе пока не требуется. Оставил на будущее может пригодится далее в проекте
            int minute_int = minute_string.toInt(); // тут я снова перевожу все в цифровое значение

            displaytime = minute_int; // тут я передаю переменной значение для дальнейшего вывода на дисплей

            display.showNumberDecEx(displaytime, 0b11100000, true); // тут вывожу на дисплей и включаю разделительные точки, они должны просто гореть.
           
            flag_Sum_dT = false; // тут я блокирую возможность дальнейшего использования  вычислений после первого применения.

Настоящая проблема в том, что я смог только заблокировать возможность дальнейшего использования клавиши “С” целиком после первого же ее использования. Но задача заключается в том, чтобы получить значение текущего времени по первому нажатию на клавишу “С” сохранить значение этой переменной и больше ее не менять на всем протяжении до момента сброса значений клавишей “*”. Если убрать if (flag_Sum_dT == true) { то при удержании клавиши “С”, например через пару минут, время снова рассчитается но уже с обновленными значениями текущего времени и передаст это переменной. Как мне сохранить переменную без изменений после первого получения значения текущего времени и при этом оставить возможность использование клавиши “С” для отображение первого расчетного значения? Думаю решение лежит на поверхности, но я бьюсь уже несколько дней и не могу решить эту проблему.

А зачем его убирать? Ничего не понял. Оно там нужно.

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

Это какой то набор функций и подпрограмм. А код то где?

Вот так его нужно вставлять:


#include <Keypad.h>         // подключение библиотеки клавиатуры
#include <TM1637Display.h>  // подключение библиотеки дисплея ТМ1637
#include "RTClib.h"         // подключение библиотеки часов реального времени

//--------------------------------------------- переменные ---------------------------------------
uint32_t last_time;  // переменная для таймера millis

uint8_t CounterI;  // Переменная для счетчика в фуекции вкл/выкл двоеточия часов
float Vbal;        // переменная для объема воздущного балона
int Pmin;          // переменная для минимального давления воздуха в баллоне газодымозащитника (P мин. включения)
float Pvix;        // переменная для давления выхода (P вых)
float Pmaxpad;     // переменная для расчета максимального падения давления при котором должны возвращаться (P макс.пад)
float dT;          // переменная для расчета дельта Т
float Tob;         // переменная для расчета общего времени работы звена ГДЗС (Т общ.)
bool maxZn = 0;    // переменная для ограничения количества вводимых символов (максимум 3)
//unsigned long startTime;  // переменная для таймера millis
//uint8_t Hh;                  // переменная для часов
//uint8_t Mm;                  // переменная для минут (используется при вычислении текущего времени + Т выхода и Т общего)
bool flag_Sum_dT;  // флаг для блокировки перерасчета времени
int Fixir_Time; // переменная для хранения зафиксированного времени

String inputValue = "";  // Переменная для хранения данных введенных с клавиатуры.
//String inputKey = "";

const byte numRows = 4;  // количество строк
const byte numCols = 4;  // количество колонок

char keymap[numRows][numCols] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};

byte rowPins[numRows] = { 9, 8, 7, 6 };
byte colPins[numCols] = { 5, 4, 3, 2 };

Keypad keypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

RTC_DS3231 rtc;
TM1637Display display(11, 12);   // Определение выводов для дисплея вывода параметров расчетов
TM1637Display displayW(A1, A2);  // Определение выводов для дисплея "Часы"

//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);                    // подключаем сериал порт на скорости 9600 бод.
  display.setBrightness(2);              // яркость дисплея вывода параметров расчетов.
  displayW.setBrightness(2);             // яркость дисплея часов.
  display.clear();                       // очищвем дисплей.
  Vbal = 6.8;                            // присваиваем переменной объем баллона равный 6,8 или 7 литров.
  flag_Sum_dT = true;                    // флаг для ограничения работы if (key == 'C')
  display.showNumberDec(0);              // отобразить "0" на дисплее 1 при запуске
  keypad.addEventListener(keypadEvent);  // Добавить слушателя события.
  keypad.setHoldTime(2000);              // Устанавливает количество миллисекунд, которое пользователь должен удерживать кнопку нажатой, чтобы было вызвано состояние HOLD. По умолчанию 1000 мс.
  keypad.setDebounceTime(50);            // Устанавливает количество миллисекунд, которое клавиатура ждет перед тем, как применить новое нажатие кнопки или событие кнопки. Это «время задержки» в методе обработки дребезга контактов.По умолчанию 50 мс.
                                         //------------------------------------- Часы -------------------------------------------------------
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1)
      ;
  }
  if (rtc.lostPower()) {
    //Serial.println("RTC lost power, lets set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    //rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  displayW.clear();
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
void loop() {
  //char inputKey = kpd.getKeys();
  //------------------------------------ Часы ---------------------------------------------------------
  DateTime now = rtc.now();
  int displaytime = (now.hour() * 100) + now.minute();








  if (CounterI == 0) {
    CounterI += 1;
    displayW.showNumberDecEx(displaytime, 0b11100000, true);
  }

  if (CounterI == 2) {
    CounterI += 1;
    displayW.showNumberDec(displaytime, true);
  }

  if (millis() - last_time >= 1000) {
    CounterI += 1;
    last_time = millis();
  }

  if (CounterI >= 4) {
    CounterI = 0;
  }


  //------------------------------------------- калькулятор ----------------------------------------------------

  char key = keypad.getKey();
  if (key) {
    Serial.println(key);
  }
}

// обработать события:
void keypadEvent(KeypadEvent key) {
  switch (keypad.getState()) {
    case PRESSED:
      if (key) {

        if (maxZn < 3) {
          if (key >= '0' && key <= '9') {
            inputValue += key;                              // Добавляем цифру к текущему вводу
            Serial.println("Текущий ввод: " + inputValue);  // Выводит строку числа в монитор порта
            OutputDisplay(inputValue);                      // Выводит значение набранное на клавиатуре на LCD
            maxZn += 1;
          }
        }
        if (key == '#') {  // Нажата клавиша "#" - выполнение операции с введенными данными
          // ллллллллллллддььторимгигишгишишгиш
        }
        if (key == '*') {  // Нажата клавиша "*" - делаем сброс всех значений в переменных и очищаем inputValue
          inputValue = "";
          maxZn = 0;
          Pmin = 0;
          Pvix = 0;
          Pmaxpad = 0;
          dT = 0;
          Tob = 0;
          flag_Sum_dT = true;
          OutputDisplay(inputValue);  // выводим на дисплей 1 "0"
        }
        if (key == 'A') {  // Нажата клавиша "A" - вывод параметров допустимого расхода воздуха Pmax. пад
          ProcessPmaxpad(inputValue);
        }
        if (key == 'B') {            // Нажата клавиша "B" - вывод параметра давления при которм нужно выходить Рвых.
          Obch_Raschet(inputValue);  // отправляемся в функцию Obch_Raschet(inputValue) для вычисления всех параметров
          ProcessPvix(inputValue);   // отправляемся в функцию ProcessPvix
        }
        if (key == 'C') {            // Нажата клавиша "C" - вывод на дисплей времени дельта Т в минутах (при давлении 300 = 15)
          Obch_Raschet(inputValue);  // отправляемся в функцию Obch_Raschet(inputValue) для вычисления всех параметров
          ProcessdT(inputValue);
        }
        if (key == 'D') {            // Нажата клавиша "D" - вывод на дисплей Тобщ. в минутах (при давлении 300 = 45)
          Obch_Raschet(inputValue);  // отправляемся в функцию Obch_Raschet(inputValue) для вычисления всех параметров
          ProcessTob(inputValue);    // отправляемся в функцию ProcessTob
        }
      }
      break;  // выходим

    case HOLD:
      if (key) {

        if (key >= '0' && key <= '9') {
          //digitalWrite(ledPin, !digitalRead(ledPin));
        }

        if (key == 'C') {  // Удерживается 2 сек клавиша "C" - вывод параметра текщего времени + dТ

          //***************************************************************************************
          if (flag_Sum_dT == true) {
            Obch_Raschet(inputValue); /* запускаем все вычисления разом, для сохранения полученных значений в переменные, чтоб потом
                                     в любое время их вывести на дисплей*/
            DateTime now = rtc.now();
            int displaytime = (now.hour() * 100) + now.minute();
            DateTime future(now + TimeSpan(0, 0, dT, 0));  // прибавляет ко времен часы и минуты
            String hour_string = String(future.hour());
            String minute_string = String(future.minute());
            minute_string = hour_string + minute_string;

            //int hour_int = hour_string.toInt();
            int minute_int = minute_string.toInt();

            displaytime = minute_int;
            Fixir_Time = minute_int;

            display.showNumberDecEx(displaytime, 0b11100000, true);
            //Serial.println(dT);
            flag_Sum_dT = false;
            Serial.println(minute_int);
            }
            else {
              display.showNumberDecEx(Fixir_Time, 0b11100000, true);
            }

          

          //****************************************************************************************
        }
      }
      break;
  }
}
//--------------------------------------------------------------------------------------
// Выводит на дисплей параметров расчета набранные на клавиатуре значения набранных клавищами с 0 до 9 включительно
void OutputDisplay(String value) {
  int OutputValueDisp = value.toInt();  // Преобразование строки в целое число
  display.showNumberDec(OutputValueDisp);
}
//---------------------------------------------------------------------------------------
// Вычисленение всех параметров разом, передача их в переменные для дальнейших выводов на дисплей
void Obch_Raschet(String value) {
  int number = value.toInt();  // Преобразование строки в целое число
  Pmin = number;               // принимает значение давления набранных пользователе с клавиатуры
  Pmaxpad = Pmin / 3;          // вычисление давления максимального падения в баллоне
  Pvix = Pmin - Pmaxpad;       // вычисление давления при котоором нужно выходить
  dT = (Pmaxpad * Vbal) / 45;  // вычисление времени в пределах которого поиск и тушение очага пожара
  Tob = (Pmin * Vbal) / 45;    // вычисление общего времени работы с момента включения в дыхательные аппараты до момента выключения
}
// ---------------------Обработка коротких нажажатий клавиш-----------------------------------------
void ProcessPmaxpad(String value) {
  int number = value.toInt();      // Преобразование строки в целое число
  Pmin = number;                   // принимает значение введенной с клавиатуры
  Pmaxpad = Pmin / 3;              // вычисление давления максимального падения в баллоне
  display.showNumberDec(Pmaxpad);  // выводит вычисленное значение на дисплей
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
// Функция для вывода Р вых. кнопкой "В"
void ProcessPvix(String value) {
  int number = value.toInt();   // Преобразование строки в целое число
  Serial.println(Pvix);         // выводит в порт вычесленное значение Pvix = Pmin - Pmaxpad
  display.showNumberDec(Pvix);  // выводит на дисплей вычесленное значение Pvix = Pmin - Pmaxpad
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
// Функция для вывода значения дельта Т клавишей "С"
void ProcessdT(String value) {
  int number = value.toInt();  // Преобразование строки в целое число
  Serial.println(dT);
  display.showNumberDec(dT);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
// Функция для вывода значения общего времени работы Т общ. клавишей "D"
void ProcessTob(String value) {
  int number = value.toInt();  // Преобразование строки в целое число
  Serial.println(Tob);
  display.showNumberDec(Tob);
}
//---------------------------------------------------------------------------------------------------

1 лайк

Не нужно экономить на переменных: одна переменная для хранения, а другая - для индикации. Возможно, флагов тоже потребуется больше одного. А, может быть, вместо флага (принимающего только два состояния) следует использовать переменную состояния (которая может принимать 3, 4, 5 или более состояний).
Но в целом, из описания проблемы трудно что-то понять, так что это только предположения.

1 лайк

Благодарю. Это мне помогло.

@HmaoKo
Вы понимаете, что эти три функции делают?

Да, конечно. Исправлено уже.

void ProcessdT() {
  //Serial.println(dT);
  display.showNumberDec(dT);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
// Функция для вывода значения общего времени работы Т общ. клавишей "D"
void ProcessTob() {
  //Serial.println(Tob);
  display.showNumberDec(Tob);

Перед этим производятся все вычисления и передаются в переменную.

void Obch_Raschet(String value) {
  int number = value.toInt();  // Преобразование строки в целое число
  Pmin = number;               // принимает значение давления набранных пользователе с клавиатуры
  Pmaxpad = Pmin / 3;          // вычисление давления максимального падения в баллоне
  Pvix = Pmin - Pmaxpad;       // вычисление давления при котоором нужно выходить
  dT = (Pmaxpad * Vbal) / 45;  // вычисление времени в пределах которого поиск и тушение очага пожара
  Tob = (Pmin * Vbal) / 45;    // вычисление общего времени работы с момента включения в дыхательные аппараты до момента выключения