Проблемы с добавлением обратного отсчета к фрагменту кода

Это и есть код. / / / - это то место, где я добавил обратный отсчет. К сожалению, обратный отсчет идет всего 9 секунд. То, что я хочу, чтобы он сделал, это спустился на полные 24 часа. Я пытался исправить эту ошибку в течение нескольких месяцев, но безуспешно.

int beeper_pin      = 2; //Наименование контакта зуммера
int resetGarden_pin = 3; //Наименование контакта предупреждающего светодиода
int pump_pin        = 6; //Наименование контакта насоса



#include <LiquidCrystal_I2C.h> // Библиотека драйверов для ЖК-модуля

LiquidCrystal_I2C lcd(0x27, A4, A5);

void clearLCDLine(int line)
{
  lcd.setCursor(0, line);
  for (int n = 0; n < 20; n++) // 20 indicates symbols in line. For 2x16 LCD write - 16
  {
    lcd.print(" ");
  }
}







void beepWarning() {            //Делает звуковой сигнал подпрограммой

  lcd.setCursor(0, 0);
  lcd.print("WARNING");
  delay(100);
  lcd.setCursor(0, 1);
  for (int x = 0; x < 3; x++) {

    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE.");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE..");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE...");
    delay(100);
    clearLCDLine(1);
  }

  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP ACTIVE...");

  for (int x = 0; x < 3; x++) {   //Повторяется 3 раза

    digitalWrite(beeper_pin, HIGH); //Включить зуммер
    delay(100);                     //Задержка 400 миллисекунд
    digitalWrite(beeper_pin, LOW);  //Выключает зуммер
    delay(100);                     //Задержка 400 миллисекунд

  }
}







void SOSWarning() {            //Делает SOS подпрограммой

  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("WPA Reset Aerogarden");

  for (int x = 0; x < 3; x++) {   //Повторяется 3 раза

    for (int d = 0; d < 3; d++) {   //Повторяется 3 раза
      digitalWrite(beeper_pin, HIGH); //Включить зуммер
      delay(200);                     //Задержка 400 миллисекунд
      digitalWrite(beeper_pin, LOW);  //Выключает зуммер
      delay(200);                     //Задержка 400 миллисекунд
    }

    for (int a = 0; a < 3; a++) {   //Повторяется 3 раза
      digitalWrite(beeper_pin, HIGH); //Включить зуммер
      delay(400);                     //Задержка 400 миллисекунд
      digitalWrite(beeper_pin, LOW);  //Выключает зуммер
      delay(400);                     //Задержка 400 миллисекунд
    }

    for (int d = 0; d < 3; d++) {   //Повторяется 3 раза
      digitalWrite(beeper_pin, HIGH); //Включить зуммер
      delay(200);                     //Задержка 400 миллисекунд
      digitalWrite(beeper_pin, LOW);  //Выключает зуммер
      delay(200);                     //Задержка 400 миллисекунд
    }

    delay(500);                     //Задержка 500 миллисекунд
  }
}







void weekDelay() { //Делает ожидание недели подпрограммой
  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");





long hour = 23, minute = 59, second = 59;//////////////////////////
long countdown_time = (hour * 3600) + (minute * 60) + second; ///////////////////////////////////////////////////////////////////////////

  long countdowntime_seconds = countdown_time - (millis() / 1000); /////////
  
  if (countdowntime_seconds >= 0) {   ///////////////////////////////////////////////
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(4, 1);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }
  delay(500);///////////////////////////////////////////////////////////////









  delay(500);

  delay(86400000);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting Six Days");
  delay(86400000);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting Five Days");
}








void pumpOn() {               //Делает включение насоса подпрограммой
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("PUMPING");
  delay(100);
  digitalWrite(pump_pin, HIGH); //Turning on the pump
}








void pumpOff() {              //Делает выключение насоса подпрограммой
  digitalWrite(pump_pin, LOW);  //Turning off the pump
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP OFF");
  delay(100);
}








