Функции и датчик расстояния HC-SR04

Датчик расстоянияВ этой статье мы будем говорить о датчике расстояния HC-SR04, который очень популярен среди энтузиастов DIY.

Также в данной статье мы разберемся с очень простым акустическим элементом — зуммером.

Надеемся, что эта статья будет интересна разработчикам роботов и всем, кто хотел бы использовать датчик расстояния в своих проектах, пример, на фото ниже.

Зуммер и датчик расстояния

Однако перед этим мы рассмотрим некоторые новые приемы программирования, которые сделают наши программы еще лучше — как для Arduino, так и для человека, ответственного за создание программы, а именно для вас!

Функции без аргументов

Пока что мы поместили наш код в функции setup () {} и loop () {}. Первая была для настройки, а вторая — для бесконечного главного цикла. Например, чтобы запрограммировать (перепрошить) светодиод, подключенный к пину 13, вам нужно было написать следующую программу:

Помните, что светодиод, встроенный в Arduino, подключен к пину 13!

Представим себе ситуацию, что наша программа очень сложна, и мы хотим использовать перепрошивку (программирование) как подтверждение выбранных операций. Быстро выяснится, что повторное дублирование фрагмента, отвечающего за включение и выключение светодиода, требует времени у программиста. Хуже того, это также усложняет анализ всей программы.

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

При программировании на Arduino мы используем множество готовых функций, например: digitalWrite (13, HIGH);. Мы знаем, что эта запись вызывает высокое состояние (логическая 1) на выводе (пине) номер 13. Однако нам не нужно знать, как это делается. Точно так же мы можем создавать свои собственные функции. Например, рассмотрим уже упомянутую перепрошивку.

За эту операцию отвечает следующий фрагмент кода:

Мы можем «вытащить» его из loop () {} и сделать отдельной функцией. Как это сделать?

Сначала необходимо объявить название функции и ее тип. Мы делаем это, например: в функции loop () {} :

Как вы можете видеть перед именем функции, в этом случае blinkedLED — это тип функции. Это не более чем информация о том, возвращает ли функция какое-либо значение после своего завершения. Если да, то туда нужно ввести соответствующий тип (по типам переменных). Это может быть, например, целое число (int), символ (char), нецелое число (float) и т.д.

В этом случае есть слово void. Этот тип означает, что функция не возвращает значения. Почему мы выбрали именно этот тип? Задача функции — прошить светодиод, никакого результата (кроме видимого нашим глазом) эта операция не дает.

Если функция не дает результата, поставьте перед ней слово void!

(Другие случаи будут обсуждаться  в этой статье позже)

Скобка появляется после имени функции. А пока предположим, что в скобках ничего нет. Затем мы открываем фигурную скобку и помещаем в нее код, который должен выполняться при вызове функции. На практике:

Обратите внимание, что в loop () {} мы ввели имя нашей переменной (без префикса void). Эта операция называется вызовом функции. Загрузите программу и проверьте, работает ли она в соответствии с анимацией ниже:

LED-Blink

Помните, что имена функций должны объяснять, что функция делает, и должны быть уникальными! Они не могут совпадать с именами переменных.

Вернемся к ранее предполагавшейся ситуации, когда вы используете перепрошивку во многих, очень разных частях программы (для подтверждения операции). Что, если вам вдруг захотелось изменить последовательность свечения или, например, количество миганий? Вам придется изменить один и тот же фрагмент кода примерно в дюжине мест. Но если вы используете свою собственную функцию, то все, что вам нужно сделать, это изменить значение только в одном месте:

Домашнее задание 8.1

Напишите функцию, которая заставляет светодиод мигать (постепенное затухание и яркость). Конечно, воспользуйтесь знаниями, полученными в статье о ШИМ-сигнале.

Arduino — собственные функции с аргументами

Пришло время открыть для себя следующие секреты функции. Помните одну из наиболее часто используемых функций Arduino? Вероятно, это будет изменение состояния определенного пина, например:

В отличие от нашей функции blinkedLED (); , здесь мы вводим некоторые данные в скобках. Это может быть номер пина (вывода), состояние, которое мы хотим получить, или заполнение сигнала ШИМ. Эта информация позже используется в функциях для выполнения определенных операций.

Это аргументы, которые передаются функции.

Обратите внимание на используемую лексику, и аргументы, и пассажи, они не использовались бессистемно. Это термины, используются всеми разработчиками! Теперь пора написать свою собственную функцию, сначала с одним аргументом.

Читать также:  Создание нового пользователя

Предположим, мы хотим отредактировать нашу функцию blinkedLED таким образом, чтобы можно было изменять скорость вспышки (мигания) при ее вызове. В нашем объявлении функции нам нужно добавить информацию о том, что она может принимать аргумент. Делаем это в заголовке функции:

С этого момента компилятор знает, что когда он встречает вызов функции в круглых скобках, он должен ожидать число (тип int ). Это число будет передано в функцию и отобразится как время.

Это будет переменная, видимая только внутри нашей функции, т.е. это будет так называемая локальная переменная.

На практике внутренняя часть функции будет выглядеть так:

Пришло время последнего элемента, то есть вызова новой функции. Здесь, наверное, не будет ничего удивительного. Мы просто вводим число в скобках, которое будет означать время, в течение которого диод должен быть включен и выключен. Весь код выглядит так:

Убедитесь в том, что вы точно можете влиять на частоту мигания, заменив значение в скобках. Пришло время для другого примера.

Функции с аргументом — пример 2

До сих пор непрерывное мигание светодиода было видно, потому что мы вызывали нашу функцию в цикле функции. Когда мы перемещаем вызов функции в раздел настройки, мы увидим только одну вспышку (мигание) после загрузки. Проверим:

Это именно то, что произошло бы, если бы мы захотели использовать функцию, например, для подтверждения нажатия кнопки. Вызов blinkedLED () вызовет одно мигание.

Пришло время переписать функцию таким образом, чтобы помимо изменения времени мигания можно было также влиять на количество миганий. Во-первых, нам нужно изменить объявление функции:

Мы добавили числовой аргумент, он будет отвечать за количество миганий. Этот параметр может быть другого типа, это не имеет значения. Важно, чтобы аргумент был соответствующий.

Функция может принимать множество аргументов разных типов!

Как вы, наверное, догадались, использовать второй аргумент очень просто. У нас просто теперь есть вторая локальная переменная, howmany.

Надеюсь, вы уже знаете, какой цикл использовать, чтобы лучше контролировать количество миганий? Если нет, обратитесь к предыдущему разделу, где мы рассмотрели циклы. Однако мы предполагаем, что вы усвоили этот материал (или собираетесь восполнить недостатки) и представляем новую функцию blinkedLED:

Проверим весь код:

Все должно работать. Теперь после запуска, светодиод должен мигнуть ровно 5 раз. Но как Arduino знает, как различать информацию в скобках, сколько времени работать и сколько повторений нужно сделать?

Что ж, правило очень простое — последовательные значения, разделенные запятыми, присваиваются следующим аргументам, описанным в объявлении функции. В приведенном выше случае, первое число всегда будет считаться временем, а второе — счетчиком повторов.

Домашнее задание 8.2

Напишите функцию, позволяющую отдельно регулировать количество миганий, время выключения светодиода и время включения светодиода.

Можно ли расширить нашу функцию? Конечно! Разве не было бы удобно, если бы, помимо объявления времени и количества повторов, можно было указать пин (вывод), к которому подключен светодиод?

Функции с аргументами — пример №3

Пин, к которому подключен светодиод, — это номер в нашей программе. Мы используем его в двух местах при объявлении данного пина (вывода) в качестве выхода и при установке высокого или низкого состояния. Значит, это число может быть еще одним аргументом нашей функции!

Сначала подключите второй диод к другому пину, например, № 8:

Подключение светодиода
Подключение светодиода к пину №8

Мы не будем здесь больше вдаваться в подробности, сразу же представим весь пример программы:

Давайте проверим, работает ли? Не совсем, правда? Мигает только светодиод, подключенный к пину 13, а тот, что под номером 8, не хочет подавать признаков жизни. Почему? Что ж, мы совершили очень простую ошибку, которую легко допустить при написании таких функций. Мы нигде не предусмотрели, что другие пины (кроме 13) могут быть выходами. Проверьте раздел настройки:

Мы можем исправить это относительно легко, нам просто нужно передать конфигурацию контактов нашей функции. Это выглядело бы так:

Сейчас все работает, но должны признать, что это не самое лучшее решение. Поэтому мы не рекомендуем использовать этот тип решений в более профессиональных проектах. Однако на этапе понимания ничего плохого случиться не должно, и мы можем облегчить себе жизнь с помощью такой простой функции.

Читать также:  Чтение данных с датчика наклона

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

Функции, возвращающие результат

До сих пор мы использовали только функции, которые выполняли некоторую операцию, но не должны были возвращать какой-либо результат. Задачей новой функции будет вычисление площади квадрата с заданной стороной и вернуть результат (вычисленную площадь). Сначала нужно объявить функцию, на этот раз это будет выглядеть так:

