Программный Reset в определенное время

Darkherald
Offline
Зарегистрирован: 30.08.2019

Здравствуйте.

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

К примеру, мне необходимо раз в сутки перезагрузить ардуинку в 00:00:00 часов. Но не через какое-то время после включения.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Darkherald пишет:

Здравствуйте.

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

К примеру, мне необходимо раз в сутки перезагрузить ардуинку в 00:00:00 часов. Но не через какое-то время после включения.

Тогда надо нанять толкового маёра, обязательно с часами, чтоб он приходил в 00:00:00, смотрел, всё ли в порядке, ну и заадно, нажимал бы на большую красную кнопку "СБРОС"

Logik
Offline
Зарегистрирован: 05.08.2014

Без источника точного времени определить что настало 00:00:00 невозможно. Кроме часов с батарейкой есть варианты: GSM, GPS, Internet и т.д.

Darkherald
Offline
Зарегистрирован: 30.08.2019

Logik пишет:

Без источника точного времени определить что настало 00:00:00 невозможно. Кроме часов с батарейкой есть варианты: GSM, GPS, Internet и т.д.

   

Интнрнет есть и при включении получаем отметку времен. по принципу UNIX. Извините забыл это добавить.

sadman41
Offline
Зарегистрирован: 19.10.2016

Таймштамп получил, таймер завёл на тик раз в секунду и добавляй к таймштампу единицу да проверяй на 00:00:00. Совпало - ребуть.

Можно вот это поизучать заодно: http://arduino.ru/forum/programmirovanie/nedokumentirovannaya-i-nestandartnaya-sluzhba-vremeni-avr-libc

 
b707
Offline
Зарегистрирован: 26.05.2017

Darkherald - лучше расскажите, зачем это нужно. А то может задачу можно решить совсем по другому

Darkherald
Offline
Зарегистрирован: 30.08.2019

b707 пишет:

Darkherald - лучше расскажите, зачем это нужно. А то может задачу можно решить совсем по другому

Есть задача, при которой необходимо каждую минуту собирать данные и записывать их в память. 

При старте отталкиваемся от Millis и каждые 60000 секунд собираем данные. Но как оказалось Millis неточно считает время, а точнее из-за миллисекунд идет смещение. Через 5 минут время уже смещается на секунду и так далее. Millis срабатывает как надо каждые 60000 секунд, а на самом деле отстает от реального времени. Через сутки порядка 10 минут. 

Поскольку нет внешнего кварца мы не можем решить сдвиг Millis относительно реального времени. Появилось решение сделать перезагрузку ардуины.

 

leks
Offline
Зарегистрирован: 22.10.2017

Какие то фальшивые миллис попались. 10 минут в сутки... Может поправка, вместо 60000- 59999 или 60001 поможет.

b707
Offline
Зарегистрирован: 26.05.2017

Darkherald пишет:

Поскольку нет внешнего кварца мы не можем решить сдвиг Millis относительно реального времени. Появилось решение сделать перезагрузку ардуины.

 Допустим, у вас действительно миллис убегает на 10 минут в сутки (хотя это очень много и похоже на косяк в коде). Но главное - я что-то не пойму, чем тут поможет перезагрузка? Вам нужно корректировать время в ардуине - либо по внешним часам, либо по данным из инета - ну так корректируйте, перегружать-то зачем?

kalapanga
Offline
Зарегистрирован: 23.10.2016

Я правильно понимаю, что через сутки после включения ардуино у Вас где-то в памяти имеются не ожидаемые 1440 измерений, а типа 1430? Если Вы их точно где-то по коду не теряете, то согласен с leks, подобрать правильный интервал - это всё, что Вам нужно.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

 Допустим, у вас действительно миллис убегает на 10 минут в сутки (хотя это очень много и похоже на косяк в коде). 

Не, реально убегает. Мошт, конечно не на 10 минут в сутки, но убегает. Я, когда SoftClock себе делал, думал точности миллиса будет хватать, ан нет, в полночь всё-равно приходилось синхронизироваться.  Это всё из-за прерываний и их запретов. 

Darkherald
Offline
Зарегистрирован: 30.08.2019

leks пишет:

