Как Сбросить millis()

lalapta100
Offline
Зарегистрирован: 01.01.2014

возникла необходимость самостоятельно сбрасывать таймер millis()

это возможно???

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

почему нет? кнопка ресет сломалась?

leshak
Offline
Зарегистрирован: 29.09.2011

1. Безопастно и гарантированно не имея побочных эффектов - никак.
2. На форуме, вверхну справа, есть поиск - тема обсуждалась. Например: millis(); Как при нажатии на кнопку, его обнулить?! | Аппаратная платформа Arduino . Думаю еще не одну найти можно...
3. Объективных причин для подобной "необходимости" - не существует. Если "нужно" - значит код выстроен не верно. Привязка к абсолютным значением millis() допустима только если сама задача стоит "через xxx миллисекунд после подачи питания или ресета, нужно..." (но тогда опять-таки обнулять millis() не нужно, ответ Puhlyaviy-го очевиден). Во всех остальных случах использование абсолютных значений - архитектурная ошибка.

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

По аналогии:

У вас есть часы или время в телефоне.

Как часто вы сбрасываете время в часах или  в телефоне и с какой целью. Расскажите мне за чем это время вам нужно?

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Поддерживаю. Если Вам нужно что-то сделать через 1 час, Вы ж не сбрасываете часы на ноль, и в 1:00:00 делаете это?

Объявие две глобальные четырёхбайтные переменные. Одну инициализируйте текущим значением millis(); вторую в нужное вам время. Их разность и будет иметь величину от нуля.  

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

мои часы отстают в сутки на 47 секунд..... Как в Гринвиче каждые сутки притормозить всемирное координированное время на туже величину ?

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

SU-27-16 пишет:

мои часы отстают в сутки на 47 секунд..... Как в Гринвиче каждые сутки притормозить всемирное координированное время на туже величину ?

Это же очень просто - прибавлять к каждой минуте/часу константу.

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

Но лучше всего часы постоянно корректировать от GPS/NTP

std
Offline
Зарегистрирован: 05.01.2012
#include <avr\wdt.h>

void setup(){
  // >> Your setup code here <<
  wdt_enable(WDTO_2S);      // watchdog timer
}

void loop(){
  // >> Your duty cycle code here <<
  if(millis()>=4294950000){           // auto reset cycle
    delay(10000);
  }
  wdt_reset();
}

 

renoshnik
Offline
Зарегистрирован: 11.04.2013

std пишет:



#include <avr\wdt.h>

void setup(){
  // >> Your setup code here <<
  wdt_enable(WDTO_2S);      // watchdog timer
}

void loop(){
  // >> Your duty cycle code here <<
  if(millis()>=4294950000){           // auto reset cycle
    delay(10000);
  }
  wdt_reset();
}

 

 

а, зачем это если в "букваре" написано - " Это количество сбрасывается на ноль, в следствие переполнения значения, приблизительно через 50 дней "

leshak
Offline
Зарегистрирован: 29.09.2011

std пишет:

#include <avr\wdt.h>

void setup(){
  // >> Your setup code here <<
  wdt_enable(WDTO_2S);      // watchdog timer
}

void loop(){
  // >> Your duty cycle code here <<
  if(millis()>=4294950000){           // auto reset cycle
    delay(10000);
  }
  wdt_reset();
}

 

Молодца. Теперь с 50% вероятностью ждем "помогите, дуина пишет not in sync resp=... и скетчи не заливаются".

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

sav13 пишет:

SU-27-16 пишет:

мои часы отстают в сутки на 47 секунд..... Как в Гринвиче каждые сутки притормозить всемирное координированное время на туже величину ?

Это же очень просто - прибавлять к каждой минуте/часу константу.

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

Но лучше всего часы постоянно корректировать от GPS/NTP

:)   :)   :) ...часы механические, старенькие, не хочется их лишний раз переводить - пусть уж Гринвич переводят ! ( millis() ) :)

leshak
Offline
Зарегистрирован: 29.09.2011

SU-27-16 пишет:

Но лучше всего часы постоянно корректировать от GPS/NTP

Шаговиком?

 

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

leshak пишет:
Молодца. Теперь с 50% вероятностью ждем "помогите, дуина пишет not in sync resp=... и скетчи не заливаются".

А, ну да. Яж привык что делаю всё на отдельной плате в меге с квадратным корпусом, и туда программа отправляется по ICSP. А при таком способе бажного загрузчика (который впадает в ступор от срабатывания watchdog) нету.

Ну тогда аффтар, разочарую. Никак.

Или меняем загрузчик на optiboot.

leshak
Offline
Зарегистрирован: 29.09.2011

std пишет:

Ну тогда аффтар, разочарую. Никак.

Или меняем загрузчик на optiboot.

