Ардуинщики всех стран - объединяйтесь! В этом форуме, конечно.
Ответить

Время от запуска

Пт фев 04, 2022 17:59:36

Есть код выводящий приблизительное время от запуска:

Serial.println(String(floor(millis()/86400000),0) + "d " + String(floor((millis()%86400000)/3600000.0),0) + "h " + String(floor((millis()%3600000)/60000.0),0) + "m " + String(floor((millis()%60000)/1000.0),0) + "s " + millis()%1000 + "ms.");

Он прекрасно отрабатывает первые 49,7 дней, а вот потом... Допустим я могу отлавливать время когда millis начинает считать с нуля, но вот как высчитать время от старта зная сколько раз millis стартовал заново и значение текущего millis?
Вроде бы задача простая, но в голову не приходит ничего стоящего... Помогите кто может советом.

Re: Время от запуска

Пт фев 04, 2022 18:20:39

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


Код:
if(millis()>=4294967200){
Count+=1;
if(Count>1){
RealMillis=millis()+(4294967200*Count)
}else{
RealMillis=millis();}
delay(100);
}



Переменная естественно должна быть uint64_t чтобы результат влез

Re: Время от запуска

Пн фев 07, 2022 15:08:16

Ужасный код. И уйма ненужных вычислений (особенно жгут глаза флоаты, которых у 8-битной аврки просто нет!).
Ну заведи ты отдельную структуру вроде такой
Код:
struct{
   int days;
   int hours;
   int minutes;
   int seconds;
} gonefromstart;

Теперь в прерывании системного таймера, считающего миллисекунды, каждый раз, как миллисекунды достигли 1000, обращаешь этот счетчик в нуль и инкрементируешь gonefromstart.seconds. Если он равен 60 — обнуляешь его и инкрементируешь minutes. Ну и так далее.
Если тебе еще и годы захочется считать, придется проверять, когда days будет равен 365, чтобы ровно на 365.2422 суток все обнулить и инкрементировать years.

Re: Время от запуска

Пн фев 07, 2022 15:42:47

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


Код:
if(millis()>=4294967200){
Count+=1;
if(Count>1){
RealMillis=millis()+(4294967200*Count)
}else{
RealMillis=millis();}
delay(100);
}



Переменная естественно должна быть uint64_t чтобы результат влез


Спасибо за совет. Счётчик был и так, uni64_t на прямую не инициализировал, но благодаря вашему совету в голову пришло:
Код:
if (fromLoading == 0)
    {
      if (altmillis < millis())
      {
        Serial.println(String(floor(millis()/86400000),0) + "d " + String(floor((millis()%86400000)/3600000.0),0) + "h " + String(floor((millis()%3600000)/60000.0),0) + "m " + String(floor((millis()%60000)/1000.0),0) + "s " + millis()%1000 + "ms.");
      }
      else
      {
        Serial.println(String(floor((4294967296 + millis())/86400000),0) + "d " + String(floor(((4294967296 + millis())%86400000)/3600000.0),0) + "h " + String(floor(((4294967296 + millis())%3600000)/60000.0),0) + "m.");
      }
     
    }
    else
    {
      if (altmillis < millis())
      {
        Serial.println(String(floor((4294967296 * fromLoading + millis())/86400000),0) + "d " + String(floor(((4294967296 * fromLoading + millis())%86400000)/3600000.0),0) + "h " + String(floor(((4294967296 * fromLoading + millis())%3600000)/60000.0),0) + "m");
      }
      else
      {
        Serial.println(String(floor((4294967296 * (fromLoading + 1) + millis())/86400000),0) + "d " + String(floor(((4294967296 * (fromLoading + 1) + millis())%86400000)/3600000.0),0) + "h " + String(floor(((4294967296 * (fromLoading + 1) + millis())%3600000)/60000.0),0) + "m.");
      }
     
    }


Код:
  if (millis() - altmillis > 600000)
  {
    if (altmillis > millis())
    {
      fromLoading++;
    }
    altmillis = millis();
  }