Какие то фальшивые миллис попались. 10 минут в сутки... Может поправка, вместо 60000- 59999 или 60001 поможет.

Смещение не поможет. Время нарастает

leks
Offline
Зарегистрирован: 22.10.2017

Darkherald пишет:

leks пишет:

Какие то фальшивые миллис попались. 10 минут в сутки... Может поправка, вместо 60000- 59999 или 60001 поможет.

Смещение не поможет. Время нарастает

Растёт размер погрешности со временем? Поправка тоже может меняться с ним:)

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

leks
Offline
Зарегистрирован: 22.10.2017

У меня часы с батарейкой за год больше чем на минуту ушли - видать батарейка бракованная:)

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

leks пишет:

У меня часы с батарейкой за год больше чем на минуту ушли - видать батарейка бракованная:)

 

а часы какие? у мня DS3231 китайский за 1.5 года ни на минуту не ушли, время как в смартфоне, стоИт, как Х у пионэра.  Причем, зимой на даче валялись, а там ночью до -52 было. 

leks
Offline
Зарегистрирован: 22.10.2017

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

b707
Offline
Зарегистрирован: 26.05.2017

Darkherald пишет:

Смещение не поможет. Время нарастает

ну ведь бред же написан. неужели самому не очевидно??? :) какая разница - нарастает или отстает - поправка может быть как положительной, так и отрицательной.

Ну и главное вы так и не сказали - перезагрузка зачем?

 

Да, не зря я спросил :) типичная новичковая ситуация - сначала изобрести квадратные колеса. а потом спрашивать у форума, как на них ездить :)

 

 

leks
Offline
Зарегистрирован: 22.10.2017

Глянул,  манипулятор-часы нарисовал время с разницей на компе в 1, потом 2 минуты:) (секунды не рисует). Может ещё момент загрузки пускового времени сыграл роль (на секунды тогда я тоже не смотрел, а было ли отставание уже тогда - не обратил внимания, редактировал скетч усердно).

В общем буду ждать пока батарейка кончится или 2-3 минуты в отставании появятся:)

Darkherald
Offline
Зарегистрирован: 30.08.2019

b707 пишет:

Darkherald пишет:

Смещение не поможет. Время нарастает

ну ведь бред же написан. неужели самому не очевидно??? :) какая разница - нарастает или отстает - поправка может быть как положительной, так и отрицательной.

Ну и главное вы так и не сказали - перезагрузка зачем?

 

Да, не зря я спросил :) типичная новичковая ситуация - сначала изобрести квадратные колеса. а потом спрашивать у форума, как на них ездить :)

 

 

Если точно, то относительно реального времени скачет, а потом отстает.

Перезагрузка сбрасывает Millis.

15:05:57.853 -> 1566302754 (15:05:54)

15:05:59.792 -> Последняя операция в минуте

15:06:57.620 -> 1566302814 (15:06:54)

15:06:59.560 ->Последняя операция в минуте

15:07:57.369 -> 1566302874 (15:07:54)

15:07:59.307 -> Последняя операция в минуте

15:08:57.093 -> 1566302934 (15:08:54)

15:09:58.765 -> Последняя операция в минуте

С лева время порта с права время полученное каждую минуту. Обратите внимания на миллисекунды, 15:05:57.853 последующая должна быть 15:06:57. 620, а должна быть 853, далее 15:07:57.369, а должна быть 853.

Это невозможно поправить смещение запроса, потому как смещение всегда разное, а в итоге отстаёт от реального времени.

b707
Offline
Зарегистрирован: 26.05.2017

Darkherald пишет:

Это невозможно поправить смещение запроса, потому как смещение всегда разное, а в итоге отстаёт от реального времени.

похоже на неправильную работу с прерываниями или с миллис. Может выложите полный код?

Ну и ещ ераз - перезагрузка вам не нужна, поймите это. Вам в любом случае понадобится источник точного времени - либо RTC, либо запрос из инета - и по сигналу этого источника вы просто подводите свой программный счетчик. ничего не перегружая. Если что непонятно - спрашивайте.

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

b707 пишет:

Darkherald пишет:

Это невозможно поправить смещение запроса, потому как смещение всегда разное, а в итоге отстаёт от реального времени.

