10 апреля, 2017 by Aviator
На выходных я получил из Китая очередную посылку с модулями для Arduino, и сразу же захотел применить их для уже знакомого нам робота-автомобиля. Тем более, что две попытки взлёта квадрокоптера обернулись неудачей и до прибытия новых пропеллеров работы по нему всё равно приостановлены.
При последней сборке робот-автомобиль анализировал окружающую его обстановку при помощи ультразвукового датчика-дальномера, который крепился на валу сервомотора, позволяющего поворачивать его влево и вправо. Конструкция получилась смешная, но робот часто утыкался носом в препятствия не замечая их. Ультразвуковой датчик тратил относительно много времени на замеры и слишком часто ошибался.
На замену ему были заказаны Инфракрасные датчики приближения! Цена из совсем смешная (меньше доллара), правда пришлось добавить ещё около двух долларов на стоимость доставки. Приехали довольно быстро, каждый датчик был запаян в отдельный метализированный пакет. У некоторых были слегка погнуты светодиоды (как на фото), но они легко выпрямились пальцами.
Принцип действия инфракрасного датчика приближения
При подаче питания на датчик сразу включается инфракрасный светодиод (прозрачный на фото). Он работает непрерывно, всё время работы датчика. Инфракрасное свечение совершенно незаметно для человеческого глаза, однако хорошо видно через любую цифровую камеру (например, мобильного телефона).
При наличии в зоне свечения светодиода препятствия (примерно на расстоянии 5-10 сантиметров), свет отражается и принимается фотодиодом (чёрный на фото).
Дополнительно, на плате датчика я заметил два светодиода красного цвета, которые очень помогают в настройке робота:
- первый светится всё время работы датчика, свидетельствует о наличии питания на плате и о работе инфракрасного светодиода.
- второй светится только при наличии в зоне действия ИК-светодиода освещённого им препятствия. Очень помогает визуально без дополнительных инструментов определить, сработал датчик или нет.
Подключение и настройка
На датчике три контакта:
- VCC (питание, +5 вольт)
- GND (земля, минусовой провод)
- OUT (выход, сигнал, информация о наличии препятствия).
Обратите внимание, порядок контактов на схеме подключения и на самом модуле (фото выше) отличается. При подключении внимательно читайте надписи на контактах!
При подключении модулей к контроллеру Arduino я стараюсь не пользоваться паяльником. Во-первых есть риск перегреть и сжечь дорогую электронику, во-вторых компоненты Arduino как правило многократно собираются и разбираются в различных комбинациях, а многократная пайка портит детали. Для решения этой проблемы я заказал недорогой комплект соединительных проводов трёх типов (мама-мама, мама-папа и папа-папа). Провода удобные, яркие, соединены между собой некрепко — можно оторвать нужное количество. Использовал только провода мама-мама, и столкнулся с необычайной жесткостью разьёмов. Чтобы надеть их на контакт, нужно приложить силу, достаточную для изгиба контакта, так что надевать их нужно очень осторожно. Ранее я использовал самопайные соединительные провода, сделанные из обрывков проводов со штекерами со старых компьютерных системных блоков (лампочки Power, HDD, кнопки Power, Reset, подключаемые от корпуса на материнскую плату). Вот с ними никаких проблем — надеваются и снимаются легко!
Закрепил я датчики на борту робомобиля в передней части корпуса, слева и справа от центра, чтобы робот по-разному реагировал на препятствия с разных сторон.
Итоги
При аналогичной скорости передвижения робот стал заметно умнее! Стал обнаруживать препятствия чётче, хоть и на меньшем расстоянии.
Однако был замечен глюк при очень ярком освещении (солнечный свет через окно). В этом случае датчики постоянно получали освещение и постоянно считали что препятствие перед автомобилем существует.
Фотогалерея
На деревянную «мачту» на платформе не обращайте внимания — это я пытался закрепить на высоте приёмник от инфракрасного пульта управления, но об этом — в следующей статье!
Текст программы управления:
int IN1 = 7; // Input1 моторшилда подключен к выводу 7
int IN2 = 6;
int IN3 = 5;
int IN4 = 4;
int EN1 = 8; //9
int EN2 = 3;
int i;
const int LeftIK = 0;
const int RightIK = 1;
void setup()
{
pinMode (EN1, OUTPUT);
pinMode (IN1, OUTPUT);
pinMode (IN2, OUTPUT);
pinMode (EN2, OUTPUT);
pinMode (IN4, OUTPUT);
pinMode (IN3, OUTPUT);
}
unsigned int impulseTime=0;
unsigned int dist1=0;
unsigned int dist3=0;
void loop()
{
int dist1 = analogRead(LeftIK); // Задаем переменную analogValue для считывания показаний
if (dist1<100) // Если датчик сработал
{
analogWrite (EN1, 0); // Остановить двигатели
analogWrite (EN2, 0);
digitalWrite (IN1, HIGH); // поменять полярность на обратную
digitalWrite (IN2, LOW); // то есть задний ход
digitalWrite (IN3, HIGH);
digitalWrite (IN4, LOW);
analogWrite(EN1, 250); // правое колесо назад
// analogWrite(EN2, 180); // левое не двигаем
delay(150);
analogWrite (EN1, 0);
analogWrite (EN2, 0);
}
int dist3 = analogRead(RightIK); // Задаем переменную analogValue для считывания показаний
if (dist3<100) // Если датчик сработал
{
analogWrite (EN1, 0);
analogWrite (EN2, 0);
digitalWrite (IN1, HIGH);
digitalWrite (IN2, LOW);
digitalWrite (IN3, HIGH);
digitalWrite (IN4, LOW);
// analogWrite(EN1, 0); // правое колесо не двигаем
analogWrite(EN2, 250); // левое колесо назад
delay(150);
analogWrite (EN1, 0);
analogWrite (EN2, 0);
}
if ((dist1>100) and (dist3>100))
{
// digitalWrite(ledPin, LOW);
digitalWrite (IN2, HIGH);
digitalWrite (IN1, LOW);
digitalWrite (IN4, HIGH);
digitalWrite (IN3, LOW);
analogWrite(EN1, 130); // Правое газ 130
analogWrite(EN2, 195); // ЛЕВОЕ газ 170
// разный газ для уравновешивания скорости колёс
}
}
Posted in Верстачок Tagged with: Arduino, робот
22 марта, 2017 by Aviator
Для компьютера — программа,
Для смартфона — приложение,
Для ардуино — скетч
В процессе сборки квадрокоптера F450 я удивлялся, как маленькая электронная плата может успевать получать данные, поступающие от всех датчиков (пульт управления, гироскопы, акселерометры, барометр, компас и GPS), обрабатывать их и на их основании управлять тягой каждого из моторов в отдельности, не давая при этом аппарату опрокинуться и заставляя его перемещаься в нужную точку! Оказывается вполне даже может, т.к. собран его полётный контроллер на базе микроконтроллера Arduino Mega.
Разновидности Arduino: Mega, Uno, Nano, Micro (Pro).
Что же такое Arduino — можно почитать в отдельной старой статье, а если вкратце — это микроконтроллер — печатная плата со своим процессором и памятью, к которой можно подключить множество устройств (датчики, модули, сенсоры, сервоприводы, двигатели, реле, другие контроллеры и т.д.), а затем при помощи особой программной среды (IDE) задать ему программу — посделовательность действий при определённых условиях.
Набор деталей для сборки робота-автомобиля
Для более глубокого изучения вопроса, в Китае был заказан набор деталей для сборки робота-автомобиля на базе Arduino Uno.
Комплектность
Прибыл набор довольно быстро, на таможне вопросов не вызвал. В комплекте обнаружились:
- Детали для сборки шасси — рама, винты, гайки.
- Два желтых двигателя с понижающими редукторами, два жёлтых колеса для них
- Третье колесо-ролик на подшипнике, свободно поворачивающееся в любую сторону
- Контроллер Arduino Uno (большая синяя на фото)
- Короткий USB-шнур для подключения Arduino к компьютеру
- Плата-щит Sensor Shied 5.0 для более удобного подключения проводов к контроллеру (зелёная плата на фото)
- Плата-драйвер для подключения моторов L298 (красная на фото)
- Ультразвуковой дальномер (синяя маленькая плата с двумя круглыми деталями)
- Сервомотор (синяя деталь с мотком провода) и комплект насадок для него
- Контейнер для четырёх AAA-батареек (батареек в комплекте нет)
- Поворотный кронштейн с местами под сервопривод
- Выключатель
- Краткая инструкция на китайском языке с картинками для сборки ШАССИ!
специальные провода для соединения компонентов Arduino
Несмотря на такую обширную комплектацию, это всё же не полный набор необходимых для сборки деталей. И я сейчас говорю не про батарейки! Прежде всего очень не хватает соединительных проводов. Нет, конечно обычные куски проводов можно найти даже на стройрынке, но сейчас я говорю о проводах со специальными штекерами на концах, для соединения компонентов Arduino между собой. Конечно кто-то может со мной поспорить, что всё можно соединить и при помощи паяльника если бы не два но: Во-первых, такую тонкую электронику нужно паять очень аккуратно, а это непросто. Во-вторых, в процессе сборки и настройки иногда возникает необходимость подключить провода по-другому, или просто отключить, а многократная пайка, пусть даже аккуратная на пользу платам не пойдёт. Также в комплекте не нашлось штекера питания самого контроллера, но я решил эту проблему по-своему…
Сборка
Итак, двигатели и колёса были прикручены довольно быстро, провода к двигателям были припаяны. Подразумевается что автомобиль должен передвигаться за счёт двух ведущих колёс, поворачивать за счёт их разницы в скорости, а третье поворотное колесо просто волочится сзади и даёт опору хвостовой части машины. Дальше работа стала, в связи с полной неизученностью электронной части набора.
Совсем немного поискав по интернету, я нашёл, скачал и установил среду программирования IDE, однако при подключении через USB компьютер увидел только «неизвестное устройство». Ещё немного танцев с бубном, поиск по интернету, скачивание определённого драйвера и вот, устройство появилось в системе в видео последовательного порта COM10.
Cхема подключения двух двигателей
Самой первой, и наверное, самой сложной задачей явилось подключение двигателей. Подключение по задумке китайцев должно происходить через плату MotorShield (драйвер двигателей) L298. Это позволит разделить цепь питания самого контроллера Arduino (стабильные 5вольт, а если через круглый штекер, то до 9вольт) от цепи питания двигателей (до 30 вольт). Наши двигатели способны питаться от напряжения от 3 до 12вольт, так что наш контейнер батареек выдающий 6 вольт вполне подходит. Схему подключения двигателей я нашёл на сайте Zelectro.cc (не забудьте снять две перемычки с красной платы!), там же пример программы для управления двигателями. Дальше было подключено питание к самому контроллеру, и вот, автомобиль уже поехал по ковру! Беспорядочно… вернее не оценивая окружающую обстановку, вращал поочерёдно каждым колесом сначала вперёд, затем назад! И это уже был первый успех которому я радовался как ребёнок!
Вторым этапом, поверх контроллера был установлен щит SensorShield 5.0 по принципу бутерброда. Штекера расположены таким образом, что ошибиться в установке трудно, если конечно не применять медвежью силу.
Плата управления двигателя была подключена на контакты щита с теми же номерами, здесь особого супер-удобства я ощутить не успел. А вот в дальнейшем, когда я подключал ультразвуковой дальномер и сервомотор, то я оценил отсутствие лишних проводов питание и земли, тянущихся в другой конец платы. Всё было подключено стандартными штекерами за соседние ножки. Собирать кронштейн для сервомотора я не стал, посчитал его лишней деталью. Сам сервомотор я укрепил на шасси, а затем ультразвуковой датчик закрепил на валу сервомотора при помощи всем известного термопистолета и клея «горячие сопли».
Отдельно приводить программу управления каждым устройством в отдельности не буду, без труда найдёте их на zelectro.cc, лучше я не напишу. А вот полную получившуюся программу приведу. Она заставляет машину ехать вперёд, постоянно вращая «головой» (дальномером) и определяя, есть ли препятствия справа и слева по ходу движения. И в случае обнаружения препятствия машинка останавливается, и для разворота вращает назад одно из колёс — либо правое либо левое, смотря с какой стороны обнаружено препятствие.
Итоги
Бегает автомобильчик довольно резво и весело, но как работает ультразвуковой сенсор мне не понравилось. Иногда не замечает мягких препятствий (подушка или мягкое кресло) и просто утыкается в них носом. Поэтому на будущее я заказал несколько инфракрасных датчиков, чтобы определение препятствий происходило оптическим путём. Также заказал инфракрасный пульт с приёмником — хочу заставить робота подчиняться командам с пульта!
А вообще — пробуйте, собирайте, программируйте, и придумывайте свои схемы взаимодействия электронных компонентов! Его возможности ограничиваются только вашей фантазией!
А теперь, обещанный текст программы:
#include <Servo.h>
Servo myservo;
int IN1 = 7; // Input1 моторшилда подключен к выводу 7
int IN2 = 6;
int IN3 = 5;
int IN4 = 4
int EN1 = 8; //9
int EN2 = 3;
int i;
#define Trig A0
#define Echo A1
// #define ledPin 13
void setup()
{
pinMode (EN1, OUTPUT);
pinMode (IN1, OUTPUT);
pinMode (IN2, OUTPUT);
pinMode (EN2, OUTPUT);
pinMode (IN4, OUTPUT);
pinMode (IN3, OUTPUT);
pinMode(Trig, OUTPUT); //инициируем как выход
pinMode(Echo, INPUT); //инициируем как вход
Serial.begin(9600);
// pinMode(ledPin, OUTPUT); // светодиод для отладки
myservo.attach(13);
}
unsigned int impulseTime=0;
unsigned int dist1=0;
unsigned int dist2=0;
unsigned int dist3=0;
void loop()
{
myservo.write(0); // Поворачиваем голову на ПРАВО
digitalWrite(Trig, HIGH); // Посылаем ультразвуковой импульс
delayMicroseconds(10); // равный 10 микросекундам
digitalWrite(Trig, LOW); // Отключаем
impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса
dist1=impulseTime/58; // Пересчитываем в сантиметры
delay(100);
if (dist1<30) // Если расстояние менее 30 сантиметром
{
analogWrite (EN1, 0); // Остановить двигатели
analogWrite (EN2, 0);
digitalWrite (IN1, HIGH); // поменять полярность на обратную
digitalWrite (IN2, LOW); // то есть задни ход
digitalWrite (IN3, HIGH);
digitalWrite (IN4, LOW);
analogWrite(EN1, 250); // правое колесо назад
// analogWrite(EN2, 180); // левое не двигаем
delay(150);
analogWrite (EN1, 0);
analogWrite (EN2, 0);
}
myservo.write(90); // поворачиваем голову налево
digitalWrite(Trig, HIGH);
delayMicroseconds(10); // равный 10 микросекундам
digitalWrite(Trig, LOW); // Отключаем
impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса
dist3=impulseTime/58; // Пересчитываем в сантиметры
delay(100);
if (dist3<30) // Если расстояние менее 30 сантиметром
{
analogWrite (EN1, 0);
analogWrite (EN2, 0);
digitalWrite (IN1, HIGH);
digitalWrite (IN2, LOW);
digitalWrite (IN3, HIGH);
digitalWrite (IN4, LOW);
// analogWrite(EN1, i);
analogWrite(EN2, 250); // левое колесо назад
delay(150);
analogWrite (EN1, 0);
analogWrite (EN2, 0);
}
if ((dist1>30) and (dist3>30))
{
// digitalWrite(ledPin, LOW);
digitalWrite (IN2, HIGH);
digitalWrite (IN1, LOW);
digitalWrite (IN4, HIGH);
digitalWrite (IN3, LOW);
analogWrite(EN1, 130); // Правое
analogWrite(EN2, 180); // ЛЕВОЕ
delay(100);
}
delay(100);
/* ждем 0.1 секунды, Следующий импульс может быть излучён, только после исчезновения эха от предыдущего.
Это время называется периодом цикла (cycle period).
Рекомендованный период между импульсами должен быть не менее 50 мс. */
}
Posted in Верстачок Tagged with: Arduino, робот