Машинка на блютуз управлении. Простая Bluetooth машинка на Arduino. Подключение Bluetooth к телефону

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

Один из самых популярных и распространенных методов обмена данными посредством 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.

После приобретения недорогого 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) - мелкие правки в активити. Исправление ошибки с инверсией координат на смартфонах

В статье рассмотрим подключение и управление Arduino по bluetooth.

В качестве блютуз-модуля будет использоваться широко распространенный hc-06.

В нашем проекте будем через bluetooth включать и выключать светодиод, подключенный к 13 порту.

Начнем с написания приложения на android-смартфон. Приложение будет писаться в удобной и простой среде программирования App Inventor. Программы будут составляться онлайн.

Пройдите по ссылке http://ai2.appinventor.mit.edu/ . Там вас попросят войти в Google-аккаунт, который вам придется завести, если его еще нет.

После входа вы попадете в программу, где сможете создать проект нажав «start new project». Вам потребуется ввести имя проекта. Назовем его led_control.

Откроется пустое окно приложения.

Здесь будем располагать необходимые компоненты. Выберите ListPicker в окне слева и поместите его в проект.

У компонента ListPicker в окне справа найдите свойство Text, и измените «Text for ListPicker1» на «Выберите BT-устройство».

Откройте закладку Layout в окне слева, поместите в приложение компонент HorizontalArrangement, измените его свойство Width на «Fill parent». Добавьте в HorizontalArrangement 2 кнопки Button, у каждой из них установите свойство Width в «Fill parent». Должно получиться так:

Изменим подписи на кнопках: на первой будет написано LED ON, на второй — LED OFF.

Ниже добавим Label и очистим его Text.

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

Теперь можно приступать к написанию программы. В верхней правой части программы выберите режим Blocks.

Здесь будет составляться программа из графических блоков. Слева кликните на компонент ListPicker1 и выберите ListPicker1.BeforePicking.

Снова нажмите на ListPicker1 и выберите set ListPicker1.Elements to

Поставьте его как на скриншоте.

Этим мы получили список сопряженных bluetooth-устройств. Теперь подключимся к выбранному устройству. Напишите блок как на скриншоте ниже.

Розовый блок с надписью Connected — это первый блок в закладке Text. Впишите Connected в пустое окошко.

Теперь напишем обработчик кнопок. При нажатии на первую кнопку будет отсылаться текст «led_on», а при нажатии на вторую — «led_off». Так же будет изменяться и надпись в Label1.

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

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

Во втором варианте проект в формате.apk сохранится на ваш компьютер и вы сможете скинуть его на смартфон любым удобным способом (например по USB).

Теперь займемся программой на Arduino.

Прием-передача данных осуществляется через COM-порт, поэтому будем использовать Serial. Будем посимвольно принимать сигналы, формировать строку и дальше сравнивать сформированную строку с командами led_on и led_off.

Arduino