void setup() {
  //запустить один раз:
  lcd.backlight();
  lcd.init();

  lcd.setCursor(4, 0);//////////////////////////////////////////////////////
  lcd.print("HH:MM:SS"); //////////////////////////////////////////////////


  lcd.clear(); // Очистить экран
  lcd.setCursor(0, 0);
  lcd.print("Aero_Pump V3");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("By Alex");
  delay(1000);
  pinMode (beeper_pin,      OUTPUT); //Настройка выходов
  pinMode (resetGarden_pin, OUTPUT); //Setting outputs
  pinMode (pump_pin,       OUTPUT); //Настройка выходов
  lcd.clear(); // Очистить экран


  digitalWrite(resetGarden_pin, LOW); //Выключение сброса садового света


  beepWarning(); //Подает звуковой сигнал предупреждения
  pumpOn();      //Включает насос
  delay(3000);  //Добавляет задержку в 24000 миллисекунд
  pumpOff();     //Выключает насос
  weekDelay();   //Ждет неделю

  beepWarning(); //Подает звуковой сигнал предупреждения
  pumpOn();      //Включает насос
  delay(135000);  //Добавляет задержку в 48000 миллисекунд
  pumpOff();     //Выключает насос
  weekDelay();   //Ждет неделю
}







void loop() {

  SOSWarning(); //Подает звуковой сигнал SOS warning
  pumpOn();      //Включает насос
  delay(48000);  //Добавляет задержку в 48000 миллисекунд
  pumpOff();     //Выключает насос

  for (int x = 0; x < 3024000; x++) {
    lcd.backlight(); // включить подсветку.
    delay(100);
    lcd.noBacklight(); // выключить подсветку
    delay(100);
  }
  lcd.backlight(); // включить подсветку.
}

Это более конкретно то, что нужно исправить:

long hour = 23, minute = 59, second = 49;//секунда //////////////////////////
long countdown_time = (hour * 3600) + (minute * 60) + second; ///////////////////////////////////////////////////////////////////////////

  long countdowntime_seconds = countdown_time - (millis() / 1000); /////////
  
  if (countdowntime_seconds >= 0) {
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(4, 1);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }

Это какой-то отредактированный код, который я пробовал, но, возможно, ошибся, потому что он делает 0 дней вместо 7 и (часы/мин/сек) 04:09:36.

void weekDelay() { //Делает ожидание недели подпрограммой
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");


  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     unsigned long countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff,"%1d days, %02d:%02d:%02d",
            (int) countdown_day, 
            countdown_hour, 
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);       
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);      
     delay(1000);
     }
}

, 👍-1

Обсуждение

