Объяснить функцию pulseIn с помощью arduino и ультразвукового датчика
дорогие инженеры.. я застрял с этой проблемой, не мог понять.. пожалуйста, помогите с объяснениями.
сначала я был расстроен отклонениями показаний ультразвукового датчика, то есть я осматриваю свой датчик в помещении и в спокойной обстановке, так что же делает эти шумные выходные показания??!!!
поэтому я попытался разобраться в функции pulseIn и отследить время выполнения каждой инструкции в коде.. прочитав библиотеку.., я решил использовать функцию pulseInLong. ниже приведен результат некоторых итераций, рассчитанных в микросекундах:
Ultrasonic Sensor HC-SR04 Test
with Arduino UNO R3
Start ~ trig LOW ~ 10us delay ~ trig High ~ 10us delay~ trig High ~ pulseIn ~ Duration
0 8 12 8 12 4 7352 137976
4 4 12 8 12 8 7336 137960
4 8 12 8 12 8 7352 137976
4 8 12 8 12 8 7356 137980
4 8 12 8 12 8 7352 137976
4 8 12 8 12 8 7356 137980
4 8 12 8 12 8 7360 137984
4 8 12 8 12 8 7364 137996
0 8 12 8 12 8 7364 137992
4 8 12 8 12 8 7372 137996
4 8 12 4 12 8 7380 138004
0 4 12 8 12 8 7372 137996
0 4 12 8 12 8 7348 137968
4 8 12 4 12 8 7372 137996
4 8 12 8 12 4 7376 138004
4 8 12 8 12 8 7380 138008
0 8 12 8 8 8 7352 137980
4 8 12 4 12 8 7352 137976
4 8 12 4 12 8 7368 137992
4 8 12 8 12 8 7340 137964
4 8 12 4 12 8 7352 137980
4 8 12 4 12 8 7360 137984
12 8 12 8 12 8 7368 137996
4 8 12 8 12 8 7348 137972
4 8 12 8 12 12 7360 137984
0 8 12 8 12 8 7344 137968
4 8 12 8 12 8 7352 137976
4 8 12 8 12 8 7364 137988
4 8 12 4 12 8 7360 137984
4 8 12 8 12 4 7372 138000
сначала я задался вопросом, почему для одной и той же инструкции разное время выполнения??! например, digitalWrite(триг_пин,НИЗКИЙ или высокий) варьируется в диапазоне 4 ~ 12 микросекунд!!????
более странно, когда я обнаружил, что прошло время после задержки 10 секунд, функция micros() показывает только 8 мкс??!!!
все это в диапазоне 16 мкс, поэтому я ожидал, возможно, из-за некоторых циклов команд или неточных часов...и т. Д.
но шорты я в шоке, когда прочитал это huuuuuge разница в pulseIn время измерения; я сбросил таймер перед функцией и сразу после нее, так что я получил истекшее время в диапазоне 7350 us. в то же время результирующее измеренное время от функции в диапазоне 138000 us?????!!!!!!
имейте в виду, что pulseInLong-это блокировка function..as вы увидите ниже, что он зацикливается в цикле времени до тайм-аута (так что возвращайте 0) или импульс, сгенерированный и измеренный до тайм-аута, а затем возвращает истекшее время импульса.
сначала я заподозрил в этом количестве, может быть, не микросекунды. внимательно изучил функцию, ??!!! я нашел его, используя точную функцию micros (), которую я делаю в коде?
* this function relies on micros() so cannot be used in noInterrupt() context
*/
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
unsigned long startMicros = micros();
// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
unsigned long start = micros();
// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
return micros() - start;
}
в любом случае ... я не хочу затягивать эту историю.. может кто-нибудь объяснить мне, что происходит, пожалуйста?!
спасибо
вот код arduino, который я использовал
#define trigPin 3 //attach pin D3 Arduino to pin Trig of HC-SR04
// defines variables
long duration; // variable for the duration of sound wave travel
int distance; // variable for the distance measurement
void setup() {
// put your setup code here, to run once:
pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
Serial.begin(9600); // // Serial Communication is starting with 9600 of baudrate speed
Serial.println("Ultrasonic Sensor HC-SR04 Test"); // print some text in Serial Monitor
Serial.println("with Arduino UNO R3");
Serial.println("Start ~ trig LOW ~ 10us delay ~ trig High ~ 10us delay ~ trig High ~ pulseIn ~ Duration");
}
void loop() {
// put your main code here, to run repeatedly:
// Clears the trigPin condition
int indx = 0;
int arr[7] = {0};
double last = micros();
arr[indx] = micros() - last;
indx++;
last = micros();
digitalWrite(trigPin, LOW);
arr[indx] = micros() - last;
indx++;
last = micros();
delayMicroseconds(10);
arr[indx] = micros() - last;
indx++;
last = micros();
// Sets the trigPin HIGH (ACTIVE) for 10 microseconds
digitalWrite(trigPin, HIGH);
arr[indx] = micros() - last;
indx++;
last = micros();
delayMicroseconds(10);
arr[indx] = micros() - last;
indx++;
last = micros();
digitalWrite(trigPin, LOW);
arr[indx] = micros() - last;
indx++;
last = micros();
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseInLong(echoPin, HIGH);
arr[indx] = micros() - last;
// Calculating the distance
distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
// Displays the distance on the Serial Monitor
for (int i = 0; i <= indx; i++)
{
Serial.print(arr[i]);
Serial.print(" \t ");
}
Serial.print(duration);
Serial.println();
}
@absi, 👍1
Обсуждение2 ответа
Почему я получаю большую разницу во времени измерения между прошедшим временем при выполнении функции pulseInLong и ее измерением длительности возврата?
Ответ кроется в выборе способа его реализации. Функция задержки сама по себе полезна, но точность невелика, когда требуется точность. Вот официальная заметка с сайта:
- Эта функция работает очень точно в диапазоне от 3 микросекунд и выше. Мы не можем гарантировать, что микросекунды задержки будут выполняться точно для меньшего времени задержки.
- Начиная с Arduino 0018, функция delayMicroseconds() больше не отключает прерывания
Если вы действительно хотите быть точным, я рекомендую использовать аппаратные таймеры. Я верю, что этого будет достаточно. чтобы узнать больше об использовании аппаратных таймеров, вы можете обратиться к
https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers
https://maker.pro/arduino/projects/timer-interrupts-improve-your-arduino-programming-skills
Я вижу по крайней мере три причины такого поведения, которое вы замечаете:
micros()
имеет разрешение 4 мкс. Если бы вы могли вызвать его с периодом, равным ровно 10 мкс, вы бы увидели, что временные интервалы чередуются между 8 и 12 мкс. Но тогдавыполнение функции micros()
занимает некоторое время, поэтому, если вы используете ее для определения времени выполнения функции, которая занимает 10 мкс для выполнения, вы будете читать 12 мкс чаще, чем 8.- Существует прерывание таймера, срабатывающее каждые 1024 мкс. Любой процесс
, который будет прерван, покажет время выполнения больше, чем обычно.
Это вероятная причина
того, что digitalWrite()
иногда занимает намного больше времени, чем обычно. pulseIn()
ожидает начала импульса, прежде чем начнет измерять его длительность. Тогда время его выполнения может быть значительно больше, чем длительность импульса, о которой он сообщает.
я ожидал, возможно, из-за некоторых циклов команд или неточных часов.
Одни и те же часы используются для последовательности инструкций процессора и для их синхронизации. Таким образом, точность часов не влияет на время, которое вы измеряете.
Правка: Здесь есть дополнительная проблема, которая заключается в переполнении
arr[6]
. Время выполнения функции pulseInLong()
может быть примерно таким
138,424 мкс. Поскольку значение int
в Uno равно 16 битам, это значение
преобразуется по модулю 216 в 7352, что соответствует значению, показанному в первой
строке вывода.
Уважаемый @Edger Bonet и другие Инженеры, пожалуйста, сконцентрируйтесь со мной немного.., @absi
@absi: Что вы имеете в виду?, @Edgar Bonet
#3) Пункт № 3: относительно возвращаемого времени pulseInLong и времени выполнения: время, возвращаемое функцией, - это то, что я перечислил в таблице синхронизации в разделе длительность, где время выполнения указано в разделе pulseIn в таблице синхронизации. как видите, время выполнения намного меньше возвращенного измеренного времени для импульса, и это очень странно??!! так что, пожалуйста, кто-нибудь попробуйте объяснить, @absi
@absi: О, я скучал по этому. См.Измененный ответ., @Edgar Bonet
- 4-битный счетчик вверх и вниз
- Arduino синтаксический анализ строки с использованием sscanf
- Программирование Arduino Uno R3 для срабатывания реле каждые 24 часа
- Получение кода FFT arduino для работы более 9 часов с использованием micros()
- Проблемы с Serial.read()
- Проблема с использованием Arduino Mega Timer2 с прерыванием PinChange
- Node.js не может распознавать символы из последовательного порта
- GPS автономный робот
Посмотрите на исходный код, он у вас есть. digitalWrite-это функция, в которой есть несколько строк. На чипе работают прерывания. Если одно из этих прерываний срабатывает во время выполнения функции digitalWrite, то выполнение этого времени займет больше времени., @Delta_G
Этот метод считывания ультразвукового датчика-отличный способ познакомить кого-то с тем, как работают эти типы датчиков, потому что очень легко следовать коду, но есть гораздо лучшие способы справиться с считыванием ультразвукового датчика гораздо более точным способом., @Delta_G
спасибо Delta_G за ответ здесь, но, к сожалению, я все еще не могу понять суть!!! во - первых: почему иногда я измеряю прошедшее время 8us, в то время как я использовал задержку 10us?! во-вторых: почему я получаю большую разницу во времени измерения между прошедшим временем при выполнении функции pulseInLong и ее измерением продолжительности возврата!?, @absi
Прочитайте документацию по delayMicroseconds. В нем четко указано, что разрешение этой функции равно 4us., @Delta_G
Просто чтобы добавить свои два цента. Возможно, библиотека digitalWriteFast может пригодиться для этого критичного по времени приложения. Обычно я использую его вместо функции по умолчанию, и это, безусловно, экономит немного времени, @Daniel Melendrez