CxemCAR - Android-управление машинкой по Bluetooth. CxemCAR на Arduino - Bluetooth управление машинкой с Android !!! терминалы, разъемы, клещи можно заменить

Мой компьютер

Не будем покупать плохие игрушки у Китайцев, а купим у них дешевый конструктор-шасси, несколько модулей и приложим руки!

Вот что у меня получилось в итоге: проходимое шасси, управляемое - ТА-ДА!!! - с моего смартфона на Андроиде.


«Я и прямо, я и боком,
С поворотом, и с прискоком,
И с разбега, и на месте,
И двумя ногами вместе…»

Сегодня мы соберём забавную машинку с дистанционным управлением по Bluetooth. Исходники программы управления под Android в комплекте.

Достойный образец игрушки

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

Почему так? Наверное потому что эта пила продавалась в магазине инструментов «STIHL». Как я полагаю, «STIHL» сделал игрушечный аналог своей продукции небольшим рекламным тиражом. В результате появилась на свет вполне вменяемая игрушка, очень похожая на своего старшего брата. Цепь резиновая – крутится, процентов на 80 реализованы органы управления. Есть даже шнур с ручкой для завода пилы, выключатель, кнопка газа. В комплекте есть запасная цепь и инструмент для смены цепи.


Вот такая игрушечная пила

О чём это я? Ах, да, об архитектуре! Это я к тому, что при желании отличную игрушку сделать можно. И есть на что равняться.

Будем строить машинку с ДУ!

Практический и технический интерес вызывают игрушки с радиоуправлением. Однако, ребёнку в возрасте 4-6 лет не будут дарить игрушки со «взрослым» пропорциональным управлением. Скорее всего, игрушка будет сломана, а деньги выкинуты на ветер.
В итоге, обычно дарят что-то недорогое. Из всего этого – «недорогого» - машинки или шибко быстрые или тормозные; танки хилые; и прочие очевидные и скрытые недостатки. И уж конечно никакого пропорционального управления.

В один прекрасный день у одной из машинок перестало вращаться правое колесо. Разобрал, проверил моторчик – исправный.
На плате управления три микросхемы – Китай голимый, вменяемой документации найти не смог. Один чип – приёмник радиосигнала с логическими выходами и два мостовых драйвера двигателей. Один из драйверов вышел из строя. Сваять сходу мостовой драйвер двигателя из дискретных компонентов у меня не получилось.

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

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

Как я выбирал шасси

Во-первых, я выбрал наземный вид транспорта, значит и шасси у меня будет наземное. Гусеничные шасси, как правило, дороже и не слишком быстроходные. Двух-трёх-колесные мне кажутся слабо проходимыми, такое шасси сможет ездить только по ровной поверхности.
Я остановился на . По моему мнению, такое шасси будет обладать отличной проходимостью и скоростью.


В комплекте поставки шасси:
две пластины из акрила с кучей технологических отверстий для крепления все возможных датчиков, плат управления и прочих компонентов
4 колеса
4 привода в сборе (электродвигатель + редуктор)
4 диска с прорезями для датчиков скорости, по одному на каждое колесо
крепеж
Да, это снова Китай. Да, дешёвый. Да, нешибко качественный. НО! Нам бы для начала попробовать. Ведь «взрослое» шасси и стоит по-взрослому, мы до него ещё не доросли.

Болото мыслей и Техзадание

Когда держишь в руках перспективную вещь, например, в плане возможностей по обвесу модели всевозможными датчиками, серво и пр., начинаешь тонуть в болоте мыслей и трясине перспектив. Но, скажем себе - СТОП! И составим себе мини-ТЗ на прототип с кратким описанием всех узлов.
У нас должна получиться RC-модель наземного траспортного средства с управлением по Bluetooth, с возможностью реверса и плавного регулирования скорости вращения колес.

Что нам потребуется для сборки машинки?

.


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


Для дистанционного управления машинкой используем канал Bluetooth. Модуль «HC-06» - это мост Bluetooth, последовательный интерфейс, позволяющий передавать данные в обе стороны. На входе - TTL-сигналы последовательного интерфейса «RxD» и «TxD» для подключения к микроконтроллеру (целевой плате).
В качестве пульта дистанционного управления будет служить сотовый телефон с Android. Напишем свою программу!



Драйвер двухканальный, на левую и правую пару колес. Драйвер имеет логические входы для изменения полярности выхода (направления вращения) и вход ШИМ, можно будет сделать управление скоростью вращения.


Выбрана эта плата т.к. валялась в ящике стола и полностью подходит для нашей цели. Есть дискретные входы/выходы, выведены сигналы МК «RxD» и «TxD», куда будет подключен «HC-06“.
Забегая вперёд скажу, что продукт Олимекс MOD-IO - это жёсткий перебор. Прекрасно можно будет применить и обычную , о чём в продолжении истории!

Итого: шасси + плата управления + Bluetooth-модуль + программа управления под Android.

Общая схема подключения

Не схема в чистом виде, а именно схема подключения, так как все платы у нас уже готовые, и остаётся их соединить между собой.