похоже на неправильную работу с прерываниями или с миллис. Может выложите полный код?

Ну и ещ ераз - перезагрузка вам не нужна, поймите это. Вам в любом случае понадобится источник точного времени - либо RTC, либо запрос из инета - и по сигналу этого источника вы просто подводите свой программный счетчик. ничего не перегружая. Если что непонятно - спрашивайте.

 

Согласен, перезагрузка не нужна, нужна синхронизация времени перед записью данных. 

Если синхронизировать не с чем то ставьте часы, цена вопроса 100-150р DS3231SN с батарейкой 

Но не берите DS3231M (MZ) они не совсем стабильно идут, убегают/отстают сильно.

Logik
Offline
Зарегистрирован: 05.08.2014

перезагрузка даже вредна, бог весть за скока бутлодер разкумарится.

Darkherald
Offline
Зарегистрирован: 30.08.2019

b707 пишет:

похоже на неправильную работу с прерываниями или с миллис. Может выложите полный код?

Вот пример кода

unsigned long timing;
void setup() {
 Serial.begin(115200);
 Serial.println(F("start"));
}
void loop() {
 if (millis() - timing >= 60000)
 {
  timing = millis(); 
  Serial.println ("60 sec");
 }
}
Обратите внимание на миллисекунды за 10 минут
01:12:25.668 -> start ...
01:13:25.678 -> 60 sec
01:14:25.679 -> 60 sec
01:15:25.698 -> 60 sec
01:16:25.698 -> 60 sec
01:17:25.710 -> 60 sec
01:18:25.691 -> 60 sec
01:19:25.694 -> 60 sec
01:20:25.711 -> 60 sec
01:21:25.719 -> 60 sec
01:22:25.720 -> 60 sec
 
Как это скорректировать?
 
 
asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Если а вас есть интернет, то просто корректируйте внутреннее текущее время периодически. Скажем раз в пару часов.

Green
Offline
Зарегистрирован: 01.10.2015

Попробуйте так:

void loop() {
  uint32_t ms = millis();
  if (ms - timing >= 60000) {
     timing = ms; 
     Serial.println ("60 sec");
  }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Вот как раз так и будет ошибка накапливаться, нужно вот так

void loop() {
  if ( millis()- timing >= 60000) {
     timing+ = 60000; 
     Serial.println ("60 sec");
  }
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Вы сейчас соревнуетесь в способе обмана зрения - чтобы в Serial Monitor красивые цифири лезли. Но при сравнении с внешним контрольным измерителем хода времени - миллис всё равно продолжит отставать ))

Darkherald
Offline
Зарегистрирован: 30.08.2019

brokly пишет:

Вот как раз так и будет ошибка накапливаться, нужно вот так

void loop() {
  if ( millis()- timing >= 60000) {
     timing+ = 60000; 
     Serial.println ("60 sec");
  }
}

Ругается на   timing+ = 60000;

b707
Offline
Зарегистрирован: 26.05.2017

Darkherald пишет:

Вот пример кода

 

 я просил выложить ПОЛНЫЙ КОД, чтобы посмотреть, не влияет ли что-нибудь на счетчик в других кусках программы. А этот обрывок мне ни к чему.

b707
Offline
Зарегистрирован: 26.05.2017

brokly пишет:

Вот как раз так и будет ошибка накапливаться, нужно вот так

void loop() {
  if ( millis()- timing >= 60000) {
     timing+ = 60000; 
     Serial.println ("60 sec");
  }
}

 

Брукля. ты что советуешь-то? переполнение миллис? :))

b707
Offline
Зарегистрирован: 26.05.2017

Darkherald пишет:

Обратите внимание на миллисекунды за 10 минут
01:12:25.668 -> start ...
01:13:25.678 -> 60 sec
01:14:25.679 -> 60 sec
01:15:25.698 -> 60 sec
01:16:25.698 -> 60 sec
01:17:25.710 -> 60 sec
01:18:25.691 -> 60 sec
01:19:25.694 -> 60 sec
01:20:25.711 -> 60 sec
01:21:25.719 -> 60 sec
01:22:25.720 -> 60 sec
 
