Help. Переполнение значения переменной типа unsigned long!!!!!!
- Войдите на сайт для отправки комментариев
Всем кто читает это, здравствуйте.
Прошу помощи у более опытных программеров. Имею нижеприведенный скетч для сравнения текущего времени с заданным
Скетч работает в составе програмного кода управления баней.
byte CompTime(int HR, int MIN) //Передаваемые параметры HR, MIN Возвращаемое значение ResultTime
{
byte ResultTime;
unsigned long InstTime = (HR * 60 * 60 + MIN * 60); //Переводим пороговое время в количество секунд от начала суток
clock.getTime();
byte SEC = clock.second;
MIN = clock.minute;
HR = clock.hour;
unsigned long NowTime = (HR * 60 * 60 + MIN * 60 + SEC); //Переводим текущее время в количество секунд от начала суток
if (NowTime > InstTime) ResultTime = true; else //Если текущее время больше порогового, возвращаем логическую единицу
if (NowTime < InstTime) ResultTime = false; else //Если текущее время меньше порогового, возвращаем логический ноль
if (NowTime == InstTime) //Если текущее время равно пороговому, возвращаем значение "2"
{
ResultTime = 2; delay(750); //Ждем 750 мСек для того чтобы цикл не успел повториться в течение этой секунды
}
return ResultTime;
}
Проблема в том что в строке 8 значение InstTime никогда не превышает 65535, т.е приблизительно в 18:12 переменная приобретает значение 0, хотя предельное значение переменной типа unsigned long равно 4 294 967 295
В строке 13 переменная NowTime имеет значение 4 294 967 295 уже приблизительно в 11:56, далее знчение становится равным 0 и отсчет начинается снова, хотя в сутках всего 86400 секунд
Путем подбора различных способов реализации алгоритма скетч трансформировался в следующий:
byte CompTime(byte HrIns, byte MinIns) //Передаваемые параметры HR, MIN Возвращаемое значение ResultTime
{
byte ResultTime;
clock.getTime();
byte HR = clock.hour;
byte MIN = clock.minute;
byte SEC = clock.second;
unsigned int m = HR*60;
unsigned long NowTime = m * 60 + MIN*60 + SEC; //Переводим текущее время в количество секунд от начала суток
unsigned long InstTime = MinIns*60 + 60*HrIns*60; //Переводим пороговое время в количество секунд от начала суток
if (NowTime > InstTime) ResultTime = true; else //Если текущее время больше порогового, возвращаем логическую единицу
if (NowTime == InstTime) //Если текущее время равно пороговому, возвращаем значение "2"
{
ResultTime = 2; delay(750); //Ждем 750 мСек для того чтобы этот цикл не успел повториться в течение этой секунды пока время 21:00
} else
if (NowTime < InstTime) ResultTime = false; //Если текущее время меньше порогового, возвращаем логический ноль
return ResultTime;
}
Проблема с переполнением NowTime изчезла, однако InstTime победить не удалось ни таким ни другими способами.
Посоветуйте пжл что делаю неправильно. Возможно есть другой алгоритм реализации функции сравнения текущего времени с заданным
Плата Arduino Mega, пробовал компилировать в средах 1.0.6, 1.6.6, 1.8.2 с одинаковым результатом
Заранее благодарен откликнувшимся
Значение HR и Min не превышает 59. Поэтому эти переменные и объявлены как Int в строке 5
Или не про это?
Проблема с переполнением NowTime изчезла, однако InstTime победить не удалось ни таким ни другими способами.
надо так:
Иначе у вас вычисления идут в размерности byte, а не unsigned long
Спасибо громадное. Завтра попробую. Чую что вы правы.
Вставляйте сериалы, мониторьте значения переменных и результатов вычислений с ними. Где то косяк и вынырнет. Ну никак в этих формулах лонга не переполнить.
bwn, не разу не сталкивались с такой ситуацией? :) Можно конечно как советовал b707, но как тогда решить пример где все множители уже заданные переменные. Например так:
Поэтому лучше всегда объявлять тип данных для обоих половин выражений:
Поэтому лучше всегда объявлять тип данных для обоих половин выражений:
"обеих половин выражений" не совсем точно. В Вашем примере тип объявлен только для a. А вот если действительно сделать "дл половины выражения" (unsigned long) (a*b*c), то опять же будет хрень.
учим наизусть приведение типов, лучше бы это было сделать ДО того, как начинать программировать.
Самый грамотный вариант решения - у b707.
bwn, не разу не сталкивались с такой ситуацией? :) Можно конечно как советовал b707, но как тогда решить пример где все множители уже заданные переменные. Например так:
Бог миловал.))) Пока писал свой ответ, прилетели все предыдущие, прочитал их позже. Править не стал, решил, что мониторинг сериалом все равно не повредит.
А так, да, если ни разу не наступил на грабли, это еще не значит, что их нет.(((( Каюсь.
Спасибо b707 за помощь. Все получилось. Верно говорят Век живи, век учись.
Пожалуйста помогите!
#include <TimeLib.h> #include <DS1307RTC.h> // датчик времени подкл SDA-А4, SCL-А5 tmElements_t tm; // назначил tm как элемент текущ времени // Печать в порт строки с параметром void SerPrnt(String S, int prmt) { Serial.print(S + " ="); Serial.println(prmt); } void setup() { Serial.begin(9600); RTC.read(tm); // текущее время 18:32 unsigned long t1 = tm.Hour; unsigned long t2 = tm.Minute; unsigned long t3 = (unsigned long)t1*3600UL; unsigned long t4 = t2 * 60; SerPrnt("t1", t1); //результат 18 SerPrnt("t2", t2); //результат 32 SerPrnt("t3", t3); //результат -736 ?????? НУ КАК ТАК-ТО ???? SerPrnt("t4", t4); //результат 1920 (=18*60) } void loop() { }запустите данный код, удивитесь void setup () { Serial.begin(9600); Serial.println(sizeof(long)); Serial.println(sizeof(int)); } void loop() { }Пожалуйста помогите!
#include <TimeLib.h> #include <DS1307RTC.h> // датчик времени подкл SDA-А4, SCL-А5 tmElements_t tm; // назначил tm как элемент текущ времени // Печать в порт строки с параметром void SerPrnt(String S, int prmt)//<- обратите на это int prmt /* ддя тех ктов танке то идет преобразоваете из любого типа в int*/ { Serial.print(S + " ="); Serial.println(prmt); } void setup() { Serial.begin(9600); RTC.read(tm); // текущее время 18:32 unsigned long t1 = tm.Hour; unsigned long t2 = tm.Minute; unsigned long t3 = (unsigned long)t1*3600UL; unsigned long t4 = t2 * 60; SerPrnt("t1", t1); //результат 18 SerPrnt("t2", t2); //результат 32 SerPrnt("t3", t3); //результат -736 ?????? НУ КАК ТАК-ТО ???? SerPrnt("t4", t4); //результат 1920 (=18*60) } void loop() { }Пожалуйста помогите!
#include <TimeLib.h> #include <DS1307RTC.h> // датчик времени подкл SDA-А4, SCL-А5 tmElements_t tm; // назначил tm как элемент текущ времени // Печать в порт строки с параметром void SerPrnt(String S, int prmt) { Serial.print(S + " ="); Serial.println(prmt); } void setup() { Serial.begin(9600); RTC.read(tm); // текущее время 18:32 unsigned long t1 = tm.Hour; unsigned long t2 = tm.Minute; unsigned long t3 = (unsigned long)t1*3600UL; unsigned long t4 = t2 * 60; SerPrnt("t1", t1); //результат 18 SerPrnt("t2", t2); //результат 32 SerPrnt("t3", t3); //результат -736 ?????? НУ КАК ТАК-ТО ???? SerPrnt("t4", t4); //результат 1920 (=18*60) } void loop() { }Тип данных передаваемый в качестве второго аргумента функции SerPrnt стоит проверить.
Мало того что 16-битный , так ещё и знаковый.
ОГРОМНОЕ спасибо!
Слона-то я и не заметил!
Исправил на void SerPrnt(String S, unsigned long prmt) и все стало на место.
Пожалуйста помогите!
Как говорится, если человек ХАМ, то это навсегда.
Как говорится, если человек ХАМ, то это навсегда.
Хам или "Нехам" - это другое дело, но Квон тот же самый ответ написал тебе на полтора часа раньше. А "спасибо" не получил. ;))
Как говорится, если человек ХАМ, то это навсегда.
А если у кого-то с самоиронией проблемы, то это насколько?
Надеюсь, что модератор удалит этот флуд не по теме.
Твой - да.