Остановка таймера обратного отсчета, когда он достигает 0

Я пытаюсь изменить следующий набросок, чтобы сделать обратный отсчет (который, кажется, частично работает). Что мне нужно изменить, чтобы таймер остановился на нуле? Прямо сейчас он отсчитывает от 10 секунд, проходит через ноль и переходит в отрицательные значения. Я действительно борюсь с кодированием, я пытался изучать наброски других людей, проводить исследования в Интернете, купил (и изучил) пару книг Саймона Монкса, но я все еще не могу разобраться с этим. Может кто-нибудь указать мне правильное направление?

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define WAITING 0 // ожидание начала
#define TIMERONE 1 // таймер один запущен
#define FINISHED 3 // таймер завершен
#define countdown 10
const int resetPin = 6;
const int buttonPin = 7;
const int ledPin =  13;      // номер пина светодиода

long startTime = 0;
long timeOne = 0;
int timer = WAITING; // состояние таймера. Изначально ожидание первого нажатия кнопки
int reset = 0;  // сброс состояния кнопки
int button = 0; // состояние основной кнопки

void setup()   {

  pinMode(buttonPin, INPUT); //инициализируем контакт кнопки для входа
  pinMode(resetPin, INPUT);  //инициализация сброса контакта на вход
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // инициализируем с адресом I2C 0x3c
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(55, 00);
  printDigits(0);
}

void loop() {
  //-------- основной цикл -------
  switch (timer) {
    case WAITING: // начальное состояние - ожидание первого нажатия кнопки.
      display.clearDisplay();
      display.setCursor(55, 00);
      printDigits(0);
      display.display(); // отображаем экран, показывающий 00:00
      button = digitalRead(buttonPin);
      if (button) { // кнопка нажата.
        timer = TIMERONE;
        startTime = millis();//считываем время нажатия кнопки.
        while (digitalRead(buttonPin)) {
          //--- дождитесь отпускания кнопки.
        }
      }
      break;
    case TIMERONE:
      timeOne = millis();
      button = digitalRead(buttonPin);
      reset = digitalRead(resetPin);
      display.clearDisplay();
      display.setCursor(55, 00);
      printDigits (timeOne - startTime);
      display.display();
      //-----------------------------------
      if (reset) { //кнопка сброса была нажата. Очистить экран и начать заново
        timer = WAITING;
        while (digitalRead(resetPin)) {
          //--- дождитесь отпускания кнопки сброса.
        }
      }
      if (button) { // кнопка была нажата
        timer = FINISHED;
        while (digitalRead(buttonPin)) {
          //--- дождитесь отпускания кнопки.
        }
      }
      break;
    case FINISHED:
      reset = digitalRead(resetPin);
      if (reset) { //кнопка сброса была нажата. Очистить экран и начать заново
        display.clearDisplay();
        display.setCursor(55, 0);
        printDigits(0);
        display.display();
        timer = WAITING;
        while (digitalRead(resetPin)) {
        }
      }
      break;
  }
}

void printDigits(long timeInMillis) {
  int seconds;
  int hundredths;

  seconds = countdown - timeInMillis / 1000;
  hundredths = (timeInMillis % 1000) / 10;

  if (seconds < 10) { // вывести начальный ноль, если необходимо
    display.print("0");
  }
  display.print(seconds);
  display.print(":");
  if (hundredths < 10) { //вывести начальный ноль, если необходимо
    display.print("0");

  }
  display.print(hundredths);

}

, 👍1

Обсуждение

попробуйте это изменение "if (seconds < 10) { // при необходимости вывести начальный ноль" ===> "if (seconds < 10 && seconds > 0) {", @futurebird

@bender, ответы помогли? Вы можете принять один, @Juraj


2 ответа


1
case TIMERONE:
  timeOne = millis();
  if (timeOne - startTime > countdown) {
    timer = WAITING;
    break;
  }
...

но с этим изменением время обратного отсчета вычисляется дважды. вам следует изменить код, чтобы вычислить текущее значение обратного отсчета вне printDigits в case TIMERONE:, а затем проверить, меньше ли оно 0.

и поместите clearDisplay и cursorPosition в функцию printDigits

,

2

В этой строке вы вычисляете время, которое собираетесь отобразить. Вы можете использовать тот же расчет в операторе if, чтобы перейти в состояние FINISHED в вашем конечном автомате.

printDigits (timeOne - startTime);
if(timeOne - startTime >= someInterval) {
    timer = FINISHED;
}

где someInterval — это количество миллисекунд, в течение которых должен работать таймер.

,