Создание Bluetooth-джойпада с помощью App Inventor 2
Здесь мы создаём базовый Bluetooth-джойпад (Classic Bluetooth) для Android-устройства, предназначенный для управления микроконтроллером (Arduino), подключённым к Bluetooth-модулю. Приложение довольно простое. Два экрана: первый — основная панель управления, второй — страница подключения.
При нажатии кнопки CONNECT на главном экране открывается второй экран, позволяющий пользователю подключиться к Bluetooth-устройству. Кнопки направления при нажатии передают коды на Arduino.
App Inventor 2
Приложение создано в App Inventor 2 с использованием Bluetooth Classic.
App Inventor 2 — простой способ начать создавать Android-приложения. Он предназначен в первую очередь для обучения, но с его помощью можно создавать удивительно продвинутые и сложные приложения. App Inventor основан на блоках. Это означает, что программы создаются с помощью визуальных элементов, которые перетаскиваются, а не текста. Он облачный — вы используете веб-браузер.
Я не вдаюсь во все подробности App Inventor и предполагаю, что у вас есть базовый опыт работы с ним. Как минимум, у вас должен быть аккаунт Google и вы должны знать, где находится сайт App Inventor.
Дизайн
Bluetooth-джойпад имеет простой интерфейс и используется в ландшафтном режиме.
4 кнопки направления
3 обычные кнопки
индикатор подключения
кнопка подключения
При нажатии кнопки CONNECT открывается второй экран. Второй экран обрабатывает Bluetooth-соединение и скорость обновления.
Второй экран имеет:
кнопку для инициации Bluetooth-подключения
ползунок для управления скоростью обновления приложения
кнопку BACK для возврата на главный экран
Как и во многих вещах в App Inventor, существуют разные способы получить одинаковый макет. Чтобы макет был максимально простым, я использую строку вверху для индикатора подключения и кнопки меню. Далее 4 столбца для кнопок управления. Всё содержится во внешней вертикальной компоновке, что позволяет легко показывать/скрывать все элементы управления одним действием.
Коды управления
Я использую односимвольные коды управления — это упрощает коммуникацию и помогает со скоростью. Вместо одного события нажатия кнопки я использую события «кнопка нажата» и «кнопка отпущена». Это означает, что каждая кнопка требует 2 кода:
Кнопки направления
U — кнопка вверх нажата |
u — кнопка вверх отпущена |
D — кнопка вниз нажата |
d — кнопка вниз отпущена |
L — кнопка влево нажата |
l — кнопка влево отпущена |
R — кнопка вправо нажата |
r — кнопка вправо отпущена |
Кнопки управления
R — красная нажата |
r — красная отпущена |
G — зелёная нажата |
g — зелёная отпущена |
B — синяя нажата |
b — синяя отпущена |
Кнопка CONNECT запускает внутренние события в приложении и не требует кода.
На стороне Arduino, когда она получает символ «U», она знает, что кнопка вверх нажата, а когда получает символ «u» — что кнопка отпущена. Если получен «U», но не «u», значит кнопка удерживается нажатой. Это удобно, например, при управлении дистанционной машинкой. «U» может означать «ехать вперёд и продолжать, пока не получено «u»». «R» — «поворачивать вправо, пока не получено «r»».
Использование односимвольных кодов также позволяет значительно упростить код Arduino.
App Inventor 2 и Bluetooth
App Inventor позволяет создавать приложения с несколькими экранами, но при использовании Bluetooth есть предостережение. Каждый экран должен иметь собственное Bluetooth-соединение. Это значит, что если мы используем экран 2 для открытия Bluetooth-соединения, после возврата на экран 1 мы уже не подключены. Чтобы обойти это, я использую псевдо-экраны. Приложение будет выглядеть так, будто мы используем 2 экрана, но на самом деле мы используем только 1 и скрываем/показываем элементы, чтобы создать иллюзию смены экранов.
PAGE1_OUTER_VA действует как страница 1, а PAGE2_OUTER_VA — как страница 2. При первом запуске приложения отображается только PAGE1_OUTER_VA. При нажатии кнопки CONNECT PAGE1_OUTER_VA скрывается, а PAGE2_OUTER_VA отображается.
Размер экрана
App Inventor имеет ограничения по размеру экрана и расположению элементов. Хорошая практика — использовать пропорциональные размеры (размер в процентах от экрана, а не в пикселях).
Кнопки направления занимают около 18% ширины экрана, цветные кнопки — 20%. Вы можете изменить размеры по своему вкусу.
Во время разработки я использовал Samsung S7, но также проверял на Sony Compact Z3 и Samsung 7» планшете. Хотя есть небольшие различия в отображении на 3 разных устройствах, общая компоновка одинакова.
Создание макета
Я не описываю каждый шаг работы с App Inventor и ожидаю, что у вас есть опыт работы с ним. Если нет — начните с онлайн-руководств и примеров.
Откройте браузер, перейдите в App Inventor по адресу http://ai2.appinventor.mit.edu/ и начните новый проект Joypad_001. Я добавляю номера версий к имени приложения и увеличиваю их по мере прогресса.
Экран приложения без прокрутки (я обнаружил, что лучше оставить экран прокручиваемым и отключить прокрутку в коде). Установите экран в Landscape и Responsive. Отключите заголовок экрана, сняв флажок TitleVisible. Включите Display hidden components in view.
Затем создайте макет.
Начните с внешних элементов, установите правильное выравнивание, а затем создайте внутренние элементы — кнопки и метки. Или, если хотите, скачайте файл aia с макетом.
Заметки о макете:
VerticalArrangement1, VerticalArrangement2, VerticalArrangement3
VerticalArrangement4
BTN_CONNECT_PAGE размер: высота 12%, ширина 18%.
Кнопки направления: высота 30%, ширина 18%.
Размер кнопок: высота 15%, ширина 20%.
Теперь добавьте изображения (правый клик — Сохранить как):
После завершения макета добавьте базовые блоки, чтобы увидеть, как будет работать приложение:
Эти блоки делают:
Третий блок обрабатывает BTN_BACK. При нажатии приложение возвращается на страницу 1, скрывая PAGE2_OUTER_VA и отображая PAGE1_OUTER_VA.
Создание приложения
Мы будем строить приложение по частям. Сначала настроим Bluetooth-подключение, затем добавим функции кнопок. Поскольку приложение будет иметь только одностороннюю связь (от приложения к Arduino), нам не нужен код для обработки приёма данных, только отправки. Всё, что нужно — установить соединение, дождаться нажатия кнопки и отправить код.
В Bluetooth Classic удалённое устройство должно быть сопряжено перед установлением соединения. Процесс сопряжения обрабатывается Android-устройством через настройки. После сопряжения устройство остаётся в списке сопряжённых устройств.
В дизайнере добавьте BluetoothClient в проект. В палитре выберите BluetoothClient и перетащите в главное окно.
Добавьте ListPicker в самый низ макета. В TEXT введите «Bluetooth device list» и снимите флажок Visible. Мы будем использовать кнопку CONNECT для активации ListPicker.
Далее добавьте Notifier:
Notifier будет использоваться для отображения сообщений об ошибках — например, когда Bluetooth выключен или соединение не может быть установлено.
В редакторе блоков, после добавления BluetoothClient, мы можем получить доступ к Bluetooth-блокам.
Я не буду описывать каждый шаг, но покажу блоки и объясню, что они делают.
Bluetooth-подключение
Для Bluetooth-подключения у нас есть 2 элемента экрана: кнопка CONNECT и ListPicker. ListPicker невидим. Также есть пустой список PAIRED_BT_DEVICE_LIST. При нажатии кнопки CONNECT вызывается функция BTN_CONNECT_BT.Click.
Сначала проверяется, включён ли Bluetooth. Если нет — отображается сообщение об ошибке. Затем проверяется, есть ли уже соединение — если есть, пользователю предлагается его закрыть.
Если Bluetooth включён и соединения нет, все сопряжённые устройства копируются в PAIRED_BT_DEVICE_LIST, и если длина списка > 0, значит есть хотя бы 1 сопряжённое устройство. Если список пуст — отображается ошибка. Если список не пуст, он копируется в ListPicker, и ListPicker активируется.
Использование списка может показаться излишним, но оно позволяет проверить наличие сопряжённых устройств. Без этого приложение может отобразить пустой список. Вместо отображения ListPicker и разрешения пользователю нажимать на него, я использую кнопку для его активации. Это даёт приложению дополнительную гибкость.
После выбора устройства из ListPicker вызывается блок ListPicker1.AfterPicking — здесь мы пытаемся установить соединение.
Если соединение успешно, изображение IMG_BT_INDICAT меняется на «circle_blue_100x100.png», а текст кнопки BT — на «CONNECTED». Если подключение не удалось — отображается ошибка.
При активном соединении нажатие кнопки CONNECT предлагает закрыть соединение. Notifier1.AfterChoosing обрабатывает ответ пользователя. При нажатии YES соединение закрывается, индикатор меняется на красный, а текст — на «NOT CONNECTED».
Если хотите проверить — настройте HC-06 или HC-05 (Arduino не нужен) и на Android-устройстве через Настройки => Bluetooth выполните сопряжение с Bluetooth-модулем. После этого запустите приложение и попробуйте подключиться.
Нажатия кнопок
Нажатия кнопок имеют 2 состояния — нажата и отпущена. В App Inventor 2 это реализуется блоками Button.TouchDown и Button.TouchUp.
Нам нужны оба блока для каждой кнопки, и каждая кнопка отправляет свою команду. Мы могли бы просто отправлять команду внутри этих блоков, но поскольку мы проверяем статус подключения перед отправкой, лучше создать отдельную процедуру sendCommand.
sendCommand получает команду для отправки, проверяет статус подключения и, если подключено, отправляет команду. Всегда полезно проверять статус перед отправкой — при попытке отправить данные без активного соединения вы получите системную ошибку.
Используйте процедуру sendCommand, вызвав её с передачей команды:
Теперь добавляем блоки для обработки нажатий кнопок. Помните — заглавные буквы для TouchDown, строчные для TouchUp.
Arduino
Основная часть приложения готова, можно приступить к стороне Arduino.
Поскольку эта статья о джойпаде, а не об Arduino, я использую очень простую схему и скетч для тестирования. Схема состоит из Arduino, Bluetooth-модуля HC-06 и делителя напряжения. Приложение отображает полученные данные в мониторе порта.
Схема
Пин RX модуля HC-06 работает на 3.3 В, а пин D9 Arduino — на 5 В. Поэтому нам нужно понизить напряжение с помощью делителя (резисторы 1 кОм и 2 кОм). Arduino видит 3.3 В как HIGH, поэтому на пине TX Bluetooth ничего делать не нужно — подключаем напрямую к D8.
Я использую HC-06 с настройками по умолчанию:
// basicSerial_AltSoftSerial_01
//
// Использует аппаратный serial для связи с компьютером
// и AltSoftSerial для связи с bluetooth-модулем.
// При получении данных через AltSoftSerial они копируются в монитор порта.
//
// Пины
// Arduino D8 (ASS RX) - BT TX (делитель напряжения не нужен)
// Arduino D9 (ASS TX) - BT RX через делитель напряжения
// Arduino 5V к BT VCC
// GND к GND
#include <AltSoftSerial.h>
AltSoftSerial BTSerial;
char c=' ';
void setup()
{
Serial.begin(9600);
Serial.println(" ");
BTSerial.begin(9600);
Serial.println("BTserial started at 9600");
}
void loop()
{
// Чтение из Bluetooth-модуля и отправка в монитор порта Arduino
if (BTSerial.available())
{
c = BTSerial.read();
Serial.println(c);
}
}
Приложение в действии
Загрузите код и запустите приложение.
При открытии приложения нажмите кнопку CONNECT — откроется страница подключения.
Нажмите кнопку NOT CONNECTED.
Отобразится список сопряжённых устройств. Выберите HC-06/HC-05 — приложение попытается подключиться.
Если подключение успешно, текст кнопки меняется на CONNECTED. Нажмите кнопку BACK для возврата на главный экран.
Индикатор подключения теперь синий.
С открытым монитором порта нажмите кнопки направления — вы должны увидеть коды управления.
Теперь попробуйте кнопки функций.