Вопрос на засыпку: а все остальные переменные, направление и состояние входов/выходов тоже сохраниться? А если скажем какой-то шилд установлен. Которому после подачи питания нужно init() сделать ОДИН РАЗ? 

Так что не "меняем загрузчик", а "это нафиг не нужно". 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

как тема разрослась-то.... без автора, правда... A ХОТЕЛОСЬ БЫ УЗНАТЬ - ЗАЧЕМ точку отсчёта по времени назначать новую = "обнулять когда Я хочу" ?

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

Точно не нужно? Прям точно точно? Я просто в этом месте не очень понимаю. Объясните, если не затруднит.

Рассмотрим поведение программы за X-n мс до переполнения millis(), если нужно отмерить интервал в X мс. Предположим, X=5000, n=300, тогда началом интервала будет FFFFFFFF-(5000-300)=4294967295-4700=4294962595. Сохраним метку времени T: millis()=4294962595. Через 4701 мс millis() будет равно 0, т. е. наступит переполнение. Остаётся 299 мс, через которые условие должно сработать. Условие у нас записано как if(millis()-T>=X), где T - метка. Имеем X-T=5000-4294967295=-4294962295Внимание вопрос: будет ли 4294962595 равно 299? Если да - то да, можно этот костыль с перезагрузкой не делать.

leshak пишет:
какой-то шилд установлен. Которому после подачи питания нужно init() сделать ОДИН РАЗ?

А вот от этого уже хромает надёжность. То есть у нас получается - какой-то форс-мажор, повисло где, ну с кем не бывает. Watchdog сработал. И тут шилд залип, потому что видите ли дважды инициализировался. Да гнать такие шилды из системы ссаными тряпками. Или отводить один из выводов под спец сброс всей периферии кроме дуины, в setup() делать на нём ноль, потом 1, пару секунд ждать - и только затем инициализировать.

leshak
Offline
Зарегистрирован: 29.09.2011

std пишет:

как if(millis()-T>=X), где T - метка. Имеем X-T=5000-4294967295=-4294962295Внимание вопрос: будет ли 4294962595 равно 299? Если да - то да, можно этот костыль с перезагрузкой не делать.

Да. Будет. Костыль можно не делать.

>То есть у нас получается - какой-то форс-мажор, повисло где, ну с кем не бывает. Watchdog сработал.

Если у нас предусмотрен вачдог именно как вачдог. Защита от форс-мажоро, то логично, что после перезагрузки будет предсумотрена и процедура воставновления. Проверка того, а был ли уже инит (да, да, при желании можно выяснить это подача питания или перезагрузка по вачдогу), будет возможность в железе передернуть питание шилду.... и т.д. и т.п. Это когда это НУЖНО.

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

А сказать "гнать сцаными тряпками" - это конечно можно. Сказать. Да вот только когда в даташите написанно что "вот так нужно инициализировать".... и альтернативной микрухи нема. Что будете делать? Шилд выгнали, а работать кто будет?

Или, скажем у вас уже сделанно 90% работы. И тут вы захотели, вдруг, миллис сбросить. Из-за этого все переделывать на другую микруху?  Разбираться заново и т.д. и т.п.

Или когда вам захотелось рестенуть, вы данные принимали по блютусу... заново коннектится? Пейрить девайсы?

Да в конце концов. Вы что хотите сказать что это нормально, когда какому-то кусочку логики, что-то потребовалось и он, по этому поводу, взял да и "рубанул все". Где же принцип несвязности кода?

Мне вот инетерестно, что-бы вы сказали, если бы у вас на PC какая-нибудь программа/напоминалка, выдавала напоминание, а потом ребутала машину (причем жестко). Что-бы вы сказали об авторе подобного чуда?

 

leshak
Offline
Зарегистрирован: 29.09.2011

Гы... подумалось.

Кстати, скажем если этот таймер нужно запускать "по кнопке". То как тогда избежать что-бы он не срабатывал от просто включения питания, а действительно ЖДАЛ первого нажатия? EEPROM? Внешняя обвязка? А если нужно два таймера?

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

Эмм, а как выяснить, перезагрузилось ли само по сторожевому таймеру, либо загрузилось при включении? i2c RAM память?

toc
Offline
Зарегистрирован: 09.02.2013

std,
в даташите ищите MCUSR
>> Bit 0 – PORF: Power-on Reset Flag
This bit is set if a Power-on Reset occurs.

Но говорят, что достать информацию не просто.

hugoboss317
Offline
Зарегистрирован: 21.03.2013

