Хабрахабр

[Из песочницы] Машинка на Arduino, управляемая Android-устройством по Bluetooth, — полный цикл (часть 1)

Введение

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

Немного об уровне, авторе и предостережения

Я, автор, пацан 16-17 лет с подмосковной деревни, специализируюсь на написании android-приложений (а там сложнее что-то сжечь), поэтому ответственность за оптимальный подход к решению задач с себя снимаю.

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

Задача

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

Понадобится

  1. Arduino
  2. Motor Shield (в моем случае две)
  3. Bluetooth
  4. Android
  5. Провода обычные

Основа конструкции

За основу была взята машина Lego Outdoor Challenger (в реальности выглядит менее пафосно). Все, что от нее осталось: корпус (все элементы украшения сняты) и три двигателя.
image
У машинки была своя плата, но одна из задач подразумевала универсальность: это сделал я, это смогут повторить другие. Мозги вынул, поставил Arduino Uno.

Установка Arduino

Создатели почему-то не предусмотрели места для Arduino, потому крепил на шурупы, просверлив пластик. Под плату подложил фанеру, чтобы ничего не закоротило. Под шурупы лучше подсунуть что-то пластиковое (кусочек бутылки), ибо плата от железный болтов не защищена.

Чтобы управлять второй, придется прокинуть один провод с любого digital порта на H1 (направление) и второй с пина с поддержкой шима (помечены знаком «~», обычно 10, 11) на E1 (скорость). Поверх платы сразу поставил две motor shiled, так надо.

Определение угла поворота

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

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

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

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

Например, когда ток есть на всех линиях, колеса повернуты в крайнее правое положение, когда ток есть только на верхней, колеса повернуты максимально влево. Благодаря различным комбинациям трех полос, можно определить до семи углов. В таблице предоставлены все варианты.

Подключение угла и код

Для каждого уровня был выбран свой цвет: нижний – зеленый, первый снизу – красный, второй – черный, третий – белый. На начальном этапе использовались breadboard и светодиоды для визуальной отладки.

Плюс тянем к зеленому, остальные протягиваем к минусу. Схема подключения показана на рисунке. Выбраны они просто из экономии остальных портов. Через резистор, установленный для устранения помех и отсутствия КЗ, подключаем провода к выходам A0-A2.

Подключаем пины и опрашиваем их через digitarRead(). Код дан с комментариями. Далее смотрим, если результат означает, что колеса в крайних положениях, запрещаем дальнейший поворот в эту сторону. Если напряжение есть, вернется значение true.

3В понадобятся в будущем, можно поставить плюс на один из digital-пинов. Небольшая хитрость: поскольку выходы на 5В и 3. Перед каждой проверкой угла выдавать ток через digitalWrite(whitePin), потом проверять угол и убирать ток.

int speedTurn = 180; //скорость поворота, от 0 до 255 //пины для определения поворота
int pinRed = A0;
int pinWhite = A1;
int pinBlack = A2; int pinAngleStop = 12; //выводит ток на светодиод, если достигнут максимальный угол, нужен //только для отладки void setup() { //пины поворота на считывание pinMode(pinRed, INPUT); pinMode(pinBlack, INPUT); pinMode(pinWhite, INPUT);
//светодиод pinMode(pinAngleStop, OUTPUT);
//пины драйвера двигателя, направление и скорость pinMode(angleDirection, OUTPUT); pinMode(angleSpeed, OUTPUT); Serial.begin(9600);
}
//функция вызывается из loop(), когда приходит команда с андроида
void turn(int angle) //если угол не максимальный, поворачиваем digitalWrite(angleDirection, HIGH); analogWrite(angleSpeed, speedTurn); } else if (angle < 31) { if(digitalRead(pinRed) == HIGH && digitalRead(pinBlack) == HIGH && digitalRead(pinWhite) == HIGH) { //если достигнуто крайне левого положение, выйти из функции не подавая ток, чтобы не //сжечь мотор return; } //если угол не максимальный, поворачиваем digitalWrite(angleDirection, LOW); analogWrite(angleSpeed, speedTurn); } digitalWrite(pinAngleStop, LOW); //убираем ток с определителя угла delay(5);
}

