Предисловие
Так получилось, что в университете я изучаю C/C++. Для души пробую делать небольшие проекты на Python. Я много слышал про платформу Arduino, смотрел видео на YouTube, частенько посещал Arduino Project Hub и вот мне стало интересно самому поэкспериментировать, углубясь в разработку под микроконтроллеры. Купив стартовый набор с самой платой и горстью электронных компонентов и попробовав собрать проекты из обучающей брошюры, понял, что надо двигаться дальше. Продумав саму идею следующей самоделки, отправился на просторы Google и обнаружил, что не могу найти всего, что мне нужно на одном ресурсе. Безусловно, мне несложно было посетить несколько сайтитов и блогов с информацией, но я бы сильно сэкономил время, если бы нашел все в одном месте. Так и появилась эта статья-туториал.
Суть проекта
Мне хотелось сделать дальномер. Во-первых, из-за того, что у меня был ультразвуковой датчик и надо было научиться с ним взаимодействовать. Во-вторых, я хотел выводить всю информацию на OLED-дисплей. В статьях, которые я находил, либо рассказывалось про работу с дисплеем и датчиком по отдельности, либо они являлись частью совершенно другого проекта. Я собрал все необходимое тут и надеюсь, что это сможет как-то помочь другим.
Что понадобится?
Любая плата Arduino (у меня Uno);
Ультразвуковой дальномер HC-SR04;
OLED-дисплей на 0,96 дюймов;
Соединительные провода;
Макетная плата.
Работа с OLED-дисплеем
OLED-дисплей идеально подходит для DIY-устройств. Во-первых, мы имеем достаточно высокое разрешение экрана — 128x64 пикселя. Во-вторых, дисплей работает без модуля подсветки, что обеспечивает низкое потребление энергии. В-третьих, для подключения используется всего четыре разъема — два для питания и два для обмена информацией. Но несмотря на это, у OLED-дисплеев есть и минусы. Со временем пиксели могут тускнеть и перегорать.
Вот таким образом можно подключить дисплей:
Есть несколько библиотек для работы с OLED-дисплеями, мне больше нравится OLED_I2C. Мне она кажется очень простой и максимально понятной. Следующим образом выведем классический «Hello, world!» на дисплей:
#include <OLED_I2C.h> // Подключаем библиотеку
OLED myOLED(A4, A5, A4); // Определяем пины
extern uint8_t SmallFont[]; // Подключаем шрифт
void setup()
{
myOLED.begin(); // Инициализируем дисплей
}
void loop()
{
myOLED.clrScr(); // Очищаем буфер дисплея
myOLED.setFont(SmallFont); // Инициализируем шрифт
myOLED.print("Hello, world!", CENTER, 0); // Выводим текст
myOLED.printNumI(123, CENTER, 20); // Выводим целое число
myOLED.update(); // Копируем буфер дисплея на дисплей
}
Если функции без параметров понятны сразу и не вызывают вопросов, то с функциями вывода на дисплей могут быть вопросы. Давайте сразу с ними разберемся, их существует всего три вида:
print(st, x, y) — печать строки на дисплей.
Параметры:
st: строка для печати;
x: координата верхнего левого угла первого символа по горизонтали;
y: координата верхнего левого угла первого символа по вертикали.
В качестве координат можно использовать как сами координаты, так и литералы LEFT, CENTER, RIGHT.printNumI(num, x, y, [length, [filler]]) — печать целого числа на дисплей.
Параметры:
num: Число для вывода на экран (от -2147483648 до 2147483647);
x: координата верхнего левого угла первой цифры/знака по горизонтали;
y: координата верхнего левого угла первой цифры/знака по вертикали;
length: <необязательный параметр> минимальное количество цифр для отображения на экране;
filler: <необязательный параметр> Символ для заполнения, чтобы получить минимальную длину. По умолчанию “ “.
В качестве координат можно использовать как сами координаты, так и литералы LEFT, CENTER, RIGHT.printNumF(num, dec, x, y, [divider, [length, [filler]]]) — печать числа с плавающей точкой на дисплей.
Параметры:
num: Число для вывода на экран (от -2147483648 до 2147483647);
dec: количество цифр после запятой (в дробной части) (допустимые значения 1-5);
x: координата верхнего левого угла первой цифры/знака по горизонтали;
y: координата верхнего левого угла первой цифры/знака по вертикали;
divider: <необязательный параметр> Одиночный символ для использования в качестве десятичной точки. По умолчанию '.';
length: <необязательный параметр> минимальное количество цифр для отображения на экране;
filler: <необязательный параметр> Символ для заполнения, чтобы получить минимальную длину.
По умолчанию “ “.В качестве координат можно использовать как сами координаты, так и литералы LEFT, CENTER, RIGHT.
Работа с ультразвуковым дальномером
Ультразвуковой датчик расстояния работает по принципу эхолокации — посылает пучок ультразвука и получает его отражение с некоторой задержкой, с помощью которой и можно высчитать расстояние до объекта. Работает датчик от напряжения в 5V на расстоянии от 2 до 400 сантиметров.
Для получения данных с датчика необходимо:
Подать на выход Trig импульс длительностью 10 микросекунд;
Трансмиттер отправит 8 импульсов с частотой 40 кГц;
Когда импульсы отразятся от препятствия и будут приняты ресивером, то на выходе Echo образуется входной сигнал;
С помощью формулы данные преобразуются в расстояние. Чтоб получить расстояние в сантиметрах, нам необходимо разделить ширину импульса на 58, для получения расстояния в дюймах — на 148.
Подключить датчик к плате можно следующим образом:
Финальный проект
Теперь, когда мы разобрались с работой с каждого элемента по отдельности, можно перейти к основному проекту дальномера.
Подключим все элементы к плате следующим образом:
Скетч проекта:
#include <OLED_I2C.h>
OLED myOLED(A4, A5, A4);
extern uint8_t SmallFont[];
// Инициализируем пины
int echoPin = 2;
int trigPin = 3;
void setup()
{
myOLED.begin();
// Определяем ввод и вывод
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop()
{
int duration, cm, inch;
// Генерация короткого импульса длительностью 2 микросекунды
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// В течении 10 микросекунд датчик посылает сигналы в 40 кГц
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Получаем время задержки с выхода Echo
duration = pulseIn(echoPin, HIGH);
// Находим расстояние в сантиметрах и дюймах
cm = duration / 58;
inch = duration / 148;
// Выводим информацию на дисплей
myOLED.clrScr();
myOLED.setFont(SmallFont);
myOLED.print("Centimeters:", CENTER, 10);
myOLED.printNumI(cm, CENTER, 20);
myOLED.print("Inches:", CENTER, 40);
myOLED.printNumI(inch, CENTER, 50);
myOLED.update();
}
Финальный проект в работе выглядит следующим образом:
Что дальше?
Проект дальномера готов и прекрасно работает, но несмотря на все, он не является идеальным законченным решением. Можно поработать над улучшениями, и сделать следующие:
Перенести все на монтажную плату и избавиться от макетки. Тогда получится цельное устройства без торчащих проводов;
Перейти на Arduino Nano ради более компактного размера;
Добавить автономное питание для работы без кабеля;
Изготовить корпус.