Ваша функция getCM()
имеет потенциально бесконечный цикл, ожидающий эхо.Если ваше оборудование не работает должным образом или в зоне действия нет объекта с достаточным отражением строки, getCM()
никогда не завершится.
Вы должны иметь тайм-аут в getCM()
.Например, если вы хотите максимальную дальность действия, скажем, три метра, максимальное время эха будет около 18 мс, т.е. (расстояние х 2) / скорость звука .После этого вам нужно сдаться и отправить еще один пинг:
Дано:
#define MIN_RANGE_CM 4
#define MAX_RANGE_METRES 3
#define SPEED_OF_SOUND_M_PER_SEC 343
#define MAX_TIME_OF_FLIGHT_US (MAX_RAMGE_METRES * 2000000) / SPEED_OF_SOUND_M_PER_SEC
#define MIN_TIME_OF_FLIGHT_US (MAX_RAMGE_CM * 20000) / SPEED_OF_SOUND_M_PER_SEC
Ваш getCM()
может выглядеть так:
int getCM()
{
int distance = -1 ;
long startTime = micros() ;
long elapsed_time = 0 ;
// Send ping pulse
digitalWrite(TRIG, HIGH);
delayMicroseconds(20);
digitalWrite(TRIG, LOW);
// Wait for ping end
while( digitalRead(ECHO) == LOW &&
elapsed_time < MIN_TIME_OF_FLIGHT_US )
{
elapsed_time = micros() - startTime ;
}
// If not timed out waiting...
if( elapsed_time < MIN_TIME_OF_FLIGHT_US )
{
// Wait for echo
elapsed_time = 0 ;
while( digitalRead(ECHO) == HIGH &&
elapsed_time < MAX_TIME_OF_FLIGHT_US )
{
elapsed_time = micros() - startTime ;
}
// If not timed out, get distance in cm
if( elapsed_time < MAX_TIME_OF_FLIGHT_US )
{
distance = (elapsed_time * SPEED_OF_SOUND_M_PER_SEC) / 20000 ;
}
}
return distance ;
}
Обратите внимание, что каждый циклесть тайм-аут.Обратите внимание, что ваши комментарии и сроки не показались правильными.Вы ожидаете окончания пинга и начала эха, а не начала и конца эха.Время полета - это период от начала пинга до первого обнаруженного эхо-сигнала.Ваша реализация не начинает отсчет времени до конца пинга.В вашем случае пинг 20us составляет всего несколько миллиметров, так что это, вероятно, не имеет значения.Приведенная выше реализация использует «минимальный диапазон» в качестве тайм-аута для ожидания окончания пинга - произвольно 5 см - если на входе не было низкого уровня за это время, возникает проблема - аппаратная ошибка или кто-то связывает свои ключи (которые могут действительноиспортите ультразвуковой датчик - попробуйте!).
Для этого приложения ваше расстояние необходимо будет измерять непрерывно.С этой целью я предлагаю:
int main(void)
{
setup();
for( ;; )
{
printf( "Distance: " ) ;
int distance = getCM() ;
if( distance >= 0 )
{
printf( "%dcm \r", distance ) ;
}
else
{
printf( "Out-of-range\r" ) ;
}
fflush( stdout ) ;
delay( 200 ) ;
}
return 0;
}
\r
будет повторно использовать ту же строку для отображения расстояния, предотвращая прокрутку терминала.Пробел гарантирует, что предыдущий вывод будет перезаписан.Вызов fflush()
обеспечивает немедленный вывод буферизованного вывода.