altmillis используется и для подсчёта сколько раз обнулялся millis и для коррекции вывода в тот промежуток пока мы этот переход не зафиксировали.

Добавлено after 2 minutes 18 seconds:
Ужасный код. И уйма ненужных вычислений (особенно жгут глаза флоаты, которых у 8-битной аврки просто нет!).
Ну заведи ты отдельную структуру вроде такой
Код:
struct{
   int days;
   int hours;
   int minutes;
   int seconds;
} gonefromstart;

Теперь в прерывании системного таймера, считающего миллисекунды, каждый раз, как миллисекунды достигли 1000, обращаешь этот счетчик в нуль и инкрементируешь gonefromstart.seconds. Если он равен 60 — обнуляешь его и инкрементируешь minutes. Ну и так далее.
Если тебе еще и годы захочется считать, придется проверять, когда days будет равен 365, чтобы ровно на 365.2422 суток все обнулить и инкрементировать years.

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

Добавлено after 7 minutes 17 seconds:
Да int в этой структуре явно лишний для всего, кроме дней...

Re: Время от запуска

Пн фев 07, 2022 15:49:33

Ну так если понимаешь, где проблема, сделай нормально! Без флоатов. Без всяких "стрингов" и "принтфов".
Да, секунды, минуты и часы будут uint8_t, а дни можно сделать uint16_t, все равно железяка никогда дольше 65536 суток не сможет "на одном дыхании" проработать! Учитывая то, что это - 179 лет, запас, мягко говоря, чрезмерный. Скорей всего, за глаза и для дней хватит uint8_t.

И да, ТС, если тебе говорят, что у тебя - отстойный быдлокод, взгляни на свой высер лишний раз! Это - не просто отстойный быдлокод, за такой надо бить по башке учебником K&R, покуда мозг не заработает в нужную сторону!

Re: Время от запуска

Пн фев 07, 2022 16:17:35

YuM писал(а):Вот не понимаю зачем забивать память ради того чтобы ускорить работу сегмента кода, который будет исполнятся раз в полгода? А в вашем варианте лишние данные и лишние операции...
Решение Eddy_Em практически идеально. Если считаете, что подобное решение сожрёт память, то посчитаете сколько съест Ваше, с этими ужасными делениями и громадными числами.

Re: Время от запуска

Пн фев 07, 2022 16:48:58

Можно разве что добавить использование дополнительного прерывания на основе TIMER0_COMPA_vect если используется мега168/328...
Не касаясь системного таймера (псевдопараллельный процесс на неиспользуемой части Т0)
:roll:

Re: Время от запуска

Пн фев 07, 2022 16:57:42

YuM писал(а):Вот не понимаю зачем забивать память ради того чтобы ускорить работу сегмента кода, который будет исполнятся раз в полгода? А в вашем варианте лишние данные и лишние операции...
Решение Eddy_Em практически идеально. Если считаете, что подобное решение сожрёт память, то посчитаете сколько съест Ваше, с этими ужасными делениями и громадными числами.

Моё решение сколько сожрёт памяти столько, сколько освободит после окончания отработки функции, а решение ругающегося человека требует выделить память на постоянной основе...
Для моей задачи, когда требуется вывод информации о времени работы, только когда было подозрение на перезагрузку устройства, что не должно происходить неделями, если не месяцами. При такой задаче, когда код будет выполнятся неимоверно редко, нет необходимости хранить не нужных данных, и тем более нет особого смысла оптимизировать конкретно данной функции. Если мне бы требовалось точное время, я бы использовал другие способы. Если бы мне требовалось не точное время, но постоянно, тогда да предложенное решение имеет смысл, но вот беда - требуется то совсем другое: ответить на запрос пользователя, если ему когда либо придёт в голову получить данную информацию. В данном контексте предложенное решение ругающегося человека - это как хранить в памяти компьютера каждый построенный видеокартой кадр, на тот случай, если пользователь нажмёт prt sc...

Re: Время от запуска

Пн фев 07, 2022 17:31:13

