Пытаюсь добавить обратный отсчет в код Arduino, но он делает 0 дней, 04:09:36 вместо того, чтобы начинать с 7 дней

Код, который я использую, вероятно, имеет математическую проблему, так как Arduino может считать только 16 - битное целое число. Эта проблема связана с функцией WeekDelay (). Проект предназначен для Аэрогардена. Он качает воду в сад каждую неделю из информации, основанной на моих собранных данных. Он записывает на ЖК-дисплее информацию, например, если он качает, ждет (у него должен быть таймер здесь и дисплей на ЖК-дисплее), и он может показать, когда он собирается качать с предупреждением о звуковом сигнале. После звукового сигнала, перекачки и ожидания в течение нескольких раз у меня заканчивается информация, я делаю цикл и показываю предупреждающее сообщение, мигая жидкокристаллическим дисплеем и перекачивая заданное количество. Более конкретно WeekDelay() должен быть задержкой на неделю. Он очищает ЖК-дисплей, устанавливает курсор на 0,0 и печатает "Ожидание одной недели". Затем на экране должен появиться обратный отсчет в 24 часа, а затем - сколько дней он ждет. Он делает это, очищая ЖК-дисплей, устанавливая курсор, печатая дни и ожидая.

Из-за сбоя он не отображает ни одного дня, хотя должен показывать 7. Он показывает 04:09:36. Кто-то помогал мне и сказал следующее:

Ах, это целочисленная математика, взаимодействующая с размером дней. 04:09:36 = 43600+960+36 = 14976 который оказывается равным 7243600 % 32768. См. gammon.com.au/forum/?id=12146 и https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Используйте+правильные+целочисленные+точности для того, что происходит.

Это какая-то урезанная версия моего кода:

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);
  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];
     int 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",
            countdown_day, 
            countdown_hour, 
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);       
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);      
     delay(1000);
     }
}


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(1000);
}








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(12000);  //Добавляет задержку в 24000 миллисекунд
  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(); // включить подсветку.
}

Это функция, которая должна быть исправлена:

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];
     int 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",
            countdown_day, 
            countdown_hour, 
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);       
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);      
     delay(1000);
     }
}

, 👍1

Обсуждение

совет: выполните команду lcd.print("ВОДЯНОЙ НАСОС АКТИВЕН"); ... задержка(100); ... lcd.print("."); ... нет необходимости очищать ЖК-дисплей и печатать одну и ту же строку снова и снова, @jsotola


1 ответ


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

1

Как уже сказано в комментарии, вы пытаетесь вычислить константу с литералами int, которая переполняется:

unsigned long week_secs = 7 * 24 * 3600;

Это 604800 (0x93A80), но поскольку ints-это просто 16-битные числа со знаком (в вашей системе компилятора), учитываются только младшие 16 бит. К счастью, эти младшие 16 бит положительны в дополнении к двум, и поэтому вы получаете 14976 (hex 0x3A80).

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

unsigned long week_secs = 7UL * 24 * 3600;

,

Надеюсь, я увижу тебя на небесах. Большое вам спасибо. Это заняло так много времени, чтобы понять., @alexlikesallthegamez