leshak пишет:

 Объективных причин для подобной "необходимости" - не существует. Если "нужно" - значит код выстроен не верно. Привязка к абсолютным значением millis() допустима только если сама задача стоит "через xxx миллисекунд после подачи питания или ресета, нужно..." (но тогда опять-таки обнулять millis() не нужно, ответ Puhlyaviy-го очевиден). Во всех остальных случах использование абсолютных значений - архитектурная ошибка.

Я бы на этом остановился. И при переполнении значений millis() не нужно изобретать ЛИСАПЕТ.А где автор? 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

есть система отсчёта дат... была "проблема" 2000-го года.... Щас опять про тоже ? ...в более мелком масштабе ?

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

std пишет:

Эмм, а как выяснить, перезагрузилось ли само по сторожевому таймеру, либо загрузилось при включении? i2c RAM память?


Я таки удивлен... а мысль что бы вачдог прежде того что бы дернуть ресет оставил записку во флеше? Не?

leshak
Offline
Зарегистрирован: 29.09.2011

Puhlyaviy пишет:
std пишет:

Эмм, а как выяснить, перезагрузилось ли само по сторожевому таймеру, либо загрузилось при включении? i2c RAM память?

Я таки удивлен... а мысль что бы вачдог прежде того что бы дернуть ресет оставил записку во флеше? Не?

Ну что вы. Куда уж нам до такого додуматься. Слово EEPROM выше было написанно случайно. В виде очепятки.

skyspirit
Offline
Зарегистрирован: 27.02.2015

Так все таки есть какой то вариант чтоб milis запускалось только по нажатии определенной кнопки? у меня задача сделать устройство что при нажатии(или разжатии кнопки) ардуина отсчитывала заданное время и включало определенный механизм, может таймер какой то применять подскажите варианты?

Клапауций 322
Offline
Зарегистрирован: 31.12.2015
49 // что-то сделать один раз по условию и по истечении времени интервала - генератор в одновибратор.
50 if (условие) {nD_01.start();}
51 if (nD_01.push_tick) {nD_01.stop(); код чего-то;}

класс титановый велосипед для delay без delay().

класс титановый велосипед для тактовой кнопки.

skyspirit
Offline
Зарегистрирован: 27.02.2015

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

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

skyspirit пишет:

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

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

если что-то более расширенное, то цепляешь + класс титановый велосипед для delay без delay(). и делаешь одно событие через заданный интервал.

at0mix
at0mix аватар
Offline
Зарегистрирован: 23.11.2015

skyspirit пишет:

Так все таки есть какой то вариант чтоб milis запускалось только по нажатии определенной кнопки? у меня задача сделать устройство что при нажатии(или разжатии кнопки) ардуина отсчитывала заданное время и включало определенный механизм, может таймер какой то применять подскажите варианты?

Я устал повторять - для того чтобы получить ПРАВИЛЬНЫЙ ответ - нужно задать ПРАВИЛЬНЫЙ вопрос!

1.Тебе надо ИМЕННО миллис?

2. Тебе надо таймаут более 50 часов?

Без контекста - купи платку точного времени типа такой

http://ru.aliexpress.com/item/2pcs-lot-DS3231-AT24C32-IIC-Module-Precision-Clock-Module-for-Arduino-Free-Shipping/1509551405.html

 DS3231 AT24C32 IIC Module Precision Clock Module, 50-60 руб цена вопроса.

поставь туда батарейку и читай себе точное время и соответственно разницу по времени.

Мне например нужно для реквизита таймаут до 16 часов - что совершенно меньше 50 часов миллса....

 
hugoboss317
Offline
Зарегистрирован: 21.03.2013

skyspirit пишет:

Так все таки есть какой то вариант чтоб milis запускалось только по нажатии определенной кнопки?

Кончечно, причём аппаратный. Нужно кнопкой подать минус на RESET pin :)

skyspirit
Offline
Зарегистрирован: 27.02.2015

hugoboss317 пишет:

skyspirit пишет:

Так все таки есть какой то вариант чтоб milis запускалось только по нажатии определенной кнопки?

Кончечно, причём аппаратный. Нужно кнопкой подать минус на RESET pin :)

Благодарю :) я какраз путем проб и ошибок пришел к этому

magstar
Offline
Зарегистрирован: 13.01.2016

Доброго времени суток! А как, например измерить время между подачей питания на одну ногу и подачей питания на другую? И не сбрасывать при этом миллис?

 

hugoboss317
Offline
Зарегистрирован: 21.03.2013
uint32_t val_1, val_2, data; 

if(одна нога == HIGH){
val_1 = millis();
}
if(вторая нога == HIGH){
val_2 = millis();
data = val_2 - val_1; // время в тысячных секундах
}

 

bad_user
Offline
Зарегистрирован: 13.11.2015

Столкнулся с необходимостью обнулять счетчик количества срабатываний датчика через указанное время, к примеру 30 сек. использую для этого:

