Наша совместная команда Banwar.org

Связаться с нами

  • (097) ?601-88-87
    (067) ?493-44-27
    (096) ?830-00-01

Статьи

Передача даних по Bluetooth між Android і Arduino

  1. Arduino
  2. Android - передаємо дані в Arduino
  3. Android - прийом і передача даних до Arduino

у статті Arduino і Bluetooth було розглянуто один із способів передачі інформації між Android-пристроєм і ПК по Bluetooth-з'єднанню. Там же, в двох словах було згадано і Android-пристрій, але для прийняття і передачі даних використовувався Android Bluetooth термінал. Однак, для реальних пристроїв необхідна повноцінна програма (думати ж ми управляти тим же роботом з терміналу ...), написана для Android'а. У даній статті хотілося б торкнутися теми програмного забезпечення для роботи з Bluetooth, із застосуванням мови Java і середовища розробки Eclipse. Установка і настройка Eclipse добре описана в цій статті: Android і Arduino. Програмне забезпечення .

Arduino

Я буду використовувати Bluetooth модуль HC-06, проте для інших модулів HC-04, HC-05 і т.п. схема підключення така ж (за винятком світлодіода). Плата Arduino Nano V3.

Для наочності, до плати Arduino я підключив червоний світлодіод, до 12-піну, але можна використовувати і вбудований LED (зазвичай 13 пін).

Скетч для Arduino наступний:

char incomingByte; // вхідні дані int LED = 12; // LED підключений до 12 піну void setup () {Serial.begin (9600); // ініціалізація порту pinMode (LED, OUTPUT); Serial.println ( "Press 1 to LED ON or 0 to LED OFF ..."); } Void loop () {if (Serial.available ()> 0) {// якщо прийшли дані incomingByte = Serial.read (); // зчитуємо байт if (incomingByte == '0') {digitalWrite (LED, LOW); // якщо 1, то вимикаємо LED Serial.println ( "LED OFF. Press 1 to LED ON!"); // і виводимо назад повідомлення} if (incomingByte == '1') {digitalWrite (LED, HIGH); // якщо 0, то включаємо LED Serial.println ( "LED ON. Press 0 to LED OFF!"); }}}

Програма працює дуже просто. Після запуску або скидання пристрою, в послідовний порт виводиться повідомлення з пропозицією натиснути 1 або 0. Залежно від натиснутої (прийнятої) цифри світлодіод буде загорятися або гаснути. Загалом програма абсолютно така ж як і в статті: Arduino і Bluetooth.

Тепер, що стосується Android. Ми розглянемо два приклади, в першому ми будемо передавати дані від Android-пристрої до arduino, а в другому прикладі ми розглянемо двосторонній обмін даними між пристроями. Другий приклад складніше і в частині розуміння і за складністю коду, тому що використовуються потоки (thread).

Ми будемо використовувати Java код, з явним зазначенням MAC-адресу свого пристрою, до якого ми будемо підключатися. Оскільки якщо робити інтерфейс виявлення Bluetooth-пристроїв, їх вибору, підключення до них і т.д., то код буде дуже великий і для деяких читачів важкозрозумілі. Але для тих, кому цікаво можуть подивитися стандартний приклад Bluetooth Chat.

Дізнатися MAC-адресу можна наприклад в програмі для Android'а: Bluetooth Terminal:

Нас цікавить пристрій BOLUTEK (наш модуль HC-06, підключений до Arduino), його MAC адресу: 00: 15: FF: F2: 19: 4C. Його і треба буде надалі прописати в програмі.

Android - передаємо дані в Arduino

Перша програма дуже проста, головне вікно активують буде містити 2 кнопки: включити LED і вимкнути LED. При натисканні на кнопку включення LED, по Bluetooth буде передаватися "1", при натисканні на вимикання LED - "0".

У файлі маніфесту необхідно прописати 2 рядки дозволу роботи з Bluetooth:

Сам код головного активують:

