pulseInLong()
pulseInLong() измеряет длительность импульса в микросекундах через micros() и лучше подходит для длинных сигналов, чем обычный pulseIn().
Полная статья
Описание
pulseInLong() решает ту же задачу, что и pulseIn(): измеряет, сколько времени вывод находится в заданном состоянии. Разница в том, что эта функция опирается на micros() вместо прямого подсчёта тактов процессора, поэтому она точнее работает на длинных импульсах и не теряет счёт, когда в программе активно срабатывают прерывания.
Принцип работы прост. Допустим, вы вызвали функцию с параметром value равным HIGH. Функция сначала ждёт, пока вывод окажется в состоянии LOW (то есть дожидается конца предыдущего импульса, если он ещё идёт), затем фиксирует момент перехода в LOW и замеряет, сколько времени вывод остаётся в этом состоянии. Как только вывод возвращается в LOW, измерение заканчивается и функция возвращает длительность в микросекундах. Если за отведённое время полный импульс так и не пришёл — возвращается 0.
Функция уверенно работает с импульсами длительностью от 10 микросекунд до 3 минут. На очень коротких импульсах точность ниже: временны́е характеристики определены экспериментально, и небольшая погрешность там неизбежна. Ключевое условие работы — прерывания должны быть включены, поскольку именно на них опирается micros().
Синтаксис
pulseInLong(pin, value)pulseInLong(pin, value, timeout)
Параметры
pin— номер вывода Arduino, на котором нужно измерить импульс. Тип данных:int.value— ожидаемый тип импульса: HIGH или LOW. Тип данных:int.timeout— необязательный параметр: максимальное время ожидания начала импульса в микросекундах. По умолчанию равно одной секунде. Тип данных:unsigned long.
Возвращает
Длительность импульса в микросекундах в виде unsigned long, или 0, если за время timeout импульс так и не начался.
Пример кода
Пример выводит в Serial Monitor длительность импульса на выводе 7.
int pin = D1;
unsigned long duration;
void setup() {
Serial.begin(9600);
pinMode(pin, INPUT);
}
void loop() {
duration = pulseInLong(pin, HIGH);
Serial.println(duration);
}
Практические замечания
pulseInLong()нельзя вызывать внутри обработчика прерывания (noInterrupts()): функция зависит отmicros(), а тот внутри прерываний не обновляется.- Если вам нужно измерять короткие импульсы (единицы микросекунд) и прерывания в коде не используются, pulseIn() может оказаться точнее — он считает такты напрямую.
- Параметр
timeoutудобно уменьшать, если датчик должен отвечать быстро: по умолчанию функция может «висеть» до секунды в ожидании импульса, что заметно тормозит цикл. - Перед вызовом убедитесь, что вывод настроен как вход (
pinMode(pin, INPUT)илиINPUT_PULLUP), иначе результат будет непредсказуемым.
Примечания и предупреждения
Функция использует micros(), поэтому её нельзя вызывать в контексте noInterrupts().