Распараллеливание ходовых колес

Изначально два ходовых двигателя соединены вместе. Их рассоединил по двум причинам: поворот эффективней, если колеса крутятся в разные стороны, и два мощных двигателя одна плата не вытянет.

Каждый двигатель ест по 0,7А. Проблема: у motor shield два выхода, каждый из которых выдает до 2 ампер. Допустим, машинка застряла в песке или уперлась, ток возрастает выше ампера. Вроде меньше, но не при максимальных нагрузках. Не критично, но потенциально опасно.

Через минуты полторы после заезда, motor shield нагревалась и начинала работать безобразно: токи подаются не те, колеса не крутятся и прочее. А вот критичным оказалось то, что плата греется.

Как ни странно, помогло. Решение обоих проблем: один двигатель подключил к одной motor shield, второй – к другой. Можно было поставить радиатор, но крепить тяжело. Температура упала, перегрев отсутствует.

Подключение Bluetooth

Я использовал модель HC-05, что сыграло роковую шутку. Подключаются все блютузы одинаково: один провод на 3.3В (иногда начинал работать только от 5В), второй на минус, еще два на порт 0 и 1 (чтение и отправка соответственно). Провод, подписанный RXD на bluetooth, втыкается в TXD ардуино, а TXD в RXD (если перепутаете, то данных не увидите).

То есть, пока воткнут блютуз, скетч не зальется. Есть оговорка: порты 0 и 1 по умолчанию используются Serial, через который заливает скетч. Второй вариант осуществляется двумя строчками Есть два выхода: вынимать блютуз на время заливки или переназначить входы и выходы блютуза.

#include <SoftwareSerial.h> \\подключение библиотеки
SoftwareSerial BTSerial(8, 9); \\установка 8 и 9 пина заместо 0 и 1

Подводный камень, съевший у меня трое суток работы – скорость общения. По привычке установил 9600 и пошел пробовать. То данные не приходили, то была каша символов. И в конце концов ответ – модель HC-05 общается на 38400! Очень сильно обратите внимание на то, что в Setup() я выполню BTSerial.begin(39400), хотя Serial.begin(9600).

Система отправки команд

Статья становится слишком длинной, поэтому рассмотрение кода Arduino и Android вынесу в отдельную вторую часть, а сейчас опишу принцип.

Андроид считывает показания с него и конвертирует их в подходящие для ардуино числа: скорость из пикселей превращает в значение от -255 до 255 (отрицательные – задний ход), а также определяет угол. На андроид устройстве есть джойстик (круг, о реализации которого также во второй части). Я сознательно отдал эту задачу телефону, так как он куда мощнее и спокойно справится с подсчетом нескольких сотен значений в секунду.

@ — говорит о том, что следующие цифры содержат скорость, # — извещает об окончании значения скорости, * — начало значения угла, # — закончить запись угла. После установки сокета данные отправляются в следующем формате: @скорость#*угол#. Если ничего не нажато на андроиде, то ничего и не отправляется. Цикл бесконечен, команды отправляются каждые 100 миллисекунд (цифра подобрана оптимальная).

Он не раз переписывался и, как по мне, работает идеально. Алгоритм приема данных подробно описан в коде скетча.

Заключение первой части

В этой статье я попытался раскрыть все, что касается физической части машинки. Вероятнее всего, что-то упустил, так что обязательно спрашивайте.

Но самое интересное, как по мне, осталось на второе – программа Arduino и приложение на Android, там творится настоящая магия, по крайней мере, для молодого меня.

Если вы не найдете ответа на какую-то часть и захотите потыкать меня в недостатки лично, жду – dendolg1@mail.ru, .

Теги
Показать больше

Похожие статьи

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть