Jenseits des Smartphones: Android Things

Google wagt mit Android Things einen aggressiven Schritt in die Welt der Hardwaresteuerung. Das Risiko, das mit der Verwendung der Marke Android einhergeht, zeigt, dass der Suchmaschinenanbieter es ernst meint.

Know-how  –  0 Kommentare
Jenseits des Smartphones: Android Things

Googles Smartphone-Plattform ist eine gesetzte Größe, und zahlreiche Entwickler schreiben Android-Apps. Neben einer Vielzahl von Spielen gibt es zahlreiche Businessapplikationen, die von der Bauernhofverwaltung bis zur Berechnung komplexer Aktienalgorithmen reichen.

Die Verbreitung des Betriebssystems auf dem Smartphone ebnet den Weg für Android Things: Abbildung 1 zeigt, dass das System im Grunde genommen nicht viel mehr ist als das herkömmliche Android, das Google um einige hardwarespezifische Bibliotheken erweitert hat.

Android Things ist Android

Der wichtigste Unterschied zu einem gewöhnlichen Android-Betriebssystem besteht in der Things Support Library, die in zwei Unterbibliotheken unterteilt ist. Erstens gibt es die Peripheral I/O API, die den Zugriff auf diverse Hardwarebusse ermöglicht, und zweitens die User Driver API, mit der Anwender von ihren Sensoren angelieferte Informationen mit dem Rest des Betriebssystems teilen können.

Zudem unterscheidet sich Android Things vom herkömmlichen Android durch das Fehlen des für die Benutzerführung vorgesehenen GUI-Stacks: Features wie den Programmstarter, den Kalender oder die Telefonapplikation fehlen am IoT-Gerät. Zudem gibt es eine Liste von API-Änderungen – einige Programmierschnittstellen sind unter Android Things deaktiviert.

Anfang 2017 hat Google die Peripheral I/OAPI zudem mit einer Abstraktionsschicht ausgestattet, die den Zugriff auf häufig verwendete Hardwarebauteile erleichtern soll. Beim Erstellen dieses Artikels hat die Schnittstelle rund zwei Dutzend Sensoren und Aktoren unterstützt – weitere Informationen dazu finden sich auf GitHub.

Nach dem Stand beim Schreiben des Artikels unterstützt Android vier Entwicklerboards: Neben dem Raspberry Pi arbeitet das System auf einem NXP-Prozessrechner und auf Intels Joule- und Edison-Boards.

Die folgenden Schritte verwenden – schon wegen der guten Verfügbarkeit – den Raspberry Pi 3. Da das von Google bereitgestellte Android-Things-Image einen 64-Bit-Prozessor voraussetzt, ist es auf Vorgängermodellen nicht lauffähig. Zum Start lädt man das Image herunter und schreibt es auf eine SD-Karte mit mindestens 8 GByte.

Android Things funktioniert auch ohne Bildschirm. Dabei ist zu beachten, dass die Erkennung des Betriebsmodus direkt nach dem Einschalten erfolgt – später angeschlossene Bildschirme erkennt Android Things nicht.

Vor dem Anschluss der Energieversorgung ist der Prozessrechner mit Maus, Tastatur, Bildschirm und Netzwerkkabel zu verbinden. Aufgrund der mageren WLAN-Performance des Raspberry Pi 3 ist es nicht empfehlenswert, den ohnehin langsamen Debugging- und Deploymentprozess noch zusätzlich mit der Latenz einer WLAN-Verbindung zu belasten.

Nach dem Anschluss an die Energiequelle nimmt der erste Bootprozess mehr Zeit in Anspruch, weil der Prozessrechner seine SD-Karte konfigurieren muss. Eventuell im Rahmen des Bootens erscheinende Fehlermeldungen bezüglich Internetverbindung oder Netzwerkkabel sind weitgehend irrelevant. Wichtig ist nur der Inhalt des in der folgenden Abbildung gezeigten Startbildschirms:

Erscheint eine IP-Adresse, ist alles in Ordnung.

Wegen des vergleichsweise frühen Entwicklungsstands von Android Things ist das SDK noch nicht vollständig in Android Studio integriert. Entwickler sollten daher das entsprechende GitHub-Repository herunterladen und entpacken. Anschließend nutzen sie die Projekt-Importfunktion von Android Studio, um die von Google angelegte Struktur zu laden. Das Gradle-Buildsystem fordert während des ersten Kompilierens mehrfach zum Herunterladen benötigter Komponenten auf. Da Gradle bei jedem Durchlauf nur eine Komponente moniert, können einige Anläufe erforderlich sein.