Как видите, в дополнение к аргументу (стороне квадрата) перед функцией появилось целое число. Это означает, что он вернет результат, который является числом. В данном случае это, конечно же, расчетная площадь.

Внутренняя часть функции должна выглядеть так:

Мы выделили здесь строку со словом return. После него мы помещаем значение (переменную), которое возвращается в результате этой функции. Итак, для аргумента 4 результат функции должен быть 16, потому что 4 * 4 = 16. Зачем это нужно?

Давайте посмотрим пример ниже:

Запустите пример. Результат операции должен появиться на мониторе последовательного порта, т.е. 16. Тот факт, что функция возвращает результат, означает, что после ее выполнения в том месте, где она вызывается, «результат будет заменен». В этом случае вместо squareField (4); 16 подставляется и записывается в переменную result.

Однако объявление отдельной переменной излишне. Следующая запись также будет работать правильно (но немного менее понятно):

Для полноты счастья, нам не хватает только того, чтобы сторона квадрата могла быть отправлена на Arduino с компьютера. Здесь мы будем использовать знания из статьи о связи через UART. Программа будет выглядеть следующим образом:

Однако новинка в нашей программе — это receiveData.toInt () . Как вы, наверное, помните, все символы отправляются в виде кодов ASCII при общении через UART. Следовательно, во время наших тестов мы не могли легко отправлять числа в Arduino.

Однако это можно очень легко изменить. Достаточно добавить к прочитанной строке ().toInt () . Это преобразует число, отправленное в виде текста, в число типа int.

Операция изменения типа переменной на другой, называется проекцией.

Домашнее задание 8.3

Напишите функции, вычисляющие площадь прямоугольника, круга и треугольника. Отправляйте результаты на ПК через UART!

Ультразвуковой датчик расстояния HC-SR04

Пришло время описать датчик расстояния. Датчик HC-SR04 состоит из передатчика и приемника ультразвука и нескольких интегральных схем. Благодаря им, основываясь на том, как отражается акустический сигнал (неслышимый для человека), мы можем довольно точно определить расстояние датчика от препятствия. Прямо как… летучие мыши:

Летучие мыши

Но вернемся к Arduino и датчику расстояния. Во-первых, давайте сосредоточимся на его четырех сигнальных контактах. Два из них используются для питания схемы (Vcc, GND), а два других (триггер и эхо) для выполнения измерений.

Триггер — это вход триггера. Когда мы дадим ему высокое состояние (как минимум на 10 микросекунд), начнется измерение расстояния. С другой стороны, по выходному эхо- сигналу мы можем прочитать измеренное расстояние. Максимальная дальность действия этой незаметной схемы заявлена ​​производителем и составляет 4 метра.

Задняя часть датчика Передняя часть датчика
Задняя часть датчика Передняя часть датчика

Пришло время для первого простого примера использования датчика на практике.

Измерение расстояния

Теперь будет измерять расстояния через определенные промежутки времени и отображать их на экране компьютера. Для этого необходимо собрать схему как показано на фото:

Принципиальная схема сборки

Описание контактов физически находится на датчике, но для формальности мы его представим ниже. Если смотреть сверху (как на схеме выше) и слева:

  1. Vcc — 5 В
  2. Триггер
  3. Эхо
  4. Gnd

Фото сборки мы выложили ниже. Не обращайте внимание на зеленый провод, мы забыли его отсоединить при фотографировании:

Подключение датчика HC-SR04
Подключение датчика HC-SR04 к плате Arduino

В нашем случае мы подключаем триггерный вход к контакту № 12, а эхо — к контакту № 11.

Вы уже более или менее знаете, как запустить измерение расстояния. Пора записать это как программу:

Обратите внимание на новую функцию delayMicroseconds (); , это не что иное, как аналог известной функции delay (); . Разница, наверное, очевидна. Новая функция ведет обратный отсчет в микросекундах. Напомню, что использованная функция задержки измеряется в миллисекундах.

Последовательность начала измерения очень проста. Вначале мы устанавливаем низкий уровень сигнала на контакте, подключенном к триггерному входу датчика. Достаточно 2 микросекунд, затем установите высокое состояние на 10 микросекунд. Датчик измеряет и возвращает результаты на вывод эхо-сигнала.

Вопрос в том, как это считать? Нужен ли мне для этого UART или другой интерфейс связи? Нет, к счастью, этот датчик очень простой, и измеренное расстояние представлено импульсом (высокое состояние) на выводе эхо-сигнала. Его длина пропорциональна расстоянию. Чем она длиннее, тем больше измеренное расстояние. Здесь пригодится новая функция, доступная в Arduino.

