"millis() сбрасывается на ноль приблизительно через 50 дней" - как обойти.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Спараведлива ли для обхода сброса следующая конструкция:

unsigned long currentMillis = millis();

if (currentMillis == 0) {
  Clock_Millis = currentMillis;
}

if(currentMillis - Clock_Millis > Clock_interval) {
    Clock_Millis = currentMillis;
}

Ждать для проверки 50 дней нет возможности, может кто опытный скажет?

В данном случае при сбросе будет пропуск интервала в двойном размере.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

На этом форуме уже обсуждалось. И образцы "правильного" кода для обработки интервалов - там были.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Andrey_Y_Ostanovsky пишет:

На этом форуме уже обсуждалось. И образцы "правильного" кода для обработки интервалов - там были.

 

А ссылкой не поделитесь?

Lipt0n
Offline
Зарегистрирован: 04.11.2013
ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

 

Сказать честно? Я ничего не понял....

melvladimir
Offline
Зарегистрирован: 08.03.2013

50 дней ждать не нужно, можно заменить миллис на микрос и тогда обнуление произойдет через 70 минут.

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

ЗЫ: код в первом посте нормально работать не будет, т.к. запросто пропустит "currentMillis == 0", надо на больше-меньше строить, чтобы не пропустить момент.

Lipt0n
Offline
Зарегистрирован: 04.11.2013

Я так понимаю, что вам нужно считать дни.

Для того чтобы после прошествия ~50 дней переменная не переполнялась, можете разделить время на две переменные. Первой переменной будет время работы микросхемы (результат функции millis), во второй -  кол-во дней.

Код будет таким:

if(millis()>(3600*24*1000)){

    day++;

    timer0_millis=0;

}

По истечении суток мы прибавляем один день и обнуляем счетчик.

То есть мы просто сокращаем размер счетчика до одних суток.  

Фактически переводим время в другую систему измерений.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Без разъяснений ТС мы будем долго гадать зачем это нужно и как лучше решить :)

std
Offline
Зарегистрирован: 05.01.2012

Lipt0n пишет:
timer0_millis=0;

2: error: 'timer0_millis' was not declared in this scope

В какие сакральные арканы меня не посвятили? Не покидает смутное ощущение, что я таки что-то упустил.

MaksMS
Offline
Зарегистрирован: 11.03.2013

Переменная локальная и добавлять надо в wiring.c  в самой функции millis()

melvladimir
Offline
Зарегистрирован: 08.03.2013

А что, без извращений (я про ковыряние библиотек) жизнь скучна?

Можно запрячь, например, второй таймер под свои нужды с нужным предделителем и выставить срабатывание прерывания по переполнению таймера, а в функции обработки прерывания то ли просто делать ++ (increment) то ли что-то серъезнее...

Но без топикстартера это из разряда: "как забить гвоздь?"
Куда забить? (материал, предмет, его размещение) Какой гвоздь? Что он будет держать? Поэтому проще ответить "двумя руками" (заодно и по пальцу себе не врежешь) :)

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

ingener.solovyev пишет:

А ссылкой не поделитесь?

http://arduino.ru/forum/programmirovanie/obrabotka-perepolneniya-schetchika-millisekund - ну, вот тут, например...

http://arduino.ru/forum/programmirovanie/eshche-raz-migaem-svetodiodom-b... - вот еще...

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

стоит в скетче отправляющим различные данные через Ethernet. снятие и отправка данных производятся раз в минуту. Для этого, как раз, millis и использую.

melvladimir
Offline
Зарегистрирован: 08.03.2013

ИМХО, лучше использовать таймер 2 и его переполнение, чтобы не задумываться об обнулении основного счетчика.

И потом, насколько критичен пропуск одного интервала? Если один раз в 50 дней пропустить одну минуту - это не критично, то оставить завязку на ms

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

melvladimir пишет:

ИМХО, лучше использовать таймер 2 и его переполнение, чтобы не задумываться об обнулении основного счетчика.

И потом, насколько критичен пропуск одного интервала? Если один раз в 50 дней пропустить одну минуту - это не критично, то оставить завязку на ms

пропустить не кретично, про остальное как то подробнее можно?

melvladimir
Offline
Зарегистрирован: 08.03.2013

Если не критично, тогда можно сделать так:

unsigned long prev_ms=0;
if (millis() < prev_ms) {prev_ms = millis();} //это проверка обнуления миллисекунд
if ((millis() - prev_ms) >= 60000) { //отбивка интервала в 1 минуту
	prev_ms = millis(); //засекаем когда сработал интервал
//сюда какую-то обработку, которая будет срабатывать каждую минуту
}

По таймеру - тоже могу написать код с камментами, но если "суперточность" не нужна (+/-10мс - допустимо), то вышеуказанного кода хватит.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

melvladimir пишет:

Если не критично, тогда можно сделать так:

unsigned long prev_ms=0;
if (millis() < prev_ms) {prev_ms = millis();} //это проверка обнуления миллисекунд
if ((millis() - prev_ms) >= 60000) { //отбивка интервала в 1 минуту
	prev_ms = millis(); //засекаем когда сработал интервал
//сюда какую-то обработку, которая будет срабатывать каждую минуту
}

