В данной статье будет подробно расписано создание небольшого приложения для мобильной операционной системы Android и скетча для Arduino. На Arduino Uno будет стоять Wireless Shield с Bluetooth-модулем. Приложение будет подключаться к Bluetooth-модулю и посылать некую команду. В свою очередь скетч по этой команде будет зажигать или гасить один из подключенных к Arduino светодиодов.
Разработка для ОС 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». Заполним содержимое окна так, как показано на рисунке.
В выпадающих списках «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 — это то, что отображается на экране телефона после запуска приложения.
На нем у нас будет две кнопки «Зажечь красный светодиод» и «Зажечь синий светодиод». Добавим их. В панели «Package Explorer» открываем res/layout/activity_main.xml
. Его вид будет примерно таким же, как на скриншоте.
Перетаскиваем 2 кнопки «ToggleButton» на экранную форму. Переключаемся во вкладку «activity_main.xml» и видим следующий код:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_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" > <ToggleButton android:id="@+id/toggleButton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="ToggleButton" /> <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" /> </RelativeLayout>
Это ни что иное, как наша Activity, которая отображается не в виде графики, а описанная в формате XML.
Сделаем имена компонентов более понятными. Изменим поля android:id
следующим образом.
<ToggleButton android:id="@+id/toggleRedLed" ... <ToggleButton android:id="@+id/toggleGreenLed" ...
А еще добавим им подписи, изменим их цвет и размер текста. Результирующий код разметки будет выглядеть следующим образом.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="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"> <ToggleButton 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" /> <ToggleButton 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" /> </LinearLayout>
Эти же изменения можно сделать и в графическом режиме, воспользовавшись вкладкой «Outline/Properties».
Мы можем запустить только что созданное приложение на эмуляторе. Идем в настройки запуска «Run» → Run Configurations», в левой части нажимаем на «Android Application». Появляется новая конфигурация «New_configuration». В правой части окна выбираем вкладку «Target» и выбираем опцию «Launch on all compatible devices/AVD».
Нажимаем «Apply», а затем «Run». Приложение запустится в эмуляторе.
Можно понажимать кнопки. Но ничего происходить не будет, поскольку обработчики нажатий еще нами не написаны.
Чтобы запустить приложение на реальном устройстве, необходимо включить в его настройках опцию «Отладка USB» и подключить его к компьютеру.
На реальном устройстве приложение выглядит абсолютно аналогично.
Каждое Android-приложение должно сообщить системе о том, какие права необходимо ему предоставить. Перечисление прав идет в так называемом файле манифеста AndroidManifest.xml
. В нем мы должны указать тот факт, что хотим использовать Bluetooth в своем приложении.
Для этого достаточно добавить буквально пару строк:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ru.amperka.arduinobtled" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10" /> <!-- Разрешаем приложению работать с Bluetooth --> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="ru.amperka.arduinobtled.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Пришла пора вдохнуть жизнь в наше приложение. Открываем файл MainActivity.java
(src → ru.amperka.arduinobtled). Изначально он содержит следующий код:
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) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
Дополним код в соответствии с тем, что нам нужно:
Передавать на Arduino мы будем один байт с двузначным числом. Первая цифра числа — номер пина, к которому подключен тот или иной светодиод, вторая — состояние светодиода: 1 — включен, 0 — выключен.
Число-команда, рассчитывается очень просто: Если нажата красная кнопка, то берется число 60 (для красного светодиода мы выбрали 6-й пин Arduino) и к нему прибавляется 1 или 0 в зависимости от того, должен ли сейчас гореть светодиод или нет. Для зеленой кнопки всё аналогично, только вместо 60 берется 70 (поскольку зеленый светодиод подключен к 7 пину). В итоге, в нашем случае, возможны 4 команды: 60, 61, 70, 71.
Напишем код, который реализует всё сказанное.
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 e) { Log.d("BLUETOOTH", e.getMessage()); } catch (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()); } } }
Данные, которые принимает Bluetooth-модуль, приходят через UART (он же Serial-соединение) на скорости 9600 бит/с. Настраивать Bluetooth-модуль нет никакой необходимости: он сразу готов к работе. Поэтому скетч должен уметь следующее:
void setup() { //Устанавливаем скорость UART Serial.begin(9600); //Настраиваем нужные пины на выход pinMode(6, 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 и ещё много-много всего интересного!