Схема в Протеусе


Расписывать, что и куда я подключил не буду. Скорее всего у вас будет другая плата управления. Исходники я прикладываю, так что прошивку сможете править. Ну, а если кто-то не в силах скомпилировать прошивку под свою плату, обращайтесь - помогу по мере свободного времени.

Программа микроконтроллера

Программа МК умеет принимать команды по последовательному интерфейсу с Bluetooth-модуля.
И, в соответствии с командами, управлять левой и правой парой приводов. Реверс и управление скоростью работают при помощи ШИМ.

Код в достаточной мере прокомментирован. Хочу отдельно остановиться на моей реализации обмена данными.
Приём данных у меня реализован через кольцевой буфер. Вещь не новая и реализаций много.

Функции кольцевого буфера у меня вынесены в отдельную библиотеку состоящую из:
заголовочного файла ring_buffer.h и файла реализаций функций ring_buffer.с
Для использования библиотеки её нужно подключить в main.c
#include "ring_buffer.h"

Далее, в заголовочном файле необходимо настроить библиотеку. Для настройки необходимо задать всего четыре директивы:
#define RX_PACKET_SIZE 7 // Размер RxD пакета #define BUFFER_SIZE 16 // Размер приёмного буфера. Должен быть в два раза больше RX_PACKET_SIZE #define START_BYTE "s" // Стартовый байт #define STOP_BYTE "e" // Стоповый байт

Собственно настраивать больше нечего.

Использование кода В main.c настраиваем USART микроконтроллера.
Вызываем функцию настройки USART
USART_Init(MYUBRR);

#define BAUD 9600 #define MYUBRR F_CPU/16/BAUD-1 void USART_Init(unsigned int ubrr) { /* Set baud rate */ UBRRH = (unsigned char)(ubrr >> 8); UBRRL = (unsigned char)ubrr; /* Enable receiver and transmitter */ UCSRB = (1 << TXCIE) | (1 << RXCIE)| (1 << TXEN) | (1 << RXEN); /* Set frame format: 8data, 2stop bit */ UCSRC = (1 << URSEL) | (0 << USBS) | (3 << UCSZ0); }

Приём пакета данных