package com.example.bluetooth1; import java.io.IOException; import java.io.OutputStream; import java.util.UUID; import com.example.bluetooth1.R; 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.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity {private static final String TAG = "bluetooth1"; Button btnOn, btnOff; private static final int REQUEST_ENABLE_BT = 1; private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; // SPP UUID сервісу private static final UUID MY_UUID = UUID.fromString ( "00001101-0000-1000-8000-00805F9B34FB"); // MAC-адресу Bluetooth модуля private static String address = "00: 15: FF: F2: 19: 4C"; / ** Called when the activity is first created. * / @Override public void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); btnOn = (Button) findViewById (R.id.btnOn); btnOff = (Button) findViewById (R.id.btnOff); btAdapter = BluetoothAdapter.getDefaultAdapter (); checkBTState (); btnOn.setOnClickListener (new OnClickListener () {public void onClick (View v) {sendData ( "1"); Toast.makeText (getBaseContext (), "Включаємо LED", Toast.LENGTH_SHORT) .show ();}}); btnOff.setOnClickListener (new OnClickListener () {public void onClick (View v) {sendData ( "0"); Toast.makeText (getBaseContext (), "Вимикаємо LED", Toast.LENGTH_SHORT) .show ();}}); } @Override public void onResume () {super.onResume (); Log.d (TAG, "... onResume - спроба з'єднання ..."); // Set up a pointer to the remote node using it's address. BluetoothDevice device = btAdapter.getRemoteDevice (address); // Two things are needed to make a connection: // A MAC address, which we got above. // A Service ID or UUID. In this case we are using the // UUID for SPP. try {btSocket = device.createRfcommSocketToServiceRecord (MY_UUID); } Catch (IOException e) {errorExit ( "Fatal Error", "In onResume () and socket create failed:" + e.getMessage () + "."); } // Discovery is resource intensive. Make sure it is not going on // when you attempt to connect and pass your message. btAdapter.cancelDiscovery (); // Establish the connection. This will block until it connects. Log.d (TAG, "... Єднаймося ..."); try {btSocket.connect (); Log.d (TAG, "... З'єднання встановлено і готове до передачі даних ..."); } Catch (IOException e) {try {btSocket.close (); } Catch (IOException e2) {errorExit ( "Fatal Error", "In onResume () and unable to close socket during connection failure" + e2.getMessage () + "."); }} // Create a data stream so we can talk to server. Log.d (TAG, "... Створення Socket ..."); try {outStream = btSocket.getOutputStream (); } Catch (IOException e) {errorExit ( "Fatal Error", "In onResume () and output stream creation failed:" + e.getMessage () + "."); }} @Override public void onPause () {super.onPause (); Log.d (TAG, "... In onPause () ..."); if (outStream! = null) {try {outStream.flush (); } Catch (IOException e) {errorExit ( "Fatal Error", "In onPause () and failed to flush output stream:" + e.getMessage () + "."); }} Try {btSocket.close (); } Catch (IOException e2) {errorExit ( "Fatal Error", "In onPause () and failed to close socket." + E2.getMessage () + "."); }} Private void checkBTState () {// Check for Bluetooth support and then check to make sure it is turned on // Emulator does not support Bluetooth and will return null if (btAdapter == null) {errorExit ( "Fatal Error" , "Bluetooth не підтримує"); } Else {if (btAdapter.isEnabled ()) {Log.d (TAG, "... Bluetooth включений ..."); } Else {// Prompt user to turn on Bluetooth Intent enableBtIntent = new Intent (btAdapter.ACTION_REQUEST_ENABLE); startActivityForResult (enableBtIntent, REQUEST_ENABLE_BT); }}} Private void errorExit (String title, String message) {Toast.makeText (getBaseContext (), title + "-" + message, Toast.LENGTH_LONG) .show (); finish (); } Private void sendData (String message) {byte [] msgBuffer = message.getBytes (); Log.d (TAG, "... Надсилаємо дані:" + message + "..."); try {outStream.write (msgBuffer); } Catch (IOException e) {String msg = "In onResume () and an exception occurred during write:" + e.getMessage (); if (address.equals ( "00: 00: 00: 00: 00: 00")) msg ​​= msg + ". \ n \ nВ змінної address у вас прописаний 00: 00: 00: 00: 00: 00, вам необхідно прописати реальний MAC-адресу Bluetooth модуля "; msg = msg + ". \ n \ nПроверьте підтримку SPP UUID:" + MY_UUID.toString () + "на Bluetooth модулі, до якого ви підключаєтеся. \ n \ n"; errorExit ( "Fatal Error", msg); }}}

Даний код знайдений на одному із зарубіжних блогів і злегка модернізований. Як видно вище, на кнопки ми вішаємо обробники подій. При натисканні на кнопку передається рядок 1 або 0 через sendData () в буфер Bluetooth адаптера. Повний проект з початковими кодами наведено нижче. Для роботи програми, необхідний Android не нижче версії API15, тобто 4.0.3 і вище.

Android - прийом і передача даних до Arduino

А ось тут довелося повозитися. Справа в тому, що в Android'е для прийому даних від будь-якого пристрою необхідно створювати окремий фоновий потік, щоб у нас не зависала основне активують. Для цього ми задіємо thread і всі дані будуть прийматися в окремому потоці.

На вікно головного активують ми додамо новий елемент TextView, який буде служити для відображення отриманих даних від Arduino. Сам java-код головного активують я постарався добре прокоментувати, щоб зробити його легким для читання:

package com.example.bluetooth2; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import com.example.bluetooth2.R; 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.os.Handler; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity {private static final String TAG = "bluetooth2"; Button btnOn, btnOff; TextView txtArduino; Handler h; private static final int REQUEST_ENABLE_BT = 1; final int RECIEVE_MESSAGE = 1; // Статус для Handler private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private StringBuilder sb = new StringBuilder (); private ConnectedThread mConnectedThread; // SPP UUID сервісу private static final UUID MY_UUID = UUID.fromString ( "00001101-0000-1000-8000-00805F9B34FB"); // MAC-адресу Bluetooth модуля private static String address = "00: 15: FF: F2: 19: 4C"; / ** Called when the activity is first created. * / @Override public void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); btnOn = (Button) findViewById (R.id.btnOn); // кнопка включення btnOff = (Button) findViewById (R.id.btnOff); // кнопка виключення txtArduino = (TextView) findViewById (R.id.txtArduino); // для виведення тексту, отриманого від Arduino h = new Handler () {public void handleMessage (android.os.Message msg) {switch (msg.what) {case RECIEVE_MESSAGE: // якщо прийняли повідомлення в Handler byte [] readBuf = (byte []) msg.obj; String strIncom = new String (readBuf, 0, msg.arg1); sb.append (strIncom); // формуємо рядок int endOfLineIndex = sb.indexOf ( "\ r \ n"); // визначаємо символи кінця рядка if (endOfLineIndex> 0) {// якщо зустрічаємо кінець рядка, String sbprint = sb.substring (0, endOfLineIndex); // то витягаємо рядок sb.delete (0, sb.length ()); // і очищаємо sb txtArduino.setText ( "Відповідь від Arduino:" + sbprint); // оновлюємо TextView btnOff.setEnabled (true); btnOn.setEnabled (true); } //Log.d(TAG, "... Рядок:" + sb.toString () + "Байт:" + msg.arg1 + "..."); break; }}; }; btAdapter = BluetoothAdapter.getDefaultAdapter (); // отримуємо локальний Bluetooth адаптер checkBTState (); btnOn.setOnClickListener (new OnClickListener () {// визначаємо обробник при натисканні на кнопку public void onClick (View v) {btnOn.setEnabled (false); mConnectedThread.write ( "1"); // Відправляємо через Bluetooth цифру 1 // Toast.makeText (getBaseContext (), "Включаємо LED", Toast.LENGTH_SHORT) .show ();}}); btnOff.setOnClickListener (new OnClickListener () {public void onClick (View v) {btnOff.setEnabled (false); mConnectedThread.write ( "0"); // Відправляємо через Bluetooth цифру 0 //Toast.makeText (getBaseContext (), "Вимикаємо LED", Toast.LENGTH_SHORT) .show ();}}); } @Override public void onResume () {super.onResume (); Log.d (TAG, "... onResume - спроба з'єднання ..."); // Set up a pointer to the remote node using it's address. BluetoothDevice device = btAdapter.getRemoteDevice (address); // Two things are needed to make a connection: // A MAC address, which we got above. // A Service ID or UUID. In this case we are using the // UUID for SPP. try {btSocket = device.createRfcommSocketToServiceRecord (MY_UUID); } Catch (IOException e) {errorExit ( "Fatal Error", "In onResume () and socket create failed:" + e.getMessage () + "."); } // Discovery is resource intensive. Make sure it is not going on // when you attempt to connect and pass your message. btAdapter.cancelDiscovery (); // Establish the connection. This will block until it connects. Log.d (TAG, "... Єднаймося ..."); try {btSocket.connect (); Log.d (TAG, "... З'єднання встановлено і готове до передачі даних ..."); } Catch (IOException e) {try {btSocket.close (); } Catch (IOException e2) {errorExit ( "Fatal Error", "In onResume () and unable to close socket during connection failure" + e2.getMessage () + "."); }} // Create a data stream so we can talk to server. Log.d (TAG, "... Створення Socket ..."); mConnectedThread = new ConnectedThread (btSocket); mConnectedThread.start (); } @Override public void onPause () {super.onPause (); Log.d (TAG, "... In onPause () ..."); try {btSocket.close (); } Catch (IOException e2) {errorExit ( "Fatal Error", "In onPause () and failed to close socket." + E2.getMessage () + "."); }} Private void checkBTState () {// Check for Bluetooth support and then check to make sure it is turned on // Emulator does not support Bluetooth and will return null if (btAdapter == null) {errorExit ( "Fatal Error" , "Bluetooth не підтримує"); } Else {if (btAdapter.isEnabled ()) {Log.d (TAG, "... Bluetooth включений ..."); } Else {// Prompt user to turn on Bluetooth Intent enableBtIntent = new Intent (btAdapter.ACTION_REQUEST_ENABLE); startActivityForResult (enableBtIntent, REQUEST_ENABLE_BT); }}} Private void errorExit (String title, String message) {Toast.makeText (getBaseContext (), title + "-" + message, Toast.LENGTH_LONG) .show (); finish (); } Private class ConnectedThread extends Thread {private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread (BluetoothSocket socket) {mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try {tmpIn = socket.getInputStream (); tmpOut = socket.getOutputStream (); } Catch (IOException e) {} mmInStream = tmpIn; mmOutStream = tmpOut; } Public void run () {byte [] buffer = new byte [256]; // buffer store for the stream int bytes; // bytes returned from read () // Keep listening to the InputStream until an exception occurs while (true) {try {// Read from the InputStream bytes = mmInStream.read (buffer); // Отримуємо кількість байт і саме собщение в байтовий масив "buffer" h.obtainMessage (RECIEVE_MESSAGE, bytes, -1, buffer) .sendToTarget (); // Відправляємо в чергу повідомлень Handler} catch (IOException e) {break; }}} / * Call this from the main activity to send data to the remote device * / public void write (String message) {Log.d (TAG, "... Дані для відправки:" + message + "... "); byte [] msgBuffer = message.getBytes (); try {mmOutStream.write (msgBuffer); } Catch (IOException e) {Log.d (TAG, "... Помилка відправки даних:" + e.getMessage () + "..."); }} / * Call this from the main activity to shutdown the connection * / public void cancel () {try {mmSocket.close (); } Catch (IOException e) {}}}}

В даному прикладі для відправки даних ми використовуємо окремий потік Thread. Теж саме і для прийому даних - метод run (). Також зверніть увагу на клас Handler, який служить для організації черги повідомлень і їх виведення в головне активують. Справа в тому, що в фоновому потоці можна безпосередньо виводити щось в головне активують, тому що це призведе до "фарбую" програми.
Клас StringBuilder використовується для формування рядки з прийнятих даних. Після, відбувається пошук кінця рядка з символами \ r \ n, і якщо вони знайдені, то рядок відображається на активують і об'єкт sb очищається, щоб не сталося склейка з подальшими прийнятими даними.

До статті додаються скомпільовані файли для Android: bluetooth1.apk і bluetooth2.apk, а також вихідні проекту для Arduino IDE і Eclipse

Прикріплені файли:

Теги:

Новости

Banwar.org
Наша совместная команда Banwar.org. Сайт казино "Пари Матч" теперь доступен для всех желающих, жаждущих волнения и азартных приключений.