Die neusten Version der RaspiBrick-Firmware (raspibrick.zip), die unter dem MenüPunkt Installation oder von hier heruntergeladen werden kann, unterstützt sowohl den eingebauten Bluetooth-Chip des Raspberry Modell 3 und des Raspberry ZeroW, wie auch die meisten USB Bluetooth-Dongles auf dem Raspberry Pi Modell 2. Das Bluetooth wird automatisch beim Start des Pi2Go-Roboters aktiviert. Der Computer oder Smartphone erkennt den Raspberry Pi mit dem Namen raspberrypi und kann sich ohne Authentifizierung paaren. Bei der Paarung wird auch die die MAC-Adresse ermittelt und zusammen mit dem Bluetooth-Namen gespeichert. Wie bei TCP/IP erfolgt die Datenübertragung auch bei Bluetooth unter Verwendung der Client-/Server-Technologie. Zuerst muss das Serverprogramm, das in der Regel auf dem Raspberry Pi läuft, gestartet werden und erst dann kann der Client eine Verbindung aufbauen. |
Beispiel 1: Fernsteuerung mit Computer Bluetooth-Server wird auf dem Pi2Go gestartet. Der Bluetooth-Client, der auf dem Computerläuft, erstellt zuerts eine Verbindung zum Server unter der Verwendung des Bluetooth-Name oder der Mac-Adresse des Raspberry Pi. Ist die Verbindung hergestellt, kann der Client die Befehle für vorwärts, rückwärts, links, rechts und stop zum Pi2Go senden und ihn dadurch fernsteuern. |
Das Server-Programm BtRobot.py wird auf den Pi2Go heruntergeladen und dort ausgeführt:
# BtRobot.py from raspibrick import * from btpycom import * def onStateChanged(state, msg): if state == "LISTENING": display.showText("LI") elif state == "CONNECTED": display.showText("conn") elif state == "MESSAGE": go(msg) display.showText("go") def go(msg): if msg == "FORWARD": gear.forward() elif msg == "BACKWARD": gear.backward() elif msg == "RIGHT": gear.rightArc(0.1) elif msg == "LEFT": gear.leftArc(0.1) elif msg == "STOP": gear.stop() robot = Robot() gear = Gear() display = Display() serviceName = "BTRobot" server = BTServer(serviceName, stateChanged = onStateChanged) while not isEscapeHit(): Tools.delay(100) server.terminate() robot.exit() |
Programmcode markieren
|
onStateChanged(): Im Callback onStateChanged() wird beim Empfang eines Befehls die entsprechende Funktion aufgerufen. | |
display.showText("LI"): Falls der Pi2Go über ein Display verfügt, können kurze Meldungen (4 Zeichen) angezeigt werden. Noch viel besser ist es ein OLED 1306 anzuschliessen, mit dem mehrere Textzeilen angezeigt werden können. Das gleiche Programm mit OLED-Display finden Sie hier. |
Die Fernsteuerung erfolgt mit dem Client-Programm BtRobotControl.py, welches auf dem Computerläuft. Die Befehle werden mit Klick auf Buttons in einem Dialogfenster gesendet. Es empfiehlt sich, das Client-Programm in einem zweiten TigerJython-Fenster auszuführen, damit man eventuelle Rückmeldungen beim Programmdownload auf den Pi2Go-Roboter im ersten TigeJython-Fenster lesen kann. |
.
# BtRobotControl.py from entrydialog import * from btcom import * def showDialog(): global dlg, buttons buttons = [ButtonEntry("Left"), ButtonEntry("Forward"), ButtonEntry("Stop"), ButtonEntry("Backward"), ButtonEntry("Right")] pane = EntryPane(buttons[0], buttons[1], buttons[2], buttons[3], buttons[4]) dlg = EntryDialog(pane) dlg.setTitle("Remote Control") dlg.show() showDialog() commands = ["LEFT", "FORWARD", "STOP", "BACKWARD", "RIGHT"] def onStateChanged(state, msg): pass serviceName = "BTRobot" client = BTClient(stateChanged = onStateChanged) dlg.setTitle("Searching for rover. Please wait...") serverInfo = client.findService(serviceName, 30) #serverInfo = ('B8:27:EB:B3:E7:A6', 1) if serverInfo == None: dlg.setTitle("Robot not found") else: if client.connect(serverInfo, 20): dlg.setTitle("Connected to " + serverInfo[0]) while not dlg.isDisposed(): for n in range(len(buttons)): if buttons[n].isTouched(): client.sendMessage(commands[n]) client.disconnect() |
Programmcode markieren
|
serverInfo = client.findService(): Im Callback onStateChanged() wird beim Empfang eines Befehls die entsprechende Funktion aufgerufen. |
Beispiel 2: Fernsteuerung mit einer Android App |
Die Android-App RobotControl.apk wurde dem Framework JDroidLib erstellt. Sie können die fertige App mit dem untenstehendem Link oder mit dem QR-Code herunterladen und auf ihrem Smartphone installieren. Die App kann mit unserem Online-Compiler modifiziert und neu erstellt werden, sodass kein lokales Android-Entwicklungssystem installiert werden muss. |
Android App RobotControl.apk mit QR-Code installieren |
Programmcode für Androd App:
// RobotControl.java package robotcontrol.app; import ch.aplu.android.*; import android.graphics.Color; import android.bluetooth.*; import ch.aplu.android.bluetooth.*; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class RobotControl extends GameGrid implements GGPushButtonListener { private GGPushButton forward; private GGPushButton backward; private GGPushButton left; private GGPushButton right; private GGPushButton stop; private GGTextField tf; private BluetoothClient bc; private DataInputStream dis; private DataOutputStream dos; public RobotControl() { super(21, 21, 0); setScreenOrientation(PORTRAIT); } public void main() { String serverName = askName(); getBg().clear(Color.BLUE); new GGTextField("RobotControl", new Location(0, 1), true).show(); addButtons(); tf = new GGTextField("Trying to connect...", new Location(4, 19), true); tf.show(); // Search device BluetoothDevice serverDevice = searchDevice(serverName); if (serverDevice != null) { bc = new BluetoothClient(serverDevice); boolean rc = bc.connect(); if (!rc) { tf.hide(); tf = new GGTextField("Connection failed", new Location(4, 19), true); tf.show(); return; } tf.hide(); tf = new GGTextField("Connection established", new Location(3, 19), true); tf.show(); dis = new DataInputStream(bc.getInputStream()); dos = new DataOutputStream(bc.getOutputStream()); enableButtons(); } } private String askName() { GGPreferences prefs = new GGPreferences(this); String oldName = prefs.retrieveString("BluetoothName"); String newName = null; while (newName == null || newName.equals("")) { newName = GGInputDialog.show(this, "RobotControl", "Enter Bluetooth Name", oldName == null ? "raspberrypi" : oldName); } prefs.storeString("BluetoothName", newName); return newName; } private void addButtons() { forward = new GGPushButton("forward"); addActor(forward, new Location(10, 5)); backward = new GGPushButton("backward"); addActor(backward, new Location(10, 15)); left = new GGPushButton("left"); addActor(left, new Location(3, 10)); right = new GGPushButton("right"); addActor(right, new Location(17, 10)); stop = new GGPushButton("stop"); addActor(stop, new Location(10, 10)); } private void enableButtons() { forward.addPushButtonListener(this); backward.addPushButtonListener(this); left.addPushButtonListener(this); right.addPushButtonListener(this); stop.addPushButtonListener(this); } public void onPause() { super.onPause(); } public void buttonPressed(GGPushButton button) { if (button == forward) sendMessage("FORWARD"); if (button == backward) sendMessage("BACKWARD"); if (button == left) sendMessage("LEFT"); if (button == right) sendMessage("RIGHT"); if (button == stop) sendMessage("STOP"); } public void buttonReleased(GGPushButton button) { } public void buttonClicked(GGPushButton button) { } public void buttonRepeated(GGPushButton button) { } private void sendMessage(String msg) { try { dos.writeBytes(msg + "\0"); dos.flush(); } catch (IOException ex) { tf.hide(); tf = new GGTextField("Connection lost", new Location(3, 19), true); tf.show(); } } private BluetoothDevice searchDevice(String btName) { BluetoothAdapter adapter = BluetoothDiscovery.getBluetoothAdapter(this); if (adapter == null) return null; if (!adapter.isEnabled()) { requestBluetoothEnable(); if (!adapter.isEnabled()) return null; } BluetoothDiscovery bd = new BluetoothDiscovery(this); BluetoothDevice device = bd.getPairedDevice(btName); return device; } } |
Programmcode markieren
|
Erklärungen zum Programmcode:
Weitere Information zur Entwicklung von Android-Apps mit dem Framework JDroidLib findet man unter www.jdroid.ch . |