Читать также:  Подключение и связь с микросхемой TLC5940

Измерение длительности импульса в Arduino

К счастью, в Arduino реализована очень простая функция, которая может измерять длительность импульса, подаваемого на любой вход. Его продолжительность должна составлять от 10 микросекунд до 3 минут. Измерение начинается, когда обнаруживается изменение состояния вывода.

Это очень просто:

Функция в простейшей форме принимает только два аргумента. Номер контакта, который необходимо проверить, и измеряемый логический уровень (низкий / высокий).

Итак, чтобы измерить расстояние, мы должны выполнить следующую операцию:

Когда вы запустите такую ​​программу, на экране начнут появляться числа. Чем ближе к датчику находится препятствие, тем оно будет меньше. Однако они далеки от используемых нами единиц. Чтобы результаты измерения были удобочитаемыми, результат необходимо разделить на «магическое число».

Проверьте, как работает следующая программа — теперь результат должен отображаться в сантиметрах:

Конечно, значение, на которое мы делим (58), не является «волшебным». Это результат времени, в течение которого звук распространяется на расстояние 1 см, и шаблона для расстояния, представленного производителем.

Функция, которая возвращает расстояние до датчика в см

Как видите, часть программы, позволяющая получить измерения, относительно длинна. Было бы удобней, если бы у нас была функция, которая все это делает. Не нужно ждать, представляем готовый фрагмент, в конце концов, это всего лишь копия приведенного выше кода:

Теперь в нужном месте программы достаточно вызвать функцию:

Так гораздо понятнее, правда?

Проверка диапазона расстояний

Пришло время для последнего объяснения в этой статье, посвященной основам Arduino. На этот раз давайте добавим в нашу схему зуммер, то есть звуковой элемент. Это выглядит так:

Зуммер с наклейкой Зуммер без наклейки
Зуммер с наклейкой сзади Зуммер без наклейки

Этот элемент имеет два входа, когда на один из них подается напряжение Vcc, а на другой — заземление, то зуммер начинает издавать громкий писк. Это не очень приятно, поэтому предлагаю вам оставить и не снимать наклейку (писк будет тише). Как нетрудно догадаться по надписи, эта этикетка защищает внутреннюю часть зуммера при ее промывке на производстве. В основном это делается для удаления следов припоя.

Зуммер — это полярный элемент! Обратите внимание, что одна из ножек длиннее, и на корпусе рядом с ней вы найдете значок плюса.

Чтобы использовать зуммер, подключите его к Arduino в соответствии со схемой ниже:

Схема установки
Схема установки зуммера

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

Изображение макета
Зуммер на макетной плате

На этот раз мы напишем функцию, задачей которой будет проверка, находится ли объект на определенном расстоянии от датчика. В этом случае раздастся звуковой сигнал зуммера.

Функция проверки диапазона будет использовать предыдущую функцию measureOdistance () :

Мы передаем два целых числа в качестве аргументов функции. Затем мы проверяем, больше ли измеренное расстояние, чем начальное значение нашего интервала (a), и меньше, чем максимальное значение (b) .

Кстати, вы можете видеть, что с помощью символов && мы объединяем несколько условий в одно.

Готовая программа выглядит так:

Проверьте, как программа работает на практике. На наш взгляд, она идеально подойдет для создания простой панели управления сигнализацией, которая будет следить за вашим домом!

Домашнее задание 8.4

Напишите программу, которая показывает расстояние от препятствия до датчика на светодиодной полосе. Чем ближе препятствие к датчику, тем больше светодиодов должно зажеться. Пример полосы можно собрать следующим образом:

Пример светодиодной полосы
Пример светодиодной полосы измерения расстояния

Домашнее задание 8.5

Проверьте, как меняются показания датчика, в зависимости от материала препятствия. Вы видите разницу в отображаемом расстоянии, когда датчик нацелен, например, на твердые или мягкие объекты? Сравните такие препятствия, как стена, одеяло, лист бумаги.

Вывод

Практика показывает, что вы просто должны знать весь материал изложенный в наших статьях по основам Arduino! Эти знания предостерегут вас от серьезных ошибок в будущих проектах. Надеемся, что вам нравяться наши статьи. Если вам они действительно интересны, то напишите нам об этом в комментариях, а мы в свою очередь, обещаем добавлять в этот раздел самую важную для вас информацию.

С Уважением, МониторБанк

Добавить комментарий