In diesem FAQ wird ein Android Smartphone mit einem Arduino über Bluetooth verbunden. Es werden Nachrichten in beide Richtungen übertragen.

 

 

Benötigte Bauteile:
# Bezeichnung ~Preis
1 Bluetooth-Seriell Modul RS232 (ebay) 6,00 €
1 LED 0,05 €
1 Widerstand 200 Ohm 0,01 €
    ~ 6 €

 

Benötigte Werkzeuge:
# Bezeichnung
1 Arduino
1 Breadboard
1 Android Smartphone
(Beispiel: Mindestens API Level 10 = Android 2.3.3 )

 

Aufbau:

Als erstes muss das Bluetooth Modul mit Strom versorgt werden. VCC an 5V und GND an GND.

Dann RX des Moduls an Arduino PIN 2 und TX des Moduls an Arduino PIN3:

 

Ansicht von oben:

Optional kann noch eine LED in Reihe mit einem 220 Ohm Widerstand an Arduino PIN 13 geschaltet werden oder die im Board integrierte verwendet werden.

 

Folgendes Codeschnippsel (beispiel_bluetooth.ino) leitet die seriellen Eingaben an das Bluetooth Modul weiter und umgekehrt. Jedes mal, wenn ein Zeichen empfangen wird, wird die Status LED ein- oder ausgeschaltet.

 

/* -------------------------------------------
/* Bluetooth Seriell senden und empfangen
/* www.frag-duino.de
/* -------------------------------------------
/* Befehle:
/* Sendet alles, was eingegeben wird
/* Empfaengt alles, was gesendet wurde
 ------------------------------------------- */

// Konstanten
#define PIN_RECEIVE 2
#define PIN_SEND 3
#define PIN_STATUS 13
#define SPEED_BLUETOOTH 9600
#define SPEED_SERIAL 9600

// INEX BT Board 9600
// Linkmatic 115200

// Includes
#include <SoftwareSerial.h>

// Variablen
SoftwareSerial blueSerial(PIN_RECEIVE, PIN_SEND);
int zustand_status = HIGH;

void setup()  
{
  Serial.begin(SPEED_SERIAL);
  Serial.println("Bluetooth Serial initialisiert");
  pinMode(PIN_STATUS, OUTPUT); 

  // auf seriellen Port horchen
  blueSerial.begin(SPEED_BLUETOOTH); 
  blueSerial.println("Bluetooth Serial Verbindung hergestellt");
}

void loop()
{
  // Sendet alles, was eingegeben wird.
  if (Serial.available())
    blueSerial.write(Serial.read());

  // Gibt alles aus, was empfangen wird:
  if (blueSerial.available()){
    Serial.write(blueSerial.read());
    if(zustand_status == HIGH)
      zustand_status=LOW;
    else zustand_status=HIGH;
  }
  digitalWrite(PIN_STATUS,zustand_status);
}

Im nächsten Schritt muss die MAC-Adresse des Bluetooth-Adapters ermittelt werden. Das geht z.B. indem man es in Windows koppelt (Code: 0000 oder 1234) und dann die Eigenschaften des Geräts einsieht ("Eindeutige ID"):

Auf Android-Seite, hilft die folgende Activity (blueActivity.java).

