Пытаюсь добавить обратный отсчет в код 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 ответ
Лучший ответ:
Как уже сказано в комментарии, вы пытаетесь вычислить константу с литералами int, которая переполняется:
unsigned long week_secs = 7 * 24 * 3600;
Это 604800 (0x93A80), но поскольку int
s-это просто 16-битные числа со знаком (в вашей системе компилятора), учитываются только младшие 16 бит. К счастью, эти младшие 16 бит положительны в дополнении к двум, и поэтому вы получаете 14976 (hex 0x3A80).
Правильный оператор использует по крайней мере одно длинное
значение без знака, и правила целочисленного продвижения гарантируют, что все значения также будут преобразованы в этот тип.
unsigned long week_secs = 7UL * 24 * 3600;
Надеюсь, я увижу тебя на небесах. Большое вам спасибо. Это заняло так много времени, чтобы понять., @alexlikesallthegamez
- Проблемы с добавлением обратного отсчета к фрагменту кода
- Проект не работает после 2 - 3 раз, требует частого выключения и включения
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Печать string and integer LCD
- Как считать время в секундах?
- как быстро loop() работает в Arduino
- Кнопка с таймером переключения и функцией сброса времени + светодиод обратной связи
- Использовать Arduino Nano V3 для программирования другого Arduino (Pro Mini)?
совет: выполните команду
lcd.print("ВОДЯНОЙ НАСОС АКТИВЕН");
...задержка(100);
...lcd.print(".");
... нет необходимости очищать ЖК-дисплей и печатать одну и ту же строку снова и снова, @jsotola