Объяснить функцию pulseIn с помощью arduino и ультразвукового датчика

arduino-uno programming timers c programming-sequence

дорогие инженеры.. я застрял с этой проблемой, не мог понять.. пожалуйста, помогите с объяснениями.

сначала я был расстроен отклонениями показаний ультразвукового датчика, то есть я осматриваю свой датчик в помещении и в спокойной обстановке, так что же делает эти шумные выходные показания??!!!

поэтому я попытался разобраться в функции 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();

}

, 👍1

Обсуждение

Посмотрите на исходный код, он у вас есть. digitalWrite-это функция, в которой есть несколько строк. На чипе работают прерывания. Если одно из этих прерываний срабатывает во время выполнения функции digitalWrite, то выполнение этого времени займет больше времени., @Delta_G

Этот метод считывания ультразвукового датчика-отличный способ познакомить кого-то с тем, как работают эти типы датчиков, потому что очень легко следовать коду, но есть гораздо лучшие способы справиться с считыванием ультразвукового датчика гораздо более точным способом., @Delta_G

спасибо Delta_G за ответ здесь, но, к сожалению, я все еще не могу понять суть!!! во - первых: почему иногда я измеряю прошедшее время 8us, в то время как я использовал задержку 10us?! во-вторых: почему я получаю большую разницу во времени измерения между прошедшим временем при выполнении функции pulseInLong и ее измерением продолжительности возврата!?, @absi

Прочитайте документацию по delayMicroseconds. В нем четко указано, что разрешение этой функции равно 4us., @Delta_G

Просто чтобы добавить свои два цента. Возможно, библиотека digitalWriteFast может пригодиться для этого критичного по времени приложения. Обычно я использую его вместо функции по умолчанию, и это, безусловно, экономит немного времени, @Daniel Melendrez


2 ответа


0

Почему я получаю большую разницу во времени измерения между прошедшим временем при выполнении функции pulseInLong и ее измерением длительности возврата?

Ответ кроется в выборе способа его реализации. Функция задержки сама по себе полезна, но точность невелика, когда требуется точность. Вот официальная заметка с сайта:

  1. Эта функция работает очень точно в диапазоне от 3 микросекунд и выше. Мы не можем гарантировать, что микросекунды задержки будут выполняться точно для меньшего времени задержки.
  2. Начиная с 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

,

1

Я вижу по крайней мере три причины такого поведения, которое вы замечаете:

  1. micros() имеет разрешение 4 мкс. Если бы вы могли вызвать его с периодом, равным ровно 10 мкс, вы бы увидели, что временные интервалы чередуются между 8 и 12 мкс. Но тогда выполнение функции micros() занимает некоторое время, поэтому, если вы используете ее для определения времени выполнения функции, которая занимает 10 мкс для выполнения, вы будете читать 12 мкс чаще, чем 8.
  2. Существует прерывание таймера, срабатывающее каждые 1024 мкс. Любой процесс , который будет прерван, покажет время выполнения больше, чем обычно. Это вероятная причина того, что digitalWrite() иногда занимает намного больше времени, чем обычно.
  3. 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