Nach dem erfolgreichen Kompiliervorgang ist es an der Zeit, den Raspberry Pi 3 mit der Workstation zu verbinden. Aus softwaretechnischer Sicht kommt dabei die vom Zusammenspiel mit Smartphones bekannte Android Debug Bridge zum Einsatz. Die IP-Adresse des Prozessrechners lässt sich dem in der obigen Abbildung gezeigten Startbildschirm entnehmen. Folgende Befehle bauen die Verbindung auf:

~/Android/Sdk/platform-tools$ ./adb connect 10.42.0.44
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
connected to 10.42.0.44:5555
~/Android/Sdk/platform-tools$ ./adb devices
List of devices attached
10.42.0.44:5555 device

In der Manifestdatei des Programms finden sich einige Unterschiede zu herkömmlichen Android-Apps. Als Erstes fällt das Laden der Android-Things-Bibliothek auf, das durch ein uses-library-Tag bewerkstelligt wird:

<manifest xmlns:android=
"http://schemas.android.com/apk/res/android"
package="com.example.androidthings.myproject">
<application . . .>
<uses-library android:name="com.google.android.things"/>

Beim Deklarieren der Activity findet sich eine weitere Besonderheit: Da der Programmstarter fehlt, müssen Entwickler zusätzliche Inhalte einfügen, um das Programm beim Starten des Prozessrechnersystems zu aktivieren. Im von Google bereitgestellten Beispielskelett sieht der dafür zuständige Code folgendermaßen aus:

<activity android:name=".MainActivity">
...
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name=
"android.intent.category.IOT_LAUNCHER"/>
<category android:name=
"android.intent.category.DEFAULT"/>
</intent-filter>
</activity>

Um die Unterschiede darzulegen, wird im Folgenden der Vergleich der Stabilität von in Hardware und in Software erzeugten Wellenformen untersucht. Der Zugriff auf GPIO (Allzweickeingabe/-ausgabe) und PWM (Pulsweitenmodulation) erfolgt in Android Things gleichermaßen unter Nutzung der Peripheral I/O API. Zum Erzeugen einer charakteristischen Wellenform ist eine Instanz der GPIO-Klasse erforderlich, die Entwickler als Member der MainActivity[i] anlegen können:

public class MainActivity extends Activity {
Gpio myGPIO;

In [i]onCreated erfolgt die eigentliche Aktivierung. Google hat die Peripheral Manager Service API als klassischen Systemdienst implementiert. Er stellt eine Instanz der GPIO-Pins-Klasse bereit, die dem jeweiligen PIN zugeordnet ist. Zu guter Letzt startet das Programm einen Thread, der für die eigentliche Ausgabe der charakteristischen Wellenform verantwortlich sein wird:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PeripheralManagerService service =
new PeripheralManagerService();
try{
myGPIO = service.openGpio("BCM6");
myGPIO.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
myGPIO.setValue(true);
HeiseToggler myThread=new HeiseToggler(myGPIO);
new Thread( myThread ).start();
}catch (Exception e){}
}

Der eigentliche Thread nutzt die Runnable-Klasse:

public void run() {
try {
while(1==1){
myGpio.setValue(true);
myGpio.setValue(false);
myGpio.setValue(true);
myGpio.setValue(false);
}
}
catch (Exception e){}
}

Der nicht gezeigte Konstruktor nimmt eine GPIO-Instanz entgegen, die im nächsten Schritt regelmäßig ein- und ausgeschaltet wird. Jeder Durchlauf der Schleife führt zu zwei Wellenformausgaben. Das erlaubt das Isolieren der Berechnungszeit der Schleife nach dem in den folgenden Abbildungen gezeigten Schema:

Die Rechteckwelle zeigt ...
... dass der Berechnungsaufwand für die while-Schleife minimal ist.

Wirklich interessant ist die Stabilität der Wellenform. Nach dem Verbinden eines Modulationsdomänenanalysator mit dem betreffenden Pin liefert das Gerät das in der folgenden Abbildung gezeigte Resultat:

Sonderlich stabil ist diese Wellenform nicht.