Требование экономии ОЗУ в течение какого-то периода должно было быть озвучено. Сравнение мк с обычным компьютером некорректно.
А вообще, с таким подходом к оптимизации, памяти и стилю вероятность ошибок повышается. И мне кажется странным экономия нескольких байт в озу при наплевательском отношение к пзу. Хотя, конечно, такая задача может иметь место быть, но всё-таки непривычно.

Re: Время от запуска

Пн фев 07, 2022 17:51:34

Как можно с таким абдуринством, как флоаты и "стринги", говорить что-то об экономии памяти?
Советую прикинуть на досуге, сколько памяти отожрет работа с флоатами на МК, где флоатов нет! Тут иной раз стараешься на STM32F0 деление на умножение и сдвиги заменить, т.к. деления даже целочисленного у них нет, а ТС флоаты сует… Да еще и uint64_t!!!

Ты посчитай: тебе понадобится 4 байта для хранения секунд, минут, часов и суток. Плюс два байта для хранения миллисекунд. Ну и сравни теперь это со своей uint64_t!

Re: Время от запуска

Пн фев 07, 2022 18:03:54

Требование экономии ОЗУ в течение какого-то периода должно было быть озвучено. Сравнение мк с обычным компьютером некорректно.
А вообще, с таким подходом к оптимизации, памяти и стилю вероятность ошибок повышается. И мне кажется странным экономия нескольких байт в озу при наплевательском отношение к пзу. Хотя, конечно, такая задача может иметь место быть, но всё-таки непривычно.

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

Я больше не люблю заставлять что-то лишнее делать процессор в основном цикле, если необходимости в этом нет...

И да: самое важное Serial, не смотря на том что в примере кода здесь есть, на самом деле там своя функция и данные уходят в сеть и лог в озу (к сожалению такое требование). Со String - это здоровый минус мне, но поскольку данная библиотека вне зависимости от моего желания пока остаётся подключённой к проекту, то я пока не вижу смысла не использовать её в данной функции. Но в планах избавиться в принципе от этой библиотеки, так же как и написать миниинтерпритатор для перевода всех констант в дефайны и все функций, что используются в коде по разу, перед компиляцией автоматически удалять, запихивая их в тело программы....

Добавлено after 3 minutes 32 seconds:
Как можно с таким абдуринством, как флоаты и "стринги", говорить что-то об экономии памяти?
Советую прикинуть на досуге, сколько памяти отожрет работа с флоатами на МК, где флоатов нет! Тут иной раз стараешься на STM32F0 деление на умножение и сдвиги заменить, т.к. деления даже целочисленного у них нет, а ТС флоаты сует… Да еще и uint64_t!!!

Ты посчитай: тебе понадобится 4 байта для хранения секунд, минут, часов и суток. Плюс два байта для хранения миллисекунд. Ну и сравни теперь это со своей uint64_t!

uint64_t выделилась в памяти один раз в месяц и убралась от туда... Или вы всё всегда в глобальные переменные суёте? Не удивительно тогда что вы так из-за флоат разнервничались...

Re: Время от запуска

Пн фев 07, 2022 18:37:17

uint64_t выделилась в памяти один раз в месяц и убралась оттуда...

Да ладно? А счетчик тиков (millis) тогда какой???
Не надо мне тут мозг пудрить!

Re: Время от запуска

Пн фев 07, 2022 18:48:51

YuM, при таком большом периоде измерения как у Вас с точным временем? Из моих наблюдений и експериментах: часы на Arduino Nano со встроенным керамическим резонатором 16 MHz (для теста только) отстает примерно на 28 секунд в сутки. За 50 дней могу только догадываться: 50 * 28 = 1400 секунд (без всяких возможных перепадов температур и их дополнительных воздействий). Не меняли опорный генератор хотя бы на настоящий кварц (или TCXO?), или время: из Real Time Clock ИС?, или точность времени не имеет значения? Потому что, если это по последний способ (с RTC), расчет времени определяется более простым способом (с точки зрения типов данных).
Ответить