- Плата Arduino. x1
- Компьютер(для написания и загрузке кода, а так же мы будем брать с него электричество и общаться с ним). x1
- Провод для соединения компьютера и платы. x1
- Ультразвуковой датчик HC-SR04
- Провода. x4
- Есть схемы с внешним источником питания, но можно взять питание и с платы.
Схема:
Скетч:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
const int pinEcho = 7; const int pinTrig = 8; float v=331.5+0.6*20; void setup() { Serial.begin(9600); pinMode(pinEcho, INPUT); pinMode(pinTrig, OUTPUT); } float distanceSM(){ digitalWrite(pinTrig, LOW); delayMicroseconds(3); digitalWrite(pinTrig, HIGH); delayMicroseconds(5); digitalWrite(pinTrig, LOW); float t = pulseIn(pinEcho, HIGH);//mks t = t/1000.0/1000.0/2; //s return t*v*100; //cm } void loop() { Serial.print(distanceSM()); Serial.print("cm"); Serial.println(); delay(1000); } |
В начале задаём константы с номерами штырьков, к которым подключён наш HC-SR04 сенсор:
1 2 |
const int pinEcho = 7; const int pinTrig = 8; |
Контакт Echo нашего сенсора подключен к 7 штырьку, котакт Trig подключён к 8 штырьку.
Дальше определяем переменную v в которой будет храниться скорость звука
1 |
float v=331.5+0.6*20; |
Скорость звука можно определить по формуле Лапаласа:
$$C=\sqrt{\frac{c_p}{c_v} * \frac{p}{\rho}}$$
где, $$p$$ давление; $$\rho$$ — плотность воздуха; $$c_ν$$ теплоемкость воздуха при постоянном давлении; $$c_p$$ теплоемкость воздуха при постоянном объеме.
Но так как у нас слишком мало данных… то сделаем так:
При нормальном давлении и температуре 0 градусов скорость звука равна 331 м/с.
А во влажном воздухе скорость звука увеличивается на 0,61 м/c при увеличении температуры на 1 градус.
и получится следующая формула:
$$c = 331+0,6*t+0,07*e$$
где $$t$$-это температура, $$e$$ — влажность.
В диапазоне температур ($$t$$) от —20° до +30° эта формула дает ошибку в скорости звука не более ± 0,5 м/сек. (Так как мы отбросили давление воздуха.)
Теперь посмотрим на форумулу которую использую я:
1 |
float v=331.5+0.6*20; |
видно, что температура у меня задана примерно 20 градусов, а влажность вообще отброшена… точность данных измерений на лицо… но для показа принцира работы данного устройства должно хватить. Для повышения точности данного прибора нужно будет установить датчик влажности-температуры, например DTH11.
Дальше в функции setup определяем скорость передачи данных по USB, а так же назначаем штырьку к которому подключен контакт сенсора Echo состояние INPUT, а Trig соответственно OUTPUT.
1 2 3 4 5 |
void setup() { Serial.begin(9600); pinMode(pinEcho, INPUT); pinMode(pinTrig, OUTPUT); } |
Дальше объявим функцию distanceSM() в ней будет происходить всё волшебство. Разберём её по подробнее.
1 2 3 4 5 6 7 8 9 10 11 |
float distanceSM(){ digitalWrite(pinTrig, LOW); delayMicroseconds(3); digitalWrite(pinTrig, HIGH); delayMicroseconds(5); digitalWrite(pinTrig, LOW); float t = pulseIn(pinEcho, HIGH);//mks t = t/1000.0/1000.0/2; //s return t*v*100; //cm } |
Сначала мы отсылаем сигнал продолжительностью 5 микросекунд
1 2 3 4 5 |
digitalWrite(pinTrig, LOW); delayMicroseconds(3); digitalWrite(pinTrig, HIGH); delayMicroseconds(5); digitalWrite(pinTrig, LOW); |
Для этого мы сначала убеждаемся, что наш контакт Trig находится в состоянии LOW и соответственно сигнал не идёт. для этого на 3 микросекунды переводим его в состояние LOW
1 2 |
digitalWrite(pinTrig, LOW); delayMicroseconds(3); |
Дальше формируем сигнал в 5 микросекунд, для этого мы подадим напряжение на ножку Trig в течении 5 микросекунд, а потом уберём напряжение.
1 2 3 |
digitalWrite(pinTrig, HIGH); delayMicroseconds(5); digitalWrite(pinTrig, LOW); |
осталось посчитать продолжительность времени импульса
1 |
float t = pulseIn(pinEcho, HIGH);//mks |
То есть он будет ждать пока на ножку Echo не придёт сигнал, или пока данная функция не завершиться по таймауту. По умолчанию данная функция ждёт сигнал 1 секунду, что превышает 45 метров и это явно за грань чувствительности сенсора. У этой функции есть ещё и нижняя граница 10 микросекунд, что для нашего сенсора будет примерно 17 миллиметров тоже за гранью чувствительности так что pulseIn полностью нам подходит.
Осталось перевести время из микросекунд в секунды, подсчитать расстояние и вернуть значение.
1 2 |
t = t/1000.0/1000.0/2; //s return t*v*100; //cm |
Осталась функция loop которая в бесконечном цикле будет с помощью функции distanceSM() получать расстояние до препятствия в сантиметрах. и выводить эти значения на USB порт:
1 2 3 4 5 6 7 8 |
void loop() { Serial.print(distanceSM()); Serial.print("cm"); Serial.println(); delay(1000); } |
Ещё установлена задержка в 1 секунду, чтоб не мельтешило.
Всё скетч кончился смотрим на результат работы скетча:
Не правильное опрделение расстояния до пушистых объектов:
Не правильное определение расстояния до поверхностей, находящихся под углом:
Другие статьи по программированию плат Arduino можно посмотреть здесь.
Этот код даёт обычную погрешность ±1,5cm. В чем его уникальность относительно стандартных которые не «подошли»? Я так понимаю, ардуина вообще не способна вычислять длину импульса с большой точностью. Команда pulseIn на микросекундах брешет как Троцкий. Я только усреднением по медиане с коэффициентом 30 смог добиться точных показаний. Но дело в том, что чем сильнее усреднение, тем дольше расчет. С большой скоростью и точностью обновлять показания не получиться. Может есть какие то варианты как можно с точностью до 1-2мкс измерить длину импульса в диапазоне 500 — 2500мкс.?
Убрал из статьи текст:
«Стандартные скетчи к сожалению нам не подоходят, поэтому рассмотрим следующий:»
Когда я писал статью arduino не подгружал так резво библиотеки. И я их считал, да и считаю чем то инородным сделанными на коленке.
Одно то, что возникают ситуации, что в библиотеке надо что то !править!. Что бы что то заработало. Меня вводит в уныние. Поэтому они небыли причислены мной к стандартным. Но это действительно вводит в замешательство. Поэтому убрал.
А теперь про точность. Там в середине статьи я пытаюсь объяснить как я вычисляю скорость звука. Так вот в этом размышлении для меня очевидно, что без датчика температуры можно добиться только приблизительного измерения.
А теперь чуть по подробнее вот скорость звука я говорю что вычисляю по формуле:
c=331+0,6∗t+0,07∗e в ней уже нет плотности воздуха… так как совсем не жалоко.. (буду говорить погрешность в конечной длине) меньше 1 милиметра на метр.
потом я отбросил 0,07∗e тоже меньше милиметра на метр выходило (может быть 2).
Но есть ещё температура я считаю что она равна 20 градусов. Но!
Погрешность ~2 милиметра на градус.
Тоесть если температура в помещении 26 градусов то это плюс 12 милиметров на метр .
Думаю сначала надо убрать эту погрешность. А потом браться за милисекунды. 🙂
С прикреплённым датчиком DTH11 код выглядит так:
надо зафотать и ещё одну статью замутить. 🙂 А на каком расстоянии +-2,5 см?
чтобы когда точность буду описывать было бы с чем сравнивать.
спасибо очень помогло потому что стандартная программа не работала я уж грешным делом подумал что датчик бракованный
Скажи, плез, что за переменная pnp и как она высчитана?