В функции обработчика прерывания приема байта по USART, нам необходимо всего лишь положить принятый байт в кольцевой буфер. Разбор пакета будем делать потом.
ISR(USART_RXC_vect) { uint8_t Data = UDR; RB_push_char(Data); // Складываем принятый байт в кольцевой буфер }
Да, я пока пренебрег всякими проверками фрейма.

Теперь нам остается время от времени проверять наш буфер. Для этого я инициировал таймер, в котором я устанавливаю флаг разрешающий проверку кольцевого буфера
ISR(TIMER0_OVF_vect) { TCNT0 = 0x64; ReadRingBuffer = 1; }

В основном цикле добавляем условие для проверки флага.
if (ReadRingBuffer) { if (RB_read_buffer((uint8_t*)&RxPacket) == 1) Чтение буфера { // Разбираем пакет, делаем что-нибудь } ReadRingBuffer = 0; }

Функция RB_read_buffer проверяет кольцевой буфер, если размер пакета, стартовый и стоповые байты находятся на своих местах - пакет считается валидным, функция возвращает "1». В качестве аргумента, функция принимает указатель, куда складывать принятый пакет.
Для пущей надежности, пакет можно снабдить контрольной суммой, в одном из своих коммерческих проектов я так и сделал. То есть к проверке размера, старт/стопового байтов прибавляется еще проверка контрольной суммы. Но пока обойдемся без неё.

Как я разбираю пакет

Теперь самое интересное, как я разбираю пакет. В пакете могут передаваться данные размерностью больше байта, знаковые данные, данные с плавающей точкой.
Объясню на примере пакета для управления шасси. Кроме стартового и стопового байтов, в своём пакете мне необходимо передавать одну команду, и два значения ШИМ, для левой и правой стороны приводов. Для команды мне достаточно одного байта, а для каждого значения ШИМ, я передаю int16 - 16 бит, знаковый тип. То есть, я не передаю флаг (байт/признак) направления. Для смены направления, я передаю положительное или отрицательное значение ШИМ.

Приёмный пакет у меня организован в виде структуры.
struct RxPacket { uint8_t StartByte; uint8_t Command; int16_t Left_PWM; int16_t Right_PWM; uint8_t StopByte; } RxPacket;

Вызывая функцию RB_read_buffer ((uint8_t*)&RxPacket ) , в качестве аргумента передаем указатель на структуру приёмного пакета. То есть, при принятом пакете, будет все разложено по своим полочкам в структуре RxPacket. Дальше остается прочитать эти данные из структуры например так:
lCmd = RxPacket.Command; lLPWM = RxPacket.Left_PWM; lRPWM = RxPacket.Right_PWM;

Передача пакета данных

Хоть в моей программе передача пока не используется, тем не менее, возможность передачи реализована. Передавать данные проще. Точно также, как и для приемного пакета, создадим структуру:
struct TxPacket { uint8_t StartByte; uint8_t Rc5System; uint8_t Rc5Command; uint8_t StopByte; } TxPacket;

Где, есть стартовый и стоповый байт и информационная часть. Мы уже инициализировали приемник USART.
Для инициирования передачи пакета - вызываем функцию
void send_packet() { // Запись стартового байта в регистр UDR UDR = START_BYTE; }
В данном примере, в этой функции, я записываю только стартовый байт в регистр UDR. Вроде бы немного, но в этой же функции можно реализовать подготовку пакета или еще что-то полезное. И это, на мой взгляд более логично. Логично в плане самодокументирования кода. То есть, если я в коде, просто запишу значение в регистр UDR это может быть воспринято, как передача всего одного байта, а вызывая самоговорящую функцию send_packet () - я говорю о том, что я отправляю пакет данных.

Далее, когда передатчик USART отправит весь байт из регистра UDR - будет вызван обработчик прерывания по передаче.
ISR(USART_TXC_vect) { unsigned char *Pointer = (unsigned char *)&(TxPacket); static unsigned char TxIndex = 1; if (TxIndex < sizeof(TxPacket)) { UDR = *(Pointer + TxIndex); TxIndex++; } else TxIndex = 1; }

В обработчике я объявляю переменную указателя и присваиваю её адрес структуры TxPacket. Далее объявляется статическая переменная - индекс передаваемого байта, которой при объявлении присвоено значение 1 . Начинаем с одного потому, что первый байт из структуры мы уже отправили. В целом, в структуре можно обойтись и без стартового байта, все равно я его отправляю отдельно, но объявления этого байта оставлено в структуре для понимания того как выглядит пакет.

Условие if (TxIndex < sizeof(TxPacket)) проверяет, что индекс меньше чем размер пакета. Если условие верно, то записываем байт в регистр UDR: UDR = *(Pointer + TxIndex);
инкрементируем TxIndex. Когда USART передаст очередной байт, то мы снова попадём в обработчик, но будет передан уже следующий байт из структуры и так будут переданы все байты структуры. Когда TxIndex будет больше чем размер структуры - условие будет не верно и мы попадем в else TxIndex = 1; Где будет проинициализирован TxIndex, но в регистр UDR уже ничего не записывается, соответственно обработчик больше не будет вызван до следующего инициирования передачи пакета. Таким образом, процесс передачи полностью автоматический, и даже, если мы изменим структуру пакета, то обработчик переписывать не придётся.

В рамках описания программы МК осталось рассказать про реализацию управления драйверами. Драйвер управляется тремя сигналами: A1 (B1), A2 (B2) и PWMA (PWMB). A1 и A2 предназначены для включения/выключения драйвера и для изменения полярности выхода. На вход PWMA подается ШИМ сигнал с МК - можно управлять скоростью вращения. Для ШИМ сигнала я задействовал два аппаратных ШИМа таймера 1.
#define _WGM13 0 #define _WGM12 1 #define _WGM11 0 #define _WGM10 1 // Timer 1 init TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (_WGM11 << WGM11) | (_WGM10 << WGM10); TCCR1B = (0 << CS12) | (0 << CS11) | (1 << CS10) | (_WGM13 << WGM13) | (_WGM12 << WGM12); TCNT1 =0x0000; OCR1A = 0; OCR1B = 0;

Таймер 16-битный, но ШИМ инициализирован на 8 бит. И как вы наверное уже заметили, в приёмном пакете у меня есть два значения для задания ШИМ, для левого и правого привода соответственно. Переменные знаковые 16-битные.
Объясню почему я так сделал.

Во-первых , это пошло от программы под Андроид. Дело в том что в Java нет без знаковых типов и я уже наступал на эти грабли. И для передачи числа от 0 до 255 мне пришлось бы как то извернуться. Я решил пойти более простым путем - отсылаю знаковое 16-бит число. При этом, 16 бит знакового типа это от -32786 до 32768, нам хватит.

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

И в-третьих , как не крути, для наших целей меньше чем в три байта не уложиться. Пожертвуем еще одним байтом, зато всё становится понятно, положительное значение ШИМ - прямое вращение, отрицательное значение - обратное вращение.

Для управления приводами я написал функцию drive (int leftPWM, int rightPWM); .
void drive(int leftPWM, int rightPWM) { // Движение ВПЕРЁД левое колесо if (leftPWM > 0){ ClearBit(A2_PORT, A2_PIN); SetBit(A1_PORT, A1_PIN); } // Движение НАЗАД левое колесо if (leftPWM < 0){ ClearBit(A1_PORT, A1_PIN); SetBit(A2_PORT, A2_PIN); } // Движение ВПЕРЁД правое колесо if (rightPWM > 0){ ClearBit(B2_PORT, B2_PIN); SetBit(B1_PORT, B1_PIN); } // Движение НАЗАД правое колесо if (rightPWM < 0){ ClearBit(B1_PORT, B1_PIN); SetBit(B2_PORT, B2_PIN); } // Остановка if (leftPWM == 0){ ClearBit(A1_PORT, A1_PIN); ClearBit(A2_PORT, A2_PIN); } // Остановка if (rightPWM == 0){ ClearBit(B1_PORT, B1_PIN); ClearBit(B2_PORT, B2_PIN); } set_PWM((uint8_t)(abs(leftPWM)), (uint8_t)(abs(rightPWM))); }
В соответствии со значением ШИМ, осуществляется управление сигналами A1 (B1), A2 (B2) и устанавливается значение ШИМ вызовом функции set_PWM (leftPWM, rightPWM) .

Уфф, выдохся…
Подытожим: приняли пакет, разобрали, передали значение ШИМ в функцию drive .

Приложение под Android для машинки

Нет, так подробно, как программу для МК я разбирать не буду. В разработке ПО под Android я ещё новичок и не готов рассказывать достаточно компетентно и глубоко.

Основная функция программы - передача данных модулю HC-06 по каналу Bluetooth. Программа имеет не замысловатый интерфейс.

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

Дальше кнопка «Выкл» - включает/отключает связь с «HC-06». Ниже слева направо: передаваемое значение ШИМ левого канала, тип датчика, значение правого канала. Ниже два слайдера регулировки чувствительности скорости и поворота.

В программе реализовано два типа управления машинкой. Для переключение типа датчика нужно коснуться надписи названия датчика: «Наклон» или «Шаркать».

1. Управление машинкой с помощью наклона телефона. Нулевое положение телефона - горизонтальное. При наклоне телефона вперед значение ШИМ увеличивается пропорционально наклону в диапазоне от 0 до 255 . При наклоне телефона назад значение ШИМ уменьшается пропорционально наклону в диапазоне от 0 до -255


Что бы повернуть влево или вправо - нужно наклонить телефон вперед или назад и, одновременно, влево или вправо соответственно. Да, как в настоящей машине, пока не поддашь газку поворот не осуществляется.

2. Управление касанием. Моё фирменное название для такого управления - «шаркать».


Можно воспринимать как тачпад. При касании в сером квадрате, значение ШИМ увеличивается/уменьшается в зависимости от места касания, чем дальше от центра вниз или вверх тем больше/меньше значение.

Никаких «красивостей» и наворотов нет. Вот вроде бы и всё.

Немножко дёгтя на «лыжи»

Есть косяк у моего телефона. Ага, телефон «лыжа» - LG G2 mini. На нём соединение по Bluetooth устанавливается неадекватно. Соединение устанавливается нормально только, если Bluetooth был включен непосредственно перед запуском приложения.
Я сделал так: при запуске приложении проверяю включен ли Bluetooth, если выключен - делаю запрос на включении. А при «сворачивании», закрытии приложения - принудительно выключаю Bluetooth.
И еще один момент, при смене ориентации экрана, Bluetooth выключается и снова выдается запрос на включения, приходится выключать автоматическое переключение разворота экрана.

Резюме

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

Есть еще поле для деятельности, есть куда расти. Можно «наворачивать» шасси, можно модернизировать и улучшать ПО для телефона.
И об этом будет продолжение!

После приобретения недорогого 7" китайского планшета и экспериментами с взаимодействием с Arduino по USB и Bluetooth захотелось сделать что-то более серьезное и полезное для своих детей. Так родилась идея сделать машинку с управлением от акселерометра Android-устройства и связи по Bluetooth каналу. До этого я никогда не увлекался робототехникой или РУ управлением, но желание было. Были поставлены три цели:

1. Сделать максимально простое для повторяемости устройство, которое сможет повторить любой начинающий радиолюбитель, айтишник, программист, домохозяйка. Т.е. минимум пайки, и (да простят меня радиолюбители), а основной упор сделать на готовые, дешевые и главное доступные модули, которые без проблем можно приобрести. Хотя конечно ничто не мешает спаять собственную отладочную плату или драйвер двигателей.
2. Проект полностью должен быть Open Source и мультиплатформенным. В качестве железной части использовать все популярные и современные аппаратно-программные платформы: Arduino (Processing), STM32, MSP430, PIC, AVR, и может быть даже .
3. Алгоритм управления полностью разработать самому с нуля, не читая при этом заумных книг по роботостроительству, а также сделать его максимально простым. Ну а в дальнейшем, уже можно будет повысить свой скил читая специализированную литературу и сделать более совершенное управление.

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

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

Данные обрабатываются и передаются по Bluetooth каналу на контроллер машинки, который в свою очередь через драйвер двигателей управляет моторчиками машинки.

Компоненты

Итак, первое что прежде всего потребуется - это любое Android устройство: смартфон, планшет, часы и т.п., желательно с датчиком наклона (акселерометром) и Bluetooth (или возможностью подключения внешнего модуля через USB OTG). Я использовал китайский Ainol Aurora с внешней USB Bluetooth флэшкой. Цена такого устройства на сегодняшний день составляет менее 100$.

2. Шасси для машинки

Также понадобится любое шасси с 2-мя или 4-мя моторчиками. Это может быть как шасси для DIY проектов, так и шасси от старой б/у радиоуправляемой машинки.
Я купил готовое шасси на eBay. Кто еще не знаком с интернет-аукционом eBay, рекомендую для прочтения эту статью: . Гарантирую, что сэкономите немало денег покупая там, а не здесь у перекупов. Также, можно воспользоваться и другими китайскими магазинами: www.aliexpress.com, dx.com и др. Найти шасси довольно легко, достаточно в поисковую строку вбить одно из словосочетаний: Robot chassis, Robot platform, DIY Car chassis и др. Стоимость варьируется от 20$ до 60$.

При выборе шасси обращайте внимание на питание и мощность двигателей, а также на обороты моторчиков и наличие редуктора. Хотя большинство платформ содержат стандартный 6В моторчик с редуктором.

Для принципа управления описанного в данном проекте, больше всего подходит гусеничная платформа, но т.к. у меня пока что ее нет, я реализовал проект на основе 4WD платформы.

3. Контроллер машинки

Как я уже говорил, проект планируется сделать мультиплатформенным. На текущий момент проект CxemCAR реализован для следующих аппаратных платформ:

  1. STM32
  2. Arduino
  3. .NET Micro Framework

"Мозги" робота не требовательны к быстродействию МК и количеству периферии, необходимый минимум, который должен поддерживать микроконтроллер: 2 ШИМ и UART.

Если вы никогда не имели дело с микроконтроллерами, то я советую вам для начала собрать этот проект на платах Arduino, т.к. во первых они достаточно дешевы (10-15$), а во вторых в сети и на этом сайте полно примеров, мануалов и т.п. Контроллеры STM32 и MSP430 более функциональны, но для новичка будут сложнее в освоении. Ну а для программистов, понравится один из вариантов данного проекта на с.NET Micro Framework, где в качестве среды программирования используется Microsoft Visual C# Express. Но нужно учесть, что сами платы FEZ не сильно распространены и купить их проблематично, хотя существует.NET вариант под Arduino форм-фактор под названием Netduino.

4. Bluetooth модуль

В качестве Bluetooth модуля использован дешевый китайский UART модуль HC-06. Подойдут модули вида HC-03, HC-04, HC-05, HC-06, да и вообще любые Serial Bluetooth. Лучше брать с готовыми штыревыми выводами, чтобы не пришлось паять, т.к. расстояние между выводами очень маленькое (см. 1-ой на фото внизу). Стоимость такого модуля на eBay составляет в среднем 5-10$.

Bluetooth модули и работа с ними применительно к Arduino, неплохо описаны в . Для других контроллеров все практически тоже самое, с описанием связи по Bluetooth между STM32 и Android.

5. Драйвер двигателя

В качестве драйвера я использовал специализированную микросхему L298N, которая представляет собой сдвоенный мостовой драйвер двигателей и предназначена для управления DC и шаговыми двигателями. На eBay продаются готовые платы со всей необходимой обвязкой, цена платы составляет 4-5$ и выглядит она приблизительно так:

Подключение к Arduino достаточно подробно описано в . В нашем проекте для плавного изменения скорости вращения двигателей, мы будем использовать ШИМ (широтно-импульсную модуляцию).

6. Остальные комплектующие

Помимо вышеперечисленных компонентов понадобятся:
- батарейный отсек (4-5 батареек АА) или аккумуляторы, можно использовать к примеру готовые блоки Li-Po аккумуляторов на 7.4В
- соединительные провода
- выключатель питания
- термоусадочная трубка, хомуты и др.

Все это конечно опционально и можно заменить тем, что есть под рукой, к примеру вместо термоусадки использовать изоленту и т.д.

Как видите, себестоимость машинки не так уж и велика, если использовать свое шасси с моторчиками, то выходит около 20-25$ на все, если покупать и шасси, то выйдет уже 45-60$ в зависимости от типа шасси (т.к. диапазон цен на них очень широк).

Вот, что получилось у меня:


Принцип работы

В Android устройстве формируются команды перемещения машинки в зависимости от наклона смартфона/планшета, либо от нажатой кнопки. Все расчеты производятся в Android-приложении, и сразу же вычисляются значения ШИМ для левого и правого двигателей. Приложение обладает гибкими настройками, такими как диапазон ШИМ, чувствительность наклона, минимальный порог ШИМ и др. По Bluetooth передаются команды вида:
L-255\rR-120\r
L - команда для левого двигателя, R - для правого
минус обозначает вращение двигателя для движения назад
255 - число ШИМ, для Arduino это максимальная скорость вращения
\r - конец команды.
По данной команде машинка будет двигаться назад и немного поворачивать в правую сторону, т.к. правый двигатель будет вращаться медленнее левого.

L255\rR-255\r
По данной команде левый двигатель будет вращаться вперед, а правый назад, что заставит машинку вращаться вокруг своей оси против часовой стрелки.

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

Символы команд L, R и H можно задавать в настройках Android-приложения.

В программе контроллера предусмотрен таймер, который отключает двигатели, если последняя команда была получена более, чем n-секунд назад. Настройка количества секунд хранится в EEPROM памяти контроллера и может быть изменена с Android устройства. Диапазон данной настройки составляет от 0.1 сек до 99.9 секунд. Также, настройку можно совсем отключить. Но тогда, при потере связи машинка будет ехать, пока не будет выключено питание.
Для работы с памятью микроконтроллера предусмотрены команды Fr - чтение значений и Fw - запись значений.

Электронная начинка

Структурная схема CxemCAR представлена ниже:

Как видим, к контроллеру (Arduino, STM32 и др. неважно какой) подключается Bluetooth модуль и драйвер двигателей, к которому в свою очередь подключается 2 или 4 моторчика Bluetooth-управляемой модели. На схеме изображен один выход дополнительного канала (включение звукового сигнала, фар и т.п.), но путем небольшой правки программы число дополнительных каналов может быть легко увеличено.

Работа с Android приложением

Приложение под Android писалось в среде Eclipse. Все исходники проекта и проект для Eclipse вы можете скачать ниже. Я не специалист в Java программировании и это мое первое приложение под Android поэтому кое-где код не совсем удачен. Именно на разработку Android приложения ушло основное время при разработке данного проекта. Версия Android должна быть не ниже 3.0, я все писал и тестировал под планшет с версией 4.0.3.

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

Предусмотрено 3 режима управления Bluetooth-моделью:

Управление от акселерометра - основной способ управления. Управление движением Bluetooth-модели осуществляется за счет наклона Android-устройства (планшет, телефон и др.)
Виртуальный руль - гибридное управление. Газ - при помощи ползунка, повороты - при помощи поворота устройства. Задний ход - отдельной экранной кнопкой.
Управление от кнопок - на экране приложения выводятся 4 кнопки управления: вперед, назад, влево и вправо. При нажатии кнопки "вперед" машина едет вперед пока держите кнопку, при нажатии "назад" тоже самое, но едет назад. При нажатии кнопок "влево" или "вправо" машинка крутится вокруг своей оси в одну или в другую сторону. При этом значение скорости фиксировано (по умолчанию стоит максимальная скорость), но в настройках можно изменить данный параметр.
Управление от touch - данный способ управления я подсмотрел в игре DeathRally и ради спортивного интереса решил повторить. Честно сказать поучилось не очень удобно, но может кому-нибудь пригодится. На экране рисуется круг, внутри которого и происходит процесс управления. Повели пальцем вверх относительно центра - машинка едет вперед, чуть левее - машинка начинает поворачивать влево. Насчет этого способа управления, есть в дальнейшем идея усовершенствования с помощью компаса, т.е. использовать круг не как задатчик скорости и поворота, а задавать с помощью него направление движения.

Настройки приложения

Скриншот настроек Android приложения CxemCar версии 1.0:

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

Точка разворота для мотора (ось X)

При наклоне Android-устройства влево или вправо программа притормаживает тот двигатель, в сторону которого наклонено устройство, т.о. осуществляется поворот. Однако, когда значение наклона доходит до заданной в настройках точки разворота, то двигатель начинает вращаться в другую сторону. Если наклонить устройство максимально вбок, то один двигатель будет вращаться с максимальной скоростью в одну сторону, а другой в другую и соответственно машинка будет крутиться вокруг своей оси на месте.

MAC адрес

Для установления связи с Bluetooth модулем машинки, в настройках приложения необходимо задать MAC-адрес. Предварительно необходимо настроить сопряжение устройств в настройках вашего Android-устройства. Для этого переходим в Настройки -> Bluetooth и нажимаем "Поиск устройств", телефон находит наш Bluetooh-модуль, нажимаем по нему и вводим пароль (как правило 1234).

Узнать Bluetooth адрес модуля можно из какого-нибудь приложения, к примеру Bluetooth Terminal . Для этого внизу нажимаем "Connect a device - Secure" и в появившемся окошке нажимаем кнопку "Scan for devices". ПО сканирует Bluetooth устройства и отобразит их MAC-адреса:

Этот MAC-адрес и необходимо прописать в настройках приложения CxemCAR.

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

Сборка платформы

Как я уже говорил выше, в качестве платформы я выбрал шасси Pirate-4WD от производителя DFRobot (SKU:ROB0003). Это одно из самых популярных шасси, вот его описание и видео по сборке . Хотя там все интуитивно понятно и сборка очень проста.

После того, как была собрана основа шасси с моторами, припаиваем провода и на всякий случай маркируем моторчики:

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

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

Следующим этапом является установка колес. На вал они налезают очень туго, кое-где даже пришлось подпилить каттэром.

Провода от 4-х моторов подключаем к плате драйвера двигателей L298N, левые 2 мотора просто запаралеленны, тоже самое и правые.

Для того, чтобы можно было видеть состояние Bluetooth соединения, у модуля HC-06 (да и у других тоже) присутствует возможность подключения светодиода состояния. Я решил его также подключить и вывести на видное место. Для этого, я использовал токоограничительный резистор номиналом 470 Ом и термоусадочную трубку.

К модулю Bluetooth подключаем или подпаиваем все необходимые провода, помимо светодиода это питание, GND, TX и RX. Смотрите документацию на ваш Bluetooth модуль. Чтобы не мучаться с пайкой, я вам советую сразу взять модуль с подпаянными штыревыми выводами (см. фото выше). И лучше брать модули HC-03/HC-05.

Я же использовал модуль HC-06, который у меня был до этого. Схема распайки следующая:

В распаянном виде модуль выглядит так:

Его я также разместил в термоусадочной трубке большого диаметра.

Для питания двигателей я использовал батарейный отсек на 5 элементов типа АА, т.е. напряжение питания двигателей составило 7.5 Вольт. Можно использовать LiPo и другие аккумуляторы. Для крепления батарейного отсека в крышке шасси просверлил два отверстия и закрепил при помощи двух болтов.

История изменений ПО для Android:
Версия 1.1 (от 28.01.2013) - в классе cBluetooth изменения для более стабильного подключения по Bluetooth. Теперь не нужно вводить код для pairing (связывания устройств)
Версия 1.2 (от 15.02.2013) - дополнен класс cBluetooth на предмет установки соединения с устройством (полезно при отладке). Изменения в классе Handler (исправлены все ошибки с static). Реализован новый вид управления - "виртуальный руль".
Версия 1.3 (от 20.07.2013) - мелкие правки в активити. Исправление ошибки с инверсией координат на смартфонах

Что нам понадобится:

1. Шасси для робота, =9,50$
2. Драйвер двигателя, =1,22$
3. Датчик, который будет определять препятствие, я остановился на самом популярном и дешевом варианте =0,94$
Однако, никто не мешает воспользоваться более дорогими или чем-то подобным
4. Крепление датчика, не самый лучший, но жизнеспособный вариант. =1,08$
В качестве аналогов: , еще существует неуловимый желтый, наиболее прошаренный, но ссылку так и не нашел. Кто будет искать на вид он похож на синий, но имеет нормальные отверстия под винт м3 и 4 шурупа для крепления дальномера.
5. Плата arduino, которая будет обрабатывать данные с датчика и выдавать решение, куда ехать дальше. Остановился на , как на самой удобной для моделирования на «лету» =5.88$
Эта плата выбрана из-за возможности заменить микроконтроллер в случае фатальной неудачи, так что можно купить версию

Итого я потратил примерно 19$ на самое основное

!!! терминалы, разъемы, клещи можно заменить

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

Парочка фото на закуску

Провода и терминалы


Стойки, болты, гайки, шайбы

Сборка

Переходим к самому интересному - к созданию Франкенштейна!
Первым делом сверлим в синем кронштейне отверстие под болт м3, потому как иного варианта крепления я не нашел


на термоклей сажаем дальномер.


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

Крепим драйвер двигателя, подключаем моторы.



Приспосабливаем повербанк вместо батарейного отсека.
Для этого делаем два отверстия под винты м3 для крепления на шасси, припаиваем два проводка "+" и "-" к USB на плате и выводим провода через еще одно просверленное отверстие. К сожалению у меня не было под руками подходящего выключателя, так что эту функцию будет выполнять отключение проводков от ардуины. Далее крепим это дело на шасси.





Ставим ардуину, подключаем провода




Удобно, что заряжается аккумулятор через повербанк.

Вставляем аккумулятор прошиваем (воспользовался средой atmel studio 6), переворачиваем, чтобы не убежала, и тестируем, что получилось.

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

Подведем итоги

Для начала, тем, кто решит делать что-то подобное, стоит обратить внимание на шасси с четырьмя моторами. Такой шаг, в теории, исключит вероятность движения по дуге, но может добавить головной боли при подборе драйвера двигателя. Но не спешите ломать голову, можно оставить этот, все должно отлично работать, по токам проходит впритык - два мотора на канал. А вот однобаночного повербанка не хватит точно. На мой взгляд это уже повод рискнуть. Так же придется покупать шайбы, т.к. при креплении к пластмассе могут быть неприятные вещи. Еще было бы отлично разделить питание ардуины и моторов, либо воспользоваться стабилизатором, на худой конец впаять конденсатор большой емкости, но это для истинных ценителей, у меня работает и так. На практике я уложился в цену примерно 2000 руб, можно было и дешевле, но это была моя зарядка для ума и первый опыт в программировании (для чего собственно все и затевалось), особо экономить не стал. Появится время прикручу радиоуправление и выключатель.

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

Очень часто в ваших проектах возникает необходимость в дистанционном управлении или передачи данных с ваших телефонных гаджетов.

Один из самых популярных и распространенных методов обмена данными посредством Bluetooth.

Сегодня мы разберем простые примеры как можно подключить Bluetooth модуль к Arduino и настроить дистанционное управление с телефона.

Нам понадобится:

  • Набор проводов ПАПА-МАМА
  • HC-06 Bluetooth

Подключать Bluetooth модуль к микроконтроллеру Arduino удобнее всего с помощью проводков ПАПА-МАМА .

Arduino Bluetooth
Pin 1 (TX) RXD
Pin 0 (RX) TXD
GND GND
5V VCC

Будьте внимательны, подключать подключать нужно TX -> RXD ,RX -> TXD .

Теперь необходимо записать пробный код программы:

Во время загрузки скетча необходимо что бы Bluetooth модуль был отключен от микроконтроллера arduino. В противном случае скетч не запишется, потому что связь с Bluetooth модулем происходит по одному и томуже порту RX и TX, что и USB.

Int val; int LED = 13; void setup() { Serial.begin(9600); pinMode(LED, OUTPUT); digitalWrite(LED, HIGH); } void loop() { if (Serial.available()) { val = Serial.read(); // При символе "1" включаем светодиод if (val == "1") { digitalWrite(LED, HIGH); } // При символе "0" выключаем светодиод if (val == "0") { digitalWrite(LED, LOW); } } }

После того как скетч записан и Bluetooth модуль подключен к Arduino, можно перейти к следующему шагу.

Подключение Bluetooth к телефону

Желательно в качестве источника питания для arduino использовать не USB, а внешний Блок питания на 9 В.

  1. Включаем Bluetooth на телефоне и ищем новые устройства
  2. Находим в списке расстройств "HC-06" и подключаемся к нему.
  3. Телефон спросит пин-код. необходимо ввести "1234 " или "0000 "
  4. Ура. Устройство подключено.

Теперь нужно скачать bluetooth terminal на ваш телефон. Мы рассмотрим на примере платформы Android.



Вы можете установить разные bluetooth терминалы, как правило они отличаются только разными дизайнами, функционал от этого не меняется. Так же можно найти и терминал и для продуктов ios.

После того как мы установили терминал, запускаем его выбираем наш bluetooth модуль HC-06 и подключаемся к нему.

Пришло время попробовать проект в деле. Пишем в терминале цифру "0" и отправляем. Светодиод L который находится на плате arduino рядом с pin 13, должен погаснуть. Теперь отправим через терминал цифру "1" и светодиод L должен зажечься.

Демонстрация работы:


Домашняя работа:

  • Изменить скетч так, что бы светодиод зажигался и потухал с помощью одной и той же команды например "G".
  • Дописать скетч и научить его преобразовывать текстовые данные приходящие через блютус в цифровые и реализовать димер, зажигать светодиод с помощью ШИМ, на заданную яркость от 0 до 254 приходящую через bluetooth.

Широкое распространение и дешевизна платформы Arduino и различных робоплатформ позволило любителям создавать радиоуправляемые машинки на любой вкус. А широкое распространение смартфонов позволило использовать их в качестве контроллеров этих машинок. Главной проблемой для многих любителей Arduino является отсутствие опыта в программировании под Android. Сегодня я расскажу, как легко решить эту проблему, используя среду визуальной разработки android-приложений App Inventor 2.



Постройку любой машинки надо начинать с «железа», поэтому вкратце опишу, что использовал для своей машинки:
arduino nano
bluetooth module HC-05
Z-Mini Motor Sensor Shield L293D
2WD Motor Chassis
Конфигурация «железа» не играет большой роли в этом проекте, поэтому шасси, шилд и саму ардуино можно заменить на любые аналоги.

Теперь перейдем к созданию приложения для Android. App Inventor - среда визуальной разработки android-приложений, работает из браузера. Заходим на сайт, разрешаем доступ к своему аккаунту в Google, нажимаем кнопку «create» и создаем новый проект. В новом проекте методом «Drag and Drop» создаем 4 кнопки для выбора направления движения и одну для подключения к нашему bluetooth модулю. Примерно так:

Теперь остается скомпилировать приложение, нажав на кнопку «Build».

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

скетч

int val;
int IN1 = 4;
int IN2 = 7;
int EN1 = 6;
int EN2 = 5;

Void setup()
{
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(EN1, OUTPUT);
pinMode(EN2, OUTPUT);

}
void loop()
{
if (Serial.available())
{
val = Serial.read();

// Задаём движение вперёд
if (val == "W") // При нажатии клавиши «W»
{
// Выводы конфигурируются согласно работе Motor Shield"а
// Моторы крутятся вперед
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
}

// Задаём движение назад
if (val == "S")
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}

// Задаём движение вправо
if (val == "D")
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
}

// Задаём движение влево
if (val == "A")
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
}

// Стоп режим
// При отпускании клавиш в программе в порт шлется «T»
if (val == "T") // При нажатии клавиши «T»
{
// Выводы ENABLE притянуты к минусу, моторы не работают
digitalWrite(EN1, LOW);
digitalWrite(EN2, LOW);
}
}
}


Итак, вот такая у меня получилась машинка:

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

P.S. Для тех, кто не сталкивался с разработкой приложений в App Inventor 2, я сделал более подробный гайд по разработке этого приложения (для просмотра нужно перейти на ютуб).

P.P.S. Сборник из более 100 обучающих материалов по ардуино для начинающих и профи