Вы уверены, что в вашем коде много " delay ()". Вот простой таймер обратного отсчета на основе `миллиса", если вам интересно. https://arduinoprosto.ru/q/82217/37523, @VE7JRO

Похоже, что обратный отсчет просто пропущен по какой-то причине., @alexlikesallthegamez

Я был бы рад вам помочь. Прежде чем писать какой-либо код, лучше сначала написать "руководство пользователя". Можете ли вы дать мне описание вашего проекта, что он делает, когда он это делает и так далее?, @VE7JRO

Ваш код находится в середине функции weekDelay (), которая, похоже, имеет несколько проблем. Что вы ожидаете от weekDelay ()?, @Dave X

Проект предназначен для Аэрогардена. Он качает воду в сад каждую неделю из информации, основанной на моих собранных данных. Он записывает на жидкокристаллический дисплей информацию, например, если он качает, ждет (здесь должен быть таймер), и может показать, когда он собирается качать, с предупреждением о звуковом сигнале. После звукового сигнала, перекачки и ожидания в течение нескольких раз у меня заканчивается информация, я делаю цикл и показываю предупреждающее сообщение, мигая жидкокристаллическим дисплеем и перекачивая заданное количество., @alexlikesallthegamez

WeekDelay() должен быть задержкой на неделю. Он очищает ЖК-дисплей, устанавливает курсор на 0,0 и печатает "Ожидание одной недели". Затем на экране должен появиться обратный отсчет в 24 часа, а затем - сколько дней он ждет. Он делает это, очищая ЖК-дисплей, устанавливая курсор, печатая дни и ожидая., @alexlikesallthegamez

Это должно подождать неделю? Как есть, "weekDelay" выглядит так, как будто он делает только двухдневную "delay(86400000);" паузу. Вы можете заменить большую часть его кода на char buff[80]; sprintf(buff,"%02d:%02d:%02d",countdowntime_hour,countdowntime_minute,countdowntime_secs); lcd.print(buff); Кроме того, похоже, что у него нет никакой логики обратного отсчета-из этого кода я не вижу циклов в weekDelay (), которые могли бы отсчитывать даже 9 секунд, не говоря уже о 604800 секундах в неделю., @Dave X

Ответ очень хорош и, кажется, работает. Но у меня есть вопрос. Как бы я заставил его отсчитывать время? Извините за дополнительное время, которое это займет у вас. Я все равно поставлю вам галочку за всю проделанную работу., @alexlikesallthegamez

Я откатил вашу правку, потому что она слишком сильно изменила вопрос., @Juraj


1 ответ


Лучший ответ:

0

Я бы попробовал что-то с циклом while(){} и sprintf(), например:

void weekDelay() { //Делает ожидание недели подпрограммой
  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     unsigned long countdown_day = countdowntime_seconds / 3600 / 24;
     // или, может быть
     //int countdown_day = (int)(countdowntime_seconds / 3600UL / 24UL);

     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff,"%1d days, %02d:%02d:%02d",
            (int) countdown_day, 
            countdown_hour, 
            countdown_minute,
            countdown_sec
            );
     clearLCDLine(1);
     lcd.setCursor(0, 0);
     lcd.print(buff);      
     delay(1000);
     }
}

Или сделайте его более общим и начните так:

void coundownDelay(unsigned long seconds) { //Делает ожидание недели подпрограммой
  unsigned long start = millis();
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = seconds - (millis() - start)/1000){

     ...

}

и звонят вроде:

  ...
  countdownDelay(7 * 24 * 3600);   //Ждет неделю
  ...
,

Это невероятно близко, и я очень благодарен вам за ваш вклад., @alexlikesallthegamez

Извините, у меня было неправильное чувство направления. Я отредактировал математику. Для отладки вы можете попробовать меньшие задержки, чтобы увидеть, если и где что-то пойдет не так, менее чем за 9 часов., @Dave X

Ах, это целочисленная математика, взаимодействующая с размером дней. 04:09:36 = 4*3600+9*60+36 = 14976 который оказывается равным 7*24*3600 % 32768. См. https://www.gammon.com.au/forum/?id=12146 и https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Используйте+правильные+целочисленные+точности для того, что происходит. Я добавил некоторые кастинги и типы в строку day=. С другой стороны, можно определить дни как"длинные дни без знака", а затем напечатать их с помощью "sprintf(buff," %1d days, %02lu:%02d:%02d",", @Dave X

Я изменил свой код на int countdown_day = countdowntime_seconds / 3600 / 24;, чтобы иметь два деления вместо умножения и деления. У меня нет arduino, так что он все еще не протестирован. В Си работало несколько версий., @Dave X

Это конкретное число, 04:09:36, особенное, это 14976 секунд, то есть неделя работы секунд (7*24*3600=604800) принудительно в знак int, который может содержать только числа в -32768, +32767. Это указывает на проблемы с математикой с 16-битными числами. Прямо сейчас я могу тестировать биты кода только с помощью gcc на Mac, где математика по умолчанию выполняется с помощью 32-битных int. Я добавил в код два варианта: один выполняет математику с помощью неподписанных длинных строк (и приводит ее к int для sprintf), а другой пытается сохранить математику в ULs и привести ее к int для хранения., @Dave X

Я отредактировал код внизу. К сожалению, это была та же проблема. Сначала я попытался просто использовать код 24UL, и он сказал, что "день обратного отсчета" не определен. Это исправило проблему, когда я добавил оба фрагмента кода, но это могло быть не то, что вы имели в виду, когда создавали код. Вы хотите, чтобы я определил дни? Кроме того, я проверю код на эмуляторе Си., @alexlikesallthegamez

Какой эмулятор вы используете? И какой код вы для этого использовали?, @alexlikesallthegamez