Проблемы с добавлением обратного отсчета к фрагменту кода
Это и есть код. / / / - это то место, где я добавил обратный отсчет. К сожалению, обратный отсчет идет всего 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 ответ
Лучший ответ:
Я бы попробовал что-то с циклом 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
- Пытаюсь добавить обратный отсчет в код Arduino, но он делает 0 дней, 04:09:36 вместо того, чтобы начинать с 7 дней
- Проект не работает после 2 - 3 раз, требует частого выключения и включения
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Печать string and integer LCD
- Как считать время в секундах?
- как быстро loop() работает в Arduino
- Кнопка с таймером переключения и функцией сброса времени + светодиод обратной связи
- Использовать Arduino Nano V3 для программирования другого Arduino (Pro Mini)?
Вы уверены, что в вашем коде много " 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