По таймеру - тоже могу написать код с камментами, но если "суперточность" не нужна (+/-10мс - допустимо), то вышеуказанного кода хватит.

для общего развития бы хотелось, спасибо!

Морда лица
Offline
Зарегистрирован: 15.11.2013

Lipt0n пишет:
Я так понимаю, что вам нужно считать дни.  Для того чтобы после прошествия ~50 дней переменная не переполнялась, можете разделить время на две переменные. Первой переменной будет время работы микросхемы (результат функции millis), во второй -  кол-во дней.  Код будет таким:

if(millis()>(3600*24*1000)){
    day++;
    timer0_millis=0;
}

По истечении суток мы прибавляем один день и обнуляем счетчик.  То есть мы просто сокращаем размер счетчика до одних суток.   Фактически переводим время в другую систему измерений.

Имхо плохой способ, имеющий методическую ошибку.

Без прерывания вы не поймаете точный момент окончания суток,  основная программа только и будет заниматься слежением за переходом границы суток, а сможете ли использовать для прерывания таймер занятый в других процедурах - большой вопрос.

 

Lipt0n
Offline
Зарегистрирован: 04.11.2013

Морда лица пишет:

Имхо плохой способ, имеющий методическую ошибку.

Без прерывания вы не поймаете точный момент окончания суток,  основная программа только и будет заниматься слежением за переходом границы суток, а сможете ли использовать для прерывания таймер занятый в других процедурах - большой вопрос.

Имеете ввиду использование внешнего часового модуля?(как-то пробовал делать подобие часов - погрешность большая была)

Почему это - основная программа, разве что-то мешает исполняться другому коду?

Это да, таймер может еще где-то использоваться, но в данном случае - по истечении суток должно произойти то же самое что и после 50 дней без этого кода, можно значение времени уменьшить и просто проверить.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

А почему вы называете внешний часовой модуль- часы( RTC ) так унизительно - "подобие часов" ?

std
Offline
Зарегистрирован: 05.01.2012

А можно ли для решения этой проблемы раз в месяц устраивать Hard reset при помощи сторожевого таймера и бесконечного цикла? Насколько я знаю, в петлю "crazy blink" дуино попадает по WDT, только имея бажный загрузчик; достаточно записать optiboot или вообще без загрузчика, и всё будет тип-топ. Поправьте, если ошибаюсь.

step962
Offline
Зарегистрирован: 23.05.2011

trembo пишет:

А почему вы называете внешний часовой модуль- часы( RTC ) так унизительно - "подобие часов" ?

Если я правильно понял LiptOn'а, то "неким подобием часов" он называет свое творение на базе RTC.

Самокритично... Но автору, наверное, виднее.

Lipt0n
Offline
Зарегистрирован: 04.11.2013

step962 пишет:

trembo пишет:

А почему вы называете внешний часовой модуль- часы( RTC ) так унизительно - "подобие часов" ?

Если я правильно понял LiptOn'а, то "неким подобием часов" он называет свое творение на базе RTC.

Самокритично... Но автору, наверное, виднее.

В том то и дело что это "некое подобие часов" было на чистой arduino без часового модуля.

А устройство просто замыкало релюшку по времени.

Lipt0n
Offline
Зарегистрирован: 04.11.2013

std пишет:

А можно ли для решения этой проблемы раз в месяц устраивать Hard reset при помощи сторожевого таймера и бесконечного цикла? Насколько я знаю, в петлю "crazy blink" дуино попадает по WDT, только имея бажный загрузчик; достаточно записать optiboot или вообще без загрузчика, и всё будет тип-топ. Поправьте, если ошибаюсь.

Вот как раз это хорощо рассписано тут - http://habrahabr.ru/post/189744/ .

Но можно поступить проще и повесить RESET на какую-то из ног.

std
Offline
Зарегистрирован: 05.01.2012

Транзистор, подтягивающий сброс с ноги, ствить нельзя - сигнал на базе может стать нулём в момент сброса, но длительность импульса окажется недостаточной, и в результате устройство надёжно повиснет. Расширять импульс при помощи конденсатора на базе транзюка тоже нельзя - кондёр может высохнуть.

Lipt0n
Offline
Зарегистрирован: 04.11.2013

std пишет:

Транзистор, подтягивающий сброс с ноги, ствить нельзя - сигнал на базе может стать нулём в момент сброса, но длительность импульса окажется недостаточной, и в результате устройство надёжно повиснет. Расширять импульс при помощи конденсатора на базе транзюка тоже нельзя - кондёр может высохнуть.

Высохнуть то он может, как и выйти из строя какой-то другой из элементов.

Для "серьёзных" плат делают расчёт надежности, который нам и покажет слабое место. Если устройство умирает раньше срока - ему обычно полагается сервисное обслуживание(если не оговорены другие условия).

И вобще каждый выбирает для себя сам как ему делать устройство - одному хватит "сколхозничать", другой же позаботится о более надежной защите.