Как это скорректировать?
 
 

Да тут и хрустального шара не надо, чтобы указать на причину. Цикл ЛУП исполняется неравномерно - иногда 1мс, иногда все 30. То есть программа криво написана.

А чтобы понять где именно она тормозит и как исправить - я и просил полный код.

kalapanga
Offline
Зарегистрирован: 23.10.2016

А у нас что, операционная система реального времени какая-то используется, чтобы в мониторе порта время события идеально точно отображалось?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Какое переполнение ? О чем это ? :)
ТС по моему варианту делай. Только размерность переменной правильно определи.

b707
Offline
Зарегистрирован: 26.05.2017

чуть поправленный вариант Брукли

void loop() {
  if ( millis()- timing >= 60000) {
     timing = ( millis()- timing ) -60000; 
     Serial.println ("60 sec");
  }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

b707 пишет:

чуть поправленный вариант Брукли

void loop() {
  if ( millis()- timing >= 60000) {
     timing = ( millis()- timing ) -60000; 
     Serial.println ("60 sec");
  }
}

 


Зачем это ? Чем плохо то что показал я. В твоём примере будет копиться ошибка.

b707
Offline
Зарегистрирован: 26.05.2017

brokly пишет:
Какое переполнение ? О чем это ? :)

да. точно, не будет переполнения. Timing всегда меньше миллис

b707
Offline
Зарегистрирован: 26.05.2017

brokly пишет:
Зачем это ? Чем плохо то что показал я. В твоём примере будет копиться ошибка.

не будет тут копится никакой ошибки - мой пример просто неверный :)

А насчет переполнения я притормозил. да. извиняюсь

b707
Offline
Зарегистрирован: 26.05.2017

Короче, вконец замордовали ТС :)

Darkherald - делайте по варианту Брукли из #25

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Специально поправил для ТС, раз уж он с пробелом справиться не может...

void loop() {
  static uint32_t timing=0;
  while ( millis()- timing >= 60000) {
     timing += 60000; 
     Serial.println ("60 sec");
  }
}

Да и, ТС, подумайте, что будет, если вместо 6000 вписать например 5900, или 6100 ;)

Darkherald
Offline
Зарегистрирован: 30.08.2019

Спасибо что поправили. 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

b707 пишет:

А насчет переполнения я притормозил. да. извиняюсь

Было бы из-за чего... Отпуск раcслабляет :)

Darkherald пишет:

Спасибо что поправили. 

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

Logik
Offline
Зарегистрирован: 05.08.2014

brokly верно в #25 написал.

Но беда у Darkherald в 6мсек за минуту. А это больше чем из за счет такой ошибки. Такая ошибка даст в минуту погрешность порядка времени прокрутки loop-а. А пустой крутится намного быстрей. Очевидно неточность кварца, точней его подобия от китайцев. Это не отменяет, разумеется #25.

Пробуйте timing += 60000-6;

Для часовых интервалов аналогично поправочку. Так можно вогнать в точность, но термостабильность не гарантируется.

b707
Offline
Зарегистрирован: 26.05.2017

Logik пишет:

Такая ошибка даст в минуту погрешность порядка времени прокрутки loop-а. А пустой крутится намного быстрей. Очевидно неточность кварца,

Посмотрите на тайминги - их "мотает" то в плюс то в минус на 30 мс в минуту. Совершенно очевидно, что это не "неточность кварца".

С чего вы взяли, что у ТС пустой Луп? Я вот абсолютно уверен, что это тайминги на рабочем скетче, из которого ТС показывает только этот кусок. Я ему предлагал запостить сюда весь код, чтобы можно было посмотреть, что именно у него тормозит - но код, как всегда у новичков - "секретный"

Logik
Offline
Зарегистрирован: 05.08.2014

//С чего вы взяли, что у ТС пустой Луп? 

в #22 код и его вывод. Несколько неожидано было бы если бы вывод не от того кода.

"мотает" - это особенность ОС, дискретность таймингов процессов в ОС, особенности работы ПО на ПК - пока драйвер выпихнет в буфер, пока ИДЕ получит сообщения. Важна систематическая составляющая.

Тут еще вопрос в пригодности часов ПК как эталона.