package de.fragduino.bluetest;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class blueActivity extends Activity {

	/*
	 * Arduino Bluetooth-Modul. Android Test-Applikation www.frag-duino.de
	 */

	// UUID fuer Kommunikation mit Seriellen Modulen
	private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	private static final String LOG_TAG = "FRAGDUINO";

	// Variablen
	private BluetoothAdapter adapter = null;
	private BluetoothSocket socket = null;
	private OutputStream stream_out = null;
	private InputStream stream_in = null;
	private boolean is_connected = false;
	private static String mac_adresse; // MAC Adresse des Bluetooth Adapters

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Log.d(LOG_TAG, "Bluetest: OnCreate");

		// Textfeld setzen
		((TextView) findViewById(R.id.text_uuid)).setText("UUID: " + uuid);

		// Verbindung mit Bluetooth-Adapter herstellen
		adapter = BluetoothAdapter.getDefaultAdapter();
		if (adapter == null || !adapter.isEnabled()) {
			Toast.makeText(this, "Bitte Bluetooth aktivieren",
					Toast.LENGTH_LONG).show();
			Log.d(LOG_TAG,
					"onCreate: Bluetooth Fehler: Deaktiviert oder nicht vorhanden");
			finish();
			return;
		} else
			Log.d(LOG_TAG, "onCreate: Bluetooth-Adapter ist bereit");
	}

	public void verbinden(View v) {
		mac_adresse = ((EditText) findViewById(R.id.text_adresse)).getText()
				.toString();
		Log.d(LOG_TAG, "Verbinde mit " + mac_adresse);

		BluetoothDevice remote_device = adapter.getRemoteDevice(mac_adresse);

		// Socket erstellen
		try {
			socket = remote_device
					.createInsecureRfcommSocketToServiceRecord(uuid);
			Log.d(LOG_TAG, "Socket erstellt");
		} catch (Exception e) {
			Log.e(LOG_TAG, "Socket Erstellung fehlgeschlagen: " + e.toString());
		}

		adapter.cancelDiscovery();

		// Socket verbinden
		try {
			socket.connect();
			Log.d(LOG_TAG, "Socket verbunden");
			is_connected = true;
		} catch (IOException e) {
			is_connected = false;
			Log.e(LOG_TAG, "Socket kann nicht verbinden: " + e.toString());
		}

		// Socket beenden, falls nicht verbunden werden konnte
		if (!is_connected) {
			try {
				socket.close();
			} catch (Exception e) {
				Log.e(LOG_TAG,
						"Socket kann nicht beendet werden: " + e.toString());
			}
		}

		// Outputstream erstellen:
		try {
			stream_out = socket.getOutputStream();
			Log.d(LOG_TAG, "OutputStream erstellt");
		} catch (IOException e) {
			Log.e(LOG_TAG, "OutputStream Fehler: " + e.toString());
			is_connected = false;
		}

		// Inputstream erstellen
		try {
			stream_in = socket.getInputStream();
			Log.d(LOG_TAG, "InputStream erstellt");
		} catch (IOException e) {
			Log.e(LOG_TAG, "InputStream Fehler: " + e.toString());
			is_connected = false;
		}

		if (is_connected) {
			Toast.makeText(this, "Verbunden mit " + mac_adresse,
					Toast.LENGTH_LONG).show();
			((Button) findViewById(R.id.bt_verbinden))
					.setBackgroundColor(Color.GREEN);
		} else {
			Toast.makeText(this, "Verbindungsfehler mit " + mac_adresse,
					Toast.LENGTH_LONG).show();
			((Button) findViewById(R.id.bt_verbinden))
					.setBackgroundColor(Color.RED);
		}
	}

	public void senden(View v) {
		String message = ((EditText) findViewById(R.id.text_eingabe)).getText()
				.toString();
		byte[] msgBuffer = message.getBytes();
		if (is_connected) {
			Log.d(LOG_TAG, "Sende Nachricht: " + message);
			try {
				stream_out.write(msgBuffer);
			} catch (IOException e) {
				Log.e(LOG_TAG,
						"Bluetest: Exception beim Senden: " + e.toString());
			}
		}
	}

	public void empfangen(View v) {
		byte[] buffer = new byte[1024]; // Puffer
		int laenge; // Anzahl empf. Bytes
		String msg = "";
		try {
			if (stream_in.available() > 0) {
				laenge = stream_in.read(buffer);
				Log.d(LOG_TAG,
						"Anzahl empfangender Bytes: " + String.valueOf(laenge));

				// Message zusammensetzen:
				for (int i = 0; i < laenge; i++)
					msg += (char) buffer[i];

				Log.d(LOG_TAG, "Message: " + msg);
				Toast.makeText(this, msg, Toast.LENGTH_LONG).show();

			} else
				Toast.makeText(this, "Nichts empfangen", Toast.LENGTH_LONG)
						.show();
		} catch (Exception e) {
			Log.e(LOG_TAG, "Fehler beim Empfangen: " + e.toString());
		}
	}

	public void trennen(View v) {
		if (is_connected && stream_out != null) {
			is_connected = false;
			((Button) findViewById(R.id.bt_verbinden))
					.setBackgroundColor(Color.RED);
			Log.d(LOG_TAG, "Trennen: Beende Verbindung");
			try {
				stream_out.flush();
				socket.close();
			} catch (IOException e) {
				Log.e(LOG_TAG,
						"Fehler beim beenden des Streams und schliessen des Sockets: "
								+ e.toString());
			}
		} else
			Log.d(LOG_TAG, "Trennen: Keine Verbindung zum beenden");
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		Log.d(LOG_TAG, "onDestroy. Trenne Verbindung, falls vorhanden");
		trennen(null);
	}
}

Dafür muss in der Android.manifest noch das Bluetooth-Recht gegeben werden:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.fragduino.bluetest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="de.fragduino.bluetest.blueActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />

</manifest>

