Есть одна важная вещь, которую вы должны помнить, работая со временем на Arudino любой формы:
- Каждая операция требует времени.
Ваша функция foo () займет некоторое время. Что это за время, мы не можем сказать.
Самый надежный способ справиться со временем - полагаться только на время запуска, а не на выработку следующего запуска.
Например, возьмите следующее:
if (millis() - last > interval) {
doSomething();
last = millis();
}
Переменная last
будет временем, когда подпрограмма сработала * плюс время, doSomething
затраченное на выполнение. Так, скажем interval
, 100, и doSomething
для запуска требуется 10 мс, вы получите срабатывание при 101 мс, 212 мс, 323 мс и т. Д. Не те 100 мс, которые вы ожидали.
Поэтому вы можете всегда использовать одно и то же время независимо от запоминания определенного момента (как предлагает Джурадж):
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
Теперь время, которое doSomething()
уходит, ни на что не повлияет. Таким образом, вы получите срабатывание при 101 мс, 202 мс, 303 мс и т. Д. Все еще не совсем те 100 мс, которые вы хотели - потому что вы ищете более 100 мс пройденных - и это означает 101 мс или более. Вместо этого вы должны использовать >=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
Теперь, предполагая, что в вашем цикле больше ничего не происходит, вы получаете срабатывание на 100 мс, 200 мс, 300 мс и т. Д. Но обратите внимание на этот бит: «пока в вашем цикле больше ничего не происходит» ...
Что произойдет, если операция, которая занимает 5 мс, происходит при 99 мс ...? Ваш следующий запуск будет отложен до 104 мс. Это дрейф. Но с этим легко бороться. Вместо того чтобы сказать «записанное время сейчас», вы говорите «записанное время на 100 мс позже, чем было». Это означает, что независимо от того, какие задержки вы получаете в своем коде, ваш запуск всегда будет происходить с интервалами в 100 мс или дрейфом в пределах 100 мсек.
if (millis() - last >= interval) {
doSomething();
last += interval;
}
Теперь вы получите срабатывание при 100 мс, 200 мс, 300 мс и т. Д. Или, если есть задержки в других битах кода, вы можете получить 100 мс, 204 мс, 300 мс, 408 мс, 503 мс, 600 мс и т. Д. Он всегда пытается запустить его как можно ближе к интервал, насколько это возможно, независимо от задержек. И если у вас есть задержки, превышающие интервал, он автоматически запустит вашу обычную программу достаточно времени, чтобы догнать текущее время.
До того, как вы дрейфовали . Теперь у вас есть дрожание .