if (millis() - previousMillis > INTERVAL)
  {
      previousMillis = millis();
      count = 0;
  }

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

Сработает ли условие в таком виде: 

if ( (millis() - previousMillis > INTERVAL)  || (millis() - previousMillis < 0) )
  {
      previousMillis = millis();   
      count = 0;
  }

 

hugoboss317
Offline
Зарегистрирован: 21.03.2013

А меньше нуля видиме не получится, значение беззнаковое.

У Вас интервал 30 сек, это 30 000 микросек. Просто укажите условие если millis() меньше 30 000...., а дальше приравнивайте millis(); 

Ничего страшного не случится если раз в месяц прочитаются данные не через 30 а через 50 секунд

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015
millis() - previousMillis < 0
никогда не будет меньше нуля:)

 

magstar
Offline
Зарегистрирован: 13.01.2016

30 сек это 30 000 000 микросек или 30 000 милисек.

bad_user
Offline
Зарегистрирован: 13.11.2015

Valera19701 пишет:

millis() - previousMillis < 0
никогда не будет меньше нуля:)

Можете объяснить почему?

как я понимаю:

if (millis()  - previousMillis < 0 ) результат вычетания. и перед переполнением, previousMillis будет равнятся скажем,  4 294 967 290, а millis после переполнения = 1000 в этом случае millis()  - previousMillis как раз будет меньше нуля.

hugoboss317 пишет:

А меньше нуля видиме не получится, значение беззнаковое.

нет возможности сейчас в ардуино скетч залить, вечером попробую, но почему-то мне кажется, что результат вычетания millis()  - previousMillis в операторе if без присвоения его переменной может быть отрицательным. или я ошибаюсь?

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Потому что у unsigned long нет ни единого битика для хранения знака числа. То бишь "по определению". :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Да, ответ на вопрос в названии темы (почему-то так никто его и не дал):

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

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

залейте этот скетч и вопросы отпадут

unsigned long previousMillis = - 1000;
unsigned long interval = 30000;
void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.print("previousMillis ");
  Serial.print(previousMillis);
  Serial.print(" interval ");
  Serial.println(interval);
  if (millis() - previousMillis > interval) {
    previousMillis = millis();
  }
}

а вот более наглядно

unsigned long previousMillis = - 1000;
unsigned long interval = 10000;
void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.print("Millis ");
  Serial.print(millis());
  Serial.print(" PreviousMillis ");
  Serial.print(previousMillis);
  Serial.print(" Interval ");
  Serial.print(interval);
  Serial.print(" Minus ");
  Serial.println(millis() - previousMillis);
  if (millis() - previousMillis > interval) {
    previousMillis = millis();
  }
}

 

bad_user
Offline
Зарегистрирован: 13.11.2015

немного не такой скетч нужно залить =)

все дело в том, что previousMillis никогда не станет отрицательным числом.

отрицательным будет результат вычитания millis() - previousMillis в случае, когда previousMillis будет больше, чем millis(). 

мне кажется нужно проверить так:

unsigned long previousMillis = 10000;
    void setup() {
          Serial.begin(9600);
        }
    void loop() {
     if (millis() - previousMillis < 0) {
    Serial.print("it Works");
    Serial.print(previousMillis);
    }else{
    previousMillis = millis();
    Serial.print(previousMillis);
    }
}

если монитор порта первые 10 секунд будет писать "it Works"  знач все получится =) вечером проверю.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Результат вычитания двух беззнаковых целых есть беззнаковое число и тоже целое.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

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

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

отрицательное беззнаковое число 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

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

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

не послал

и попробуйте в этом скетче задать положительное значение previousMillis , пусть будет 10000 , что получите?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

Kisoft и Arhat109-2, я думаю вам надо залить этот скетч и попробовать задать значение переменной previousMillis = 10000, я думаю после этого вы полезете в wirring искать, почему при при вычитании из функции millis() не задается переменная previousMillis

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Зря не послал. Кривой компилятор или слишком добрый. :)

То, что он вам запихнул знаковое в беззнаковое - весьма пичалька. И это ни коим разом не отменяет кривости примеру. Почему вычитание двух беззнаковых чиселок работает верно - тут было объяснение и не единожды, лично мне - лень повторятся, но суть в том, что когда вы вычитаете из меньшего большее, то происходит "заем" (переполнение наоборот) из старших разрядов, в т.ч. и "за" разрядной сеткой. Раз нет знака - стало быть получить отрицательное число нельзя "в принципе", поэтому факт заема - игнорируется в сравнении.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

это понятно, я не об этом, а о том почему не присваивается значение переменной в связке с millis()?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Условие не выполняется, вот и не изменяется .. у вас же выводится результат вычитания, что там непонятно?