Измерить время между 2 входами
Я делаю небольшой проект, и для этого мне нужно измерить время между 2 входами. по сути, это программа для измерения времени, прошедшего с момента, когда цифровой вывод 2 стал высоким, до момента, когда он снова стал высоким.
@Chinar, 👍2
Обсуждение2 ответа
Вы могли бы сделать что-то вроде этого:
unsigned long startTime;
unsigned long elapsedTime;
// Любые необходимые настройки
void setup()
{
...
}
void loop()
{
// Дождитесь, пока вход станет высоким
while(digitalRead(2) == LOW);
// Start timing
startTime = millis();
// Подождите, пока вход станет низким
while(digitalRead(2) == HIGH);
// Теперь подождите, пока он снова поднимется высоко
while(digitalRead(2) == LOW);
// Теперь получим временной интервал
elapsedTime = millis() - startTime;
// Делайте с результатом все, что угодно.
...
}
Имейте в виду, что значение millis() будет переполняться каждые 50 дней или около того. Если вам нужно запускать это непрерывно, вам нужно проверить переполнение и соответствующим образом настроить его.
elapsedTime = millis() - startTime;
даже хорошо работает, когда millis передает 0 при "переполнении". Нечего приспосабливаться., @DataFiddler
Несмотря на работу с millis(), это пример ** блокировки ** из-за операторов while. (Еще хуже, что функция Arduino "pulseIn", которая имеет тайм-аут), @DataFiddler
Я не видел никакого требования делать что-либо, кроме измерения интервала. Поэтому блокирующее решение - это нормально. Зачем все усложнять, если в этом нет необходимости? Как это часто бывает, существует множество возможных решений., @jwh20
Поэтому следует сравнить ваше решение со стандартным пульсированием
., @DataFiddler
Путь зависит от временного диапазона, который будет иметь событие. Фреймворк Arduino уже включает в себя функцию хронометража: millis()
. Он возвращает количество миллисекунд с момента запуска (очень похоже на часы) и измеряет время с помощью аппаратного таймера 0 и его прерываний. Эта функция будет хорошо работать в 2-значном миллисекундном диапазоне и выше. С одноразрядной миллисекундой или микросекундным доменом вы должны вместо этого использовать micros()
с аналогичными работами, но возвращает микросекунды с момента запуска. Для диапазона низких микросекунд и ниже вам нужно будет работать непосредственно с выделенным аппаратным таймером, настраивая его через свои аппаратные регистры.
Здесь я бы показал принцип millis()
/micros()
, так как это, скорее всего, то, что вам нужно. В дальнейшем я напишу только millis()
, но все вычисления также можно сделать с помощью micros()
. Единственное различие для расчетов - это коэффициент 1000 между миллисекундами и микросекундами.
Когда вы смотрите на часы и хотите измерить разницу во времени, вы записываете время начала и время окончания. Затем вы вычисляете разницу, чтобы получить продолжительность события. Вы можете сделать то же самое с millis()
:
unsigned long starttime = millis(); // обратите внимание на время начала
// здесь событие для измерения
unsigned long endtime = millis(); // обратите внимание на время окончания
unsigned long duration = endtime - starttime; // продолжительность события в мс
Поэтому в вашем коде вам нужно проверить наличие восходящего фронта вашего сигнала. На каждом восходящем фронте вы вычисляете разницу во времени между последней меткой времени и текущим временем. Затем вы сбрасываете метку времени. Что-то вроде этого:
int last_input_state = LOW;
unsigned long timestamp;
// настройка здесь
void loop(){
int current_input_state = digitalRead(2); // получить текущий уровень сигнала
if(current_input_state && !last_input_state){ //проверьте, если сигнал сейчас высокий и был низким до
unsigned long current_time = millis(); // обратите внимание на текущее время
unsigned long duration = current_time - timestamp; // вычислить длительность и что-то с ней
timestamp = current_time; // обновить метку времени текущим временем
}
last_input_state = current_input_state; // обновите последнее входное состояние новым измеренным
}
Примечание:
- Этот код не блокируется. Он должен работать быстро и непрерывно, чтобы работать правильно. Вы не можете делать длинные блокирующие вещи в остальной части вашего кода, например, использовать вызовы high
delay()
, но вы не должны делать этого в любом случае, так как это заблокирует что-либо. - Вы можете пойти еще дальше, чтобы снять вес с вашего процессора, и использовать прерывание, чтобы ощутить растущее преимущество. Вы можете использовать
attachInterrupt(digitalPinToInterrupt(pin), service_function, RISING);
и предоставитьvoid service_function()
, который выполняет измерение и вычисление метки времени (в основном тот же код, что и в операторе if приведенного выше кода).
- Как справиться с rollover millis()?
- Как получить текущее время и дату в Arduino без внешнего источника?
- Преобразование в Unix Timestamp и обратно
- Как запустить цикл на определенное время?
- Почему мои часы реального времени показывают неверное время с моего ПК?
- Разница между «time_t» и «DateTime»
- Чтение из Serial
- Точность часов времени Arduino
Вы видели функцию
millis()
и измерение времени в примереBlinkWithoutDelay
? В Интернете есть много руководств поmillis()
, @chrisl