Die Main.xml gestaltet das rudimentäre UI:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/text_uuid"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="UUID" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="MAC Adresse des Bluetooth Devices:" />

    <EditText
        android:id="@+id/text_adresse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:text="00:11:12:14:00:35" >
    </EditText>

    <Button
        android:id="@+id/bt_verbinden"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="verbinden"
        android:text="Verbinden" />

    <Button
        android:id="@+id/bt_verbinden"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="trennen"
        android:text="Trennen" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Eingabe:" />

    <EditText
        android:id="@+id/text_eingabe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:text="Test 123" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/bt_senden"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="senden"
        android:text="Senden" />

    <Button
        android:id="@+id/bt_empfangen"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="empfangen"
        android:text="Empfangen" />

</LinearLayout>

Zur Benutzung:

Bevor die Android-App gestartet wird, muss Bluetooth aktiviert worden sein und ein Paring mit dem Gerät geschehen. Bei meinem Dongle ("linvor") musste ich den Pin "1234" verwenden.

Das UI sieht folgendermaßen aus:

Als erstes muss die oben ermittelte MAC Adresse des Moduls eingetragen werden und der Button "Verbinden" gedrückt werden. War die Verbindung erfolgreich, ändert sich die Farbe des Buttons auf Grün:

Auftretende Fehler können unter dem Logtag "FRAGDUINO" eingesehen werden.

Ist die Verbindung erst hergestellt, kann eine Nachricht im Feld "Eingabe:" gemacht werden und mit "Senden" abgesendet werden.

Das Resultat auf Arduino-Seite (hier in der Arduino IDE im Serial Monitor) sieht dann so aus:

 

Um den umgekehrten Weg zu testen, muss eine Nachricht in der seriellen Konsole eingegeben und "Senden" geklickt werden. Die Nachricht erscheint dann in der Android-App, nachdem man den "Empfangen"-Button gedrückt hat:

Diese Vorgang könnte auch in einem eigenen Thread automatisiert werden.

Die Beispiel-Dateien gibt es hier:

bluetest.zip

Kommentare  

#1 Walter Doerler 2014-09-30 08:00
Hallo,
es geht auch ein wenig einfacher mit EZ-Link von Adafruit.
Selbst einen "Stand alone "Atmel 328P kann man damit
programmieren. BTW super Seite
#2 Tobias Neubronner 2016-03-10 12:13
Hallo,Super Seite. Ich hätte nur eine Frage ist es auch möglich das man sich verbinden kann, ohne die MAC Adresse einzugeben

Würde mich über eine Antwort freuen.
#3 Marcel I. 2016-03-10 12:57
Hey Tobias,

leider nein. Aber es müsste möglich sein, nach Bluetooth Geräten zu scannen und dann die verfügbaren Devices zur Auswahl anzubieten.

grüße
marcel
#4 Tobi 2016-07-31 21:40
Kann ich aus der blueActivity auch eine „normale“ Java-Klasse machen? Dass ich also in meiner Activity eine Instanz davon erstelle, die Verbinden Funktion aufrufe und dann bei zum Beispiel einem Buttonevent die senden Funktion aufrufe.
#5 Marcel I. 2016-08-01 14:36
Hallo Tobi,
ja das geht. Du solltest sogar die Funktionen in einem eigenen Thread aufrufen, damit die UI nicht hakt.
#6 grim 2017-01-27 19:51
Wo sieht man die Mac? braucht man dafür einen Bluetoothfähige n Rechner?
#7 Manfred K 2017-02-05 10:02
Hallo,
das Programm zeigt einen Fehler in der AndroidManifest.xml
offensichtlich wird die blueActivity nicht gefunden ( android:name="d e.fragduino.blu etest.blueActiv ity" ).

Woran kann das liegen ?
Gruß
Manfred
#8 Marcel I. 2017-02-05 16:15
Hallo Manfred,

das Tutorial habe ich vor etwa 4 Jahren geschrieben. Ich vermute es gibt Kompatibilitäts probleme mit der aktuellen Android IDE oder dem SDK. Die Fehlermeldung weist darauf hin, dass er die Klasse nicht finden kann. Prüf mal, ob sie so korrekt in deinem Projekt eingebunden ist.

grüße
Marcel
#9 Benjamin Färber 2017-10-27 09:09
Servus Leute
ich hocke gerade verzweifelt an meiner App dran und nimm mir die Vorlage als Hilfe. Ich muss nur eine App programmieren die mit Bluetooth Low Energy funktioniert.
Und weis nicht was ich alles brauche.
Kann mir jemand weiterhelfen ?