String val = ""; void setup() { Serial.begin(9600); pinMode(13, OUTPUT); } void loop() { while (Serial.available()) { //пока приходят данные char c = Serial.read(); //считываем их val += c; //и формируем строку delay(3); } if (val != "") { Serial.println(val); } if (val == "led_on") { digitalWrite(13, HIGH); } else if (val == "led_off") { digitalWrite(13, LOW); } val = ""; }

String val = "" ;

void setup () {

Serial . begin (9600 ) ;

pinMode (13 , OUTPUT ) ;

void loop () {

while (Serial . available () ) { //пока приходят данные

char c = Serial . read () ; //считываем их

val += c ; //и формируем строку

delay (3 ) ;

}

Загрузите код в Arduino.

Теперь можно подключить Bluetooth-модуль HC-06. Подключается он очень просто:

Vcc 5v (можно 3,3 v)

ЕСЛИ ПОПЫТАТЬСЯ ЗАГРУЗИТЬ ПРОГРАММУ В ARDUINO С ПОДКЛЮЧЕННЫМ МОДУЛЕМ, ТО ВЫЛЕЗЕТ ОШИБКА, Т.К. И МОДУЛЬ И ЗАГРУЗКА ПРОГРАММЫ ЗАДЕЙСТВУЮТ ПОРТЫ RX И TX!

Подайте питание на Arduino. На bluetooth-модуле должен заморгать светодиод, это означает, что он ожидает подключения. Возьмите смартфон, найдите в настройках bluetooth, включите его и запустите поиск. Найдите устройство с именем hc-06 и подключитесь к нему. С первого раза может не получиться. После однократного успешного сопряжения можно запускать программу на смартфоне.

Сначала нажмите на «Выберите BT-устройство» и выберите модуль среди сопряженных устройств. Далее нажимайте кнопки включения и выключения светодиода. Если все сделано правильно, то все будет работать.

Мы сделали очень простое приложение с использованием Bluetooth, без дизайна и даже проверки, подключились мы к модулю или нет. В следующих уроках будем делать более сложные приложения и получше познакомимся с App Inventor.

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

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

Создание приложения для Android

Заготовка

Разработка для ОС Android ведется в среде разработки ADT, Android Development Tools. Которую можно скачать с портала Google для разработчиков. После скачивания и установке ADT, смело его запускаем. Однако, еще рано приступать к разработке приложения. Надо еще скачать Android SDK нужной версии. Для этого необходимо открыть Android SDK Manager «Window → Android SDK Manager». В списке необходимо выбрать нужный нам SDK, в нашем случае Android 2.3.3 (API 10). Если телефона нет, то выбирайте 2.3.3 или выше; а если есть - версию, совпадающую с версией ОС телефона. Затем нажимаем на кнопку «Install Packages», чтобы запустить процесс установки.

После завершения скачивания и установки мы начинаем создавать приложение. Выбираем «File → New → Android Application Project». Заполним содержимое окна так, как показано на рисунке.

    Application Name - то имя приложения, которое будет показываться в Google Play Store. Но выкладывать приложение мы не собираемся, поэтому имя нам не особо важно.

    Project Name - имя проекта в ADT.

    Package Name - идентификатор приложения. Он должен быть составлен следующим образом: название Вашего сайта задом наперед, плюс какое-либо название приложения.

В выпадающих списках «Minimum Required SDK», «Target SDK», «Compile With» выбираем ту версию, которую мы скачали ранее. Более новые версии SDK поддерживают графические темы для приложений, а старые нет. Поэтому в поле «Theme» выбираем «None». Нажимаем «Next».

Снимаем галочку с «Create custom launcher icon»: в рамках данной статьи не будем заострять внимание на создании иконки приложения. Нажимаем «Next».

В появившемся окне можно выбрать вид «Activity»: вид того, что будет на экране, когда будет запущено приложение. Выбираем «Blank activity», что означает, что мы хотим начать всё с чистого листа. Нажимаем «Next».

В нашем приложении будет всего одно Activity, поэтому в появившемся окне можно ничего не менять. Поэтому просто жмем на «Finish».

Все, наше приложение создано.

Настройка эмулятора

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

Для этого запустим «Window → Android Virtual Device Manager». В появившемся окне нажмем «New». Заполняем поля появившейся формы. От них зависит сколько и каких ресурсов будет предоставлять эмулятор «телефону». Выберите разумные значения и нажимайте «ОК».

В окне Android Virtual Device Manager нажимаем кнопку «Start». Это запустит эмулятор. Запуск занимает несколько минут. Так что наберитесь терпения.

В результате вы увидите окно эмулятора подобное этому:

Заполнение Activity

Activity - это то, что отображается на экране телефона после запуска приложения. На нем у нас будет две кнопки «Зажечь красный светодиод» и «Зажечь синий светодиод». Добавим их. В панели «Package Explorer» открываем res/layout/activity_main.xml . Его вид будет примерно таким же, как на скриншоте.

Перетаскиваем 2 кнопки «ToggleButton» на экранную форму. Переключаемся во вкладку «activity_main.xml» и видим следующий код:

activity_main_aiutogen.xml xmlns:tools = android:layout_width ="match_parent" android:layout_height ="match_parent" android:paddingBottom = android:paddingLeft = android:paddingRight ="@dimen/activity_horizontal_margin" android:paddingTop ="@dimen/activity_vertical_margin" tools:context =".MainActivity" > android:id ="@+id/toggleButton1" android:layout_alignParentLeft ="true" android:layout_alignParentTop ="true" android:text ="ToggleButton" /> android:id ="@+id/toggleButton2" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_above ="@+id/textView1" android:layout_alignParentRight ="true" android:text ="ToggleButton" /> >

Это ни что иное, как наша Activity, которая отображается не в виде графики, а описанная в формате XML.

Сделаем имена компонентов более понятными. Изменим поля android:id следующим образом.

android:id ="@+id/toggleRedLed" ... android:id ="@+id/toggleGreenLed" ...

А еще добавим им подписи, изменим их цвет и размер текста. Результирующий код разметки будет выглядеть следующим образом.

activity_main.xml "http://schemas.android.com/apk/res/android" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="fill_parent" android:paddingBottom ="@dimen/activity_vertical_margin" android:paddingLeft ="@dimen/activity_horizontal_margin" android:paddingRight ="@dimen/activity_horizontal_margin" android:paddingTop ="@dimen/activity_vertical_margin" tools:context =".MainActivity" android:weightSum ="2" android:orientation ="horizontal" > android:id ="@+id/toggleRedLed" android:layout_width ="wrap_content" android:layout_height ="fill_parent" android:layout_weight ="1" android:background ="#FF0000" android:textOff ="OFF" android:textOn ="ON" android:textSize ="30dp" /> android:id ="@+id/toggleGreenLed" android:layout_width ="wrap_content" android:layout_height ="fill_parent" android:layout_weight ="1" android:background ="#00FF00" android:textOff ="OFF" android:textSize ="30dp" android:textOn ="ON" /> >

Эти же изменения можно сделать и в графическом режиме, воспользовавшись вкладкой «Outline/Properties».

Пробный запуск

Мы можем запустить только что созданное приложение на эмуляторе. Идем в настройки запуска «Run» → Run Configurations», в левой части нажимаем на «Android Application». Появляется новая конфигурация «New_configuration». В правой части окна выбираем вкладку «Target» и выбираем опцию «Launch on all compatible devices/AVD».

Нажимаем «Apply», а затем «Run». Приложение запустится в эмуляторе.

Можно понажимать кнопки. Но ничего происходить не будет, поскольку обработчики нажатий еще нами не написаны.

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

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

Написание кода для Android

Правка манифеста

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

AndroidManifest.xml "http://schemas.android.com/apk/res/android" package ="ru.amperka.arduinobtled" android:versionCode ="1" android:versionName ="1.0" > android:minSdkVersion ="10" android:targetSdkVersion ="10" /> "android.permission.BLUETOOTH" /> "android.permission.BLUETOOTH_ADMIN" />
android:allowBackup ="true" android:icon ="@drawable/ic_launcher" android:label ="@string/app_name" android:theme ="@style/AppTheme" > android:name ="ru.amperka.arduinobtled.MainActivity" android:label ="@string/app_name" > > "android.intent.category.LAUNCHER" /> > > > >

Добавляем основной код

Пришла пора вдохнуть жизнь в наше приложение. Открываем файл MainActivity.java (src → ru.amperka.arduinobtled). Изначально он содержит следующий код:

MainActivityAutogen.java package ru.amperka.arduinobtled ; import android.os.Bundle ; import android.app.Activity ; import android.view.Menu ; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate (savedInstanceState) ; setContentView(R.layout .activity_main ) ; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater() .inflate (R.menu .main , menu) ; return true ; } }

Дополним код в соответствии с тем, что нам нужно:

    Будем включать Bluetooth, если он выключен.

    Будем обрабатывать нажатия на кнопки

    Будем посылать информацию о том, какая кнопка была нажата.

Передавать на Arduino мы будем один байт с двузначным числом. Первая цифра числа - номер пина, к которому подключен тот или иной светодиод, вторая - состояние светодиода: 1 - включен, 0 - выключен.

Число-команда, рассчитывается очень просто: Если нажата красная кнопка, то берется число 60 (для красного светодиода мы выбрали 6-й пин Arduino) и к нему прибавляется 1 или 0 в зависимости от того, должен ли сейчас гореть светодиод или нет. Для зеленой кнопки всё аналогично, только вместо 60 берется 70 (поскольку зеленый светодиод подключен к 7 пину). В итоге, в нашем случае, возможны 4 команды: 60, 61, 70, 71.

Напишем код, который реализует всё сказанное.

MainActivity.java package ru.amperka.arduinobtled ; import java.io.IOException ; import java.io.OutputStream ; import java.lang.reflect.InvocationTargetException ; import java.lang.reflect.Method ; import android.app.Activity ; import android.bluetooth.BluetoothAdapter ; import android.bluetooth.BluetoothDevice ; import android.bluetooth.BluetoothSocket ; import android.content.Intent ; import android.os.Bundle ; import android.util.Log ; import android.view.Menu ; import android.view.View ; import android.view.View.OnClickListener ; import android.widget.Toast ; import android.widget.ToggleButton ; public class MainActivity extends Activity implements View .OnClickListener { //Экземпляры классов наших кнопок ToggleButton redButton; ToggleButton greenButton; //Сокет, с помощью которого мы будем отправлять данные на Arduino BluetoothSocket clientSocket; //Эта функция запускается автоматически при запуске приложения @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate (savedInstanceState) ; setContentView(R.layout .activity_main ) ; //"Соединям" вид кнопки в окне приложения с реализацией redButton = (ToggleButton) findViewById(R.id .toggleRedLed ) ; greenButton = (ToggleButton) findViewById(R.id .toggleGreenLed ) ; //Добавлем "слушатель нажатий" к кнопке redButton.setOnClickListener (this ) ; greenButton.setOnClickListener (this ) ; //Включаем bluetooth. Если он уже включен, то ничего не произойдет String enableBT = BluetoothAdapter.ACTION_REQUEST_ENABLE ; startActivityForResult(new Intent(enableBT) , 0 ) ; //Мы хотим использовать тот bluetooth-адаптер, который задается по умолчанию BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter () ; //Пытаемся проделать эти действия try { //Устройство с данным адресом - наш Bluetooth Bee //Адрес опредеяется следующим образом: установите соединение //между ПК и модулем (пин: 1234), а затем посмотрите в настройках //соединения адрес модуля. Скорее всего он будет аналогичным. BluetoothDevice device = bluetooth.getRemoteDevice ("00:13:02:01:00:09" ) ; //Инициируем соединение с устройством Method m = device.getClass () .getMethod ( "createRfcommSocket" , new Class { int .class } ) ; clientSocket = (BluetoothSocket) m.invoke (device, 1 ) ; clientSocket.connect () ; //В случае появления любых ошибок, выводим в лог сообщение } catch (IOException SecurityException e) { Log.d ("BLUETOOTH" , e.getMessage () ) ; } catch (NoSuchMethodException e) { Log.d ("BLUETOOTH" , e.getMessage () ) ; } catch (IllegalArgumentException e) { Log.d ("BLUETOOTH" , e.getMessage () ) ; } catch (IllegalAccessException e) { Log.d ("BLUETOOTH" , e.getMessage () ) ; } catch (InvocationTargetException e) { Log.d ("BLUETOOTH" , e.getMessage () ) ; } //Выводим сообщение об успешном подключении Toast.makeText (getApplicationContext() , "CONNECTED" , Toast.LENGTH_LONG ) .show () ; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater() .inflate (R.menu .main , menu) ; return true ; } //Как раз эта функция и будет вызываться @Override public void onClick(View v) { //Пытаемся послать данные try { //Получаем выходной поток для передачи данных OutputStream outStream = clientSocket.getOutputStream () ; int value = 0 ; //В зависимости от того, какая кнопка была нажата, //изменяем данные для посылки if (v == redButton) { value = (redButton.isChecked () ? 1 : 0 ) + 60 ; } else if (v == greenButton) { value = (greenButton.isChecked () ? 1 : 0 ) + 70 ; } //Пишем данные в выходной поток outStream.write (value) ; } catch (IOException e) { //Если есть ошибки, выводим их в лог Log.d ("BLUETOOTH" , e.getMessage (, OUTPUT) ; pinMode(7 , OUTPUT) ; } void loop() { //Если данные пришли if (Serial.available () > 0 ) { //Считываем пришедший байт byte incomingByte = Serial.read () ; //Получаем номер пина путем целочисленного деления значения принятого байта на 10 //и нужное нам действие за счет получения остатка от деления на 2: //(1 - зажечь, 0 - погасить) digitalWrite(incomingByte / 10 , incomingByte % 2 ) ; } }

Особенности заливки скетча

Для связи Bluetooth-Bee с контроллером используются те же пины (0 и 1), что и для прошивки. Поэтому при программировании контроллера переключатель «SERIAL SELECT» на «Wireless Shield» должен быть установлен в положение «USB», а после прошивки его надо вернуть в положение «MICRO».

Результат

Заключение

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

Вы можете развить мысль и сделать более дружественный интерфейс на Android, управлять с его помощью гораздо более сложными устройствами, публиковать классные приложения в Android Market и ещё много-много всего интересного!

Там же находятся исходники для Android и другая полезная информация. В этой статье я покажу сборку CxemCAR для платформы Arduino. В качестве платы Arduino можно использовать практически любую Arduino-совместимую плату: UNO, Nano, Mega, Leonardo и даже на основе STM32 - Arduino DUE. Я использовал платку Arduino Nano V3, приобретенную на eBay за 9$.

Схема подключения Arduino к Bluetooth модулю HC-06 и драйверу двигателей L298N:

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

В качестве платформы я использовал небольшую RC DIY платформу, купленную на за 25$. Сама платформа представляет из себя алюминиевое основание, куда крепится два двигателя, редуктор и 4 карданные передачи для 4-х колес. Сверху, на 3-х стойках ставится макетная плата.

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

После этого, я припаял Bluetooth-модуль к Arduino и вывел для него светодиод состояния. О разновидностях Bluetooth модулей, их подключении к Arduino, работы с ними и т.п. можете почитать в данной статье: . Модуль HC-06 поместил в термоусадочную трубку 10мм. Светодиод Bluetooth-состояния с токоограничительным резистором также были помещены в термоусадку, но более тонкую - 5мм.

В макетной плате, которая шла вместе с платформой, я просверлил отверстия и закрепил драйвер двигателей L298N. Плату Arduino прикрепил при помощи двухстороннего скотча.

Между алюминиевой платформой машинки и макетной платой я разместил 3 Li-Po аккумулятора 3.7В 1100 мА*Ч. Питание контроллера и двигателей раздельное: Arduino запитывается от одного аккумулятора 3.7В, а моторчики и драйвер L298N от двух последовательно соединенных аккумуляторов 3.7В. Предусмотрено два 2-х позиционных выключателя питания - в одном положение питание идет от аккумуляторов к потребителям, в другом положении на клеммы зарядки.

Фото машинки на подзарядке:

Программное обеспечение

Программа писалась в среде Arduino IDE 1.01. Код программы я постарался хорошо прокомментировать, но если будут вопросы - спрашивайте на форуме, в .

#include "EEPROM.h" #define D1 2 // направление вращение двигателя 1 #define M1 3 // ШИМ вывод для управления двигателем 1 (левый) #define D2 4 // направление вращение двигателя 2 #define M2 5 // направление вращение двигателя 2 (правый) #define HORN 13 // доп. канал 1 подключен к 13 пину //#define autoOFF 2500 // кол-во миллисекунд через которое робот останавливается при потери связи #define cmdL "L" // команда UART для левого двигателя #define cmdR "R" // команда UART для правого двигателя #define cmdH "H" // команда UART для доп. канала 1 (к примеру сигнал Horn) #define cmdF "F" // команда UART для работы с EEPROM памятью МК для хранения настроек #define cmdr "r" // команда UART для работы с EEPROM памятью МК для хранения настроек (чтение) #define cmdw "w" // команда UART для работы с EEPROM памятью МК для хранения настроек (запись) char incomingByte; // входящие данные char L_Data; // строковый массив для данных левого мотора L byte L_index = 0; // индекс массива char R_Data; // строковый массив для данных правого мотора R byte R_index = 0; // индекс массива char H_Data; // строковый массив для доп. канала byte H_index = 0; // индекс массива H char F_Data; // строковый массив данных для работы с EEPROM byte F_index = 0; // индекс массива F char command; // команда: передача координат R, L или конец строки unsigned long currentTime, lastTimeCommand, autoOFF; void setup() { Serial.begin(9600); // инициализация порта pinMode(HORN, OUTPUT); // дополнительный канал pinMode(D1, OUTPUT); // выход для задания направления вращения двигателя pinMode(D2, OUTPUT); // выход для задания направления вращения двигателя /*EEPROM.write(0,255); EEPROM.write(1,255); EEPROM.write(2,255); EEPROM.write(3,255);*/ timer_init(); // инициализируем программный таймер } void timer_init() { uint8_t sw_autoOFF = EEPROM.read(0); // считываем с EEPROM параметр "включена ли ф-ия остановки машинки при потере связи" if(sw_autoOFF == "1"){ // если таймер останова включен char var_Data; var_Data = EEPROM.read(1); var_Data = EEPROM.read(2); var_Data = EEPROM.read(3); autoOFF = atoi(var_Data)*100; // переменная автовыкл. для хранения кол-ва мс } else if(sw_autoOFF == "0"){ autoOFF = 999999; } else if(sw_autoOFF == 255){ autoOFF = 2500; // если в EEPROM ничего не записано, то по умолчанию 2.5 сек } currentTime = millis(); // считываем время, прошедшее с момента запуска программы } void loop() { if (Serial.available() > 0) { // если пришли UART данные incomingByte = Serial.read(); // считываем байт if(incomingByte == cmdL) { // если пришли данные для мотора L command = cmdL; // текущая команда memset(L_Data,0,sizeof(L_Data)); // очистка массива L_index = 0; // сброс индекса массива } else if(incomingByte == cmdR) { // если пришли данные для мотора R command = cmdR; memset(R_Data,0,sizeof(R_Data)); R_index = 0; } else if(incomingByte == cmdH) { // если пришли данные для доп. канала 1 command = cmdH; memset(H_Data,0,sizeof(H_Data)); H_index = 0; } else if(incomingByte == cmdF) { // если пришли данные для работы с памятью command = cmdF; memset(F_Data,0,sizeof(F_Data)); F_index = 0; } else if(incomingByte == "\r") command = "e"; // конец строки else if(incomingByte == "\t") command = "t"; // конец строки для команд работы с памятью if(command == cmdL && incomingByte != cmdL){ L_Data = incomingByte; // сохраняем каждый принятый байт в массив L_index++; // увеличиваем текущий индекс массива } else if(command == cmdR && incomingByte != cmdR){ R_Data = incomingByte; R_index++; } else if(command == cmdH && incomingByte != cmdH){ H_Data = incomingByte; H_index++; } else if(command == cmdF && incomingByte != cmdF){ F_Data = incomingByte; F_index++; } else if(command == "e"){ // если приняли конец строки Control4WD(atoi(L_Data),atoi(R_Data),atoi(H_Data)); delay(10); } else if(command == "t"){ // если приняли конец строки для работы с памятью Flash_Op(F_Data,F_Data,F_Data,F_Data,F_Data); } lastTimeCommand = millis(); // считываем текущее время, прошедшее с момента запуска программы } if(millis() >= (lastTimeCommand + autoOFF)){ // сравниваем текущий таймер с переменной lastTimeCommand + autoOFF Control4WD(0,0,0); // останавливаем машинку } } void Control4WD(int mLeft, int mRight, uint8_t Horn){ bool directionL, directionR; // направление вращение для L298N byte valueL, valueR; // значение ШИМ M1, M2 (0-255) if(mLeft > 0){ valueL = mLeft; directionL = 0; } else if(mLeft < 0){ valueL = 255 - abs(mLeft); directionL = 1; } else { directionL = 0; valueL = 0; } if(mRight > 0){ valueR = mRight; directionR = 0; } else if(mRight < 0){ valueR = 255 - abs(mRight); directionR = 1; } else { directionR = 0; valueR = 0; } analogWrite(M1, valueL); // задаем скорость вращения для L analogWrite(M2, valueR); // задаем скорость вращения для R digitalWrite(D1, directionL); // задаем направление вращения для L digitalWrite(D2, directionR); // задаем направление вращения для R digitalWrite(HORN, Horn); // дополнительный канал } void Flash_Op(char FCMD, uint8_t z1, uint8_t z2, uint8_t z3, uint8_t z4){ if(FCMD == cmdr){ // если команда чтения EEPROM данных Serial.print("FData:"); // посылаем данные с EEPROM Serial.write(EEPROM.read(0)); // считываем значение ячейки памяти с 0 адресом и выводим в UART Serial.write(EEPROM.read(1)); Serial.write(EEPROM.read(2)); Serial.write(EEPROM.read(3)); Serial.print("\r\n"); // маркер конца передачи EEPROM данных } else if(FCMD == cmdw){ // если команда записи EEPROM данных EEPROM.write(0,z1); // запись z1 в ячейку памяти с адресом 0 EEPROM.write(1,z2); EEPROM.write(2,z3); EEPROM.write(3,z4); timer_init(); // переинициализируем таймер Serial.print("FWOK\r\n"); // посылаем сообщение, что данные успешно записаны } }

В коде используется библиотека для работы с EEPROM памятью AVR. В памяти хранится одна настройка: количество миллисекунд через которое машинка останавливается при потери связи. Можно эту настройку "жестко" прописать в программе, для этого раскомментируйте строчку #define autoOFF 2500 (где 2500 кол-во миллисекунд). После этого, функцию Flash_Op можно удалить, также необходимо будет внести небольшие правки в код, отвечающий за прием команд для работы с EEPROM-памятью.