Измерить время между 2 входами

time input

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

, 👍2

Обсуждение

Вы видели функцию millis() и измерение времени в примере BlinkWithoutDelay? В Интернете есть много руководств по millis(), @chrisl


2 ответа


1

Вы могли бы сделать что-то вроде этого:

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


3

Путь зависит от временного диапазона, который будет иметь событие. Фреймворк 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 приведенного выше кода).
,