Teil 2: Die GPIO des Raspberry Pi 2 mit Java optimal ausreizen

Raspberry Pi 2: GPIO mit Java programmieren
Kommentare

Der Raspberry Pi wird als Mediacenter oder auch als Miniserver im Heimnetzwerk eingesetzt. Ein weiterer interessanter Aspekt des Raspberry Pi ist seine GPIO. Mit ihr ist es möglich, die unterschiedlichste Hardware an den Raspberry Pi anzubinden. Wie man die GPIO mit Java optimal ausreizt, erklärt diese Artikelserie. In Teil 2 widmen wir uns dem Programmieren des Raspi mit Java.

Mit dem Raspberry Pi Typ 2 ist Anfang 2015 ein wirklich sehr leistungsfähiger Vertreter der Pi-Familie auf den Markt gekommen. Mit seinem ARM-Cortex-A7-Chip ist er seinen Vorgängern um Längen überlegen. Auf dem Raspberry Pi 2 kann man ohne Probleme Java als Programmiersprache verwenden. Diese Artikelserie wird Schritt für Schritt erklären, was zu tun ist, um mit Java die GPIO des Raspberry Pi zu verwenden. Wir zeigen am Beispiel einer Dachfenstersteuerung, was alles mit der GPIO und Java möglich ist. Nachdem wir im ersten Teil die Details der GPIO beleuchtet und Java auf dem Raspi installiert haben, geht es jetzt an das Programmieren mit Java. In Teil 3 beginnen wir ein echtes Projekt und bauen eine Dachfenstersteuerung. Dazu blicken wir zunächst auf die benötigte Hardware wie Taster und Temperatursensor und erläutern im vierten Teil die Programmierung von Servomotor und Display.

Artikelreihe

Raspberry Pi Zwischenstopp

Wie wir im ersten Teil gesehen haben, war ziemlich viel Arbeit nötig, um Java auf den Raspberry Pi zu bekommen. Wir benötigen es allerdings, um die GPIO verwenden zu können. Alle diese Vorarbeiten sind nötig, um in Teil zwei unsere Dachfenstersteuerung aufbauen zu können. Mit der vorliegenden Installation können Sie bereits mit eigenen Experimenten der GPIO und Java starten.

Hardware

Alle Einzelteile lassen sich, wie in Abbildung 1 zu sehen ist, leicht auf eine kleine Lochrasterplatine auflöten. Der Schaltplan (Abb. 2) zeigt Ihnen genau, wie alle Teile zusammen gehören. Er ist als gEDA- und .eps-Datei auf der Heft-DVD und auf der Website zur Ausgabe vorhanden. Das einzige kniffelige Bauteil ist der Temperatursensor, da er nur das halbe Rastermaß hat. Es gibt viele Möglichkeiten, ihn zu verbauen; eine der eleganteren Methoden ist es, ihn auf eine Adapterplatine für SOP8 nach DIL8 zu löten.

mohr_raspberry_1_2

Abb. 1: Die komplett aufgebaute Platine

mohr_raspberry_2_2

Abb. 2: Der Schaltplan zeigt, wie alles zusammengebaut werden muss

Im Handel sind unterschiedliche Versionen des Nokia-5110-Displays zu bekommen, die sich durch die Pinbelegung unterscheiden. Die Taster für die Temperatureinstellung sind verdrahtet, wie in unserem Beispiel aus dem ersten Teil des Artikels.

Generell sollte man bei elektrischen Antrieben (z. B. Servomotor) darauf achten, sie über eine getrennte Spannungsquelle zu versorgen, da sie Störungen verursachen können, die den Raspberry Pi zum Absturz bringen. Wir gehen hier noch einen Schritt weiter und trennen die Signalleitung zwischen Raspberry Pi und Servomotor galvanisch. Dieser spezielle Aufbau hat zusätzlich den Vorteil, dass das Signal nicht um 180 Grad gedreht wird, wie es eine normale Transistorverstärkerstufe machen würde. Das Display und der Sensor sind zur Betriebsspannung des Raspberry Pi (3,3 Volt) kompatibel und benötigen daher keine Pegelanpassungen.

Taster

Um die Taster zu testen, verwenden wir die gleiche Methode wie im ersten Teil:

pi@raspberrypi ~ $ gpio mode 1 in 
pi@raspberrypi ~ $ gpio mode 2 in
pi@raspberrypi ~ $ watch -n 0.5 'gpio read 1 ; gpio read 2' 

Wenn sich beim Löten kein Fehler eingeschlichen hat, sollten Sie den Status der Schalter auf dem Bildschirm sehen.

Temperatur messen

Zum Messen der Temperatur kommt ein handelsüblicher I2C-Temperatur-/-Luftfeuchtigkeitssensor zum Einsatz. Der AM2321 kann hier bestellt werden. Im Datenblatt zum Sensor AM2321 finden sich viele wichtige Informationen. Um den Sensor testen zu können, müssen wir uns zuerst den I2C-Treiber installieren. Das klappt leider nicht so reibungslos, wie man es erwarten würde. Fangen wir erst einmal damit an, die Raspi-Config (sudo raspi-config) zu starten. Unter den „8 Advanced Options“ findet sich der Unterpunkt „A7 I2C“; dort sind einfach alle Fragen mit ja zu beantworten. Das raspi-config-Tool bootet beim Verlassen den Raspberry Pi automatisch neu. Nach dem Neustart sollten die nötigen Treiber vorhanden sein. Unschönerweise funktioniert es so nicht richtig – es sind noch einige manuelle Eingriffe nötig, bis alles so klappt, wie es soll.

Falls die Datei /etc/modprobe.d/raspi-blacklist.conf auf Ihrem System vorhanden ist, müssen Sie dort die Zeile blacklist i2c-bcm2708 mit einem # auskommentieren. Danach überprüfen Sie, ob in der Datei /etc/modules die folgenden Einträge vorhanden sind:

i2c-bcm2708
i2c-dev

Falls sie nicht vorhanden sind, tragen Sie diese bitte mit ein. Zu guter Letzt müssen Sie auch noch die /boot/config.txt anpassen und folgende Zeile hinzufügen, falls diese nicht vorhanden ist: dtparam=i2c_arm=on

Damit wir die Möglichkeit haben, unseren I2C-Hardwareaufbau zu testen, benötigen wir noch die i2c-Tools, die sich mit folgendem Befehl installieren lassen: sudo apt-get install i2c-tools.

Damit wir später nicht immer als Superuser arbeiten müssen, nehmen wir den User pi mithilfe von sudo adduser pi i2c mit in die Gruppe i2c auf.

Um alle Änderung zu aktivieren, müssen wir jetzt einen Reboot durchführen: sudo reboot. Wir dürfen natürlich nicht vergessen, den I2C-Treiber mittels gpio load i2c auch zu laden, bevor wir mit den Tests beginnen können. Das Warning, das hier auftritt, ist nicht weiter tragisch, da wir den I2C-Bus-0 nicht verwenden.

Als Erstes überprüfen wir, ob sich unser IO-Baustein auch am I2C-Bus meldet. Das bewerkstelligen wir mit dem Befehl aus Listing 4.

pi@raspberrypi ~ $ i2cdetect -y 1 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@raspberrypi ~ $ i2cdetect -y 1 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- 5c -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@raspberrypi ~ $ 

Dem aufmerksamen Leser wird sicherlich aufgefallen sein, dass sich der AM2321 beim zweiten Aufruf von i2cdetect unter der Adresse 0x5c meldet. Das liegt daran, dass dieser Sensor eine ausgeklügelte Energiesparfunktion hat: Beim ersten Zugriff wird der Baustein aus seinem Schlafmodus geweckt. Ist der AM2321 wach, kann man mit dem zweiten Zugriff die Werte des Sensors lesen. Das zweite Lesen legt ihn dann auch gleich wieder schlafen.

Warum wird hier so ein Aufwand betrieben? Zum einen, um Energie zu sparen, da der Sensor in mobilen Geräten verbaut werden soll. Der zweite wichtige Grund ist, dass der Sensor durch seine eigene Wärmeentwicklung die Messwerte verfälschen würde. Im Datenblatt ist diese Funktion sehr genau beschrieben.

Tipp: Der richtige Editor

Falls Sie Ihre Java-Programme nicht mit vi direkt auf dem Raspberry Pi editieren möchten, zeige ich Ihnen einen kleinen Trick, mit dem Sie Ihren Lieblingseditor zum Programmieren verwenden können. NFS – Network File System – heißt die Lösung. Mit NFS kann man Filesysteme ins Netzwerk exportieren, die sich dann auf dem Linux-PC wieder bequem einbinden lassen.

Um den NFS-Server auf dem Raspberry Pi zu installieren, verwenden wir folgenden Befehl:

sudo apt-get install nfs-server

Nach erfolgreicher Installation können wir in der Datei /etc/exports festlegen, welche Dateisysteme an andere Rechner exportiert werden sollen. Die folgende Zeile gewährt jedem Client Zugriff auf das Homeverzeichnis des Users pi auf unseren Raspberry. Das sollte man daher nur so machen, wenn es sich um ein lokales (sicheres) Netzwerk handelt …:

sudo nano /etc/exports
/home/pi *(rw,no_subtree_check)

Jetzt müssen wir dafür sorgen, dass der Portmap Deamon gestartet ist. Danach kann der NFS-Server gestartet werden:

sudo /etc/init.d/rpcbind restart 
sudo /etc/init.d/nfs-kernel-server restart

Der Kernel des Raspberry kennt kein IP v6, daher können wir die Fehler, die beim Starten des NFS-Servers auftreten, ignorieren. Um nun von einem Client (Linux-PC) aus auf das NFS-Verzeichnis zugreifen zu können, müssen wir das Filesystem mounten. Das kann man mit folgendem Befehl unter Linux bewerkstelligen:

sudo mount -t nfs 192.168.2.6:/home/pi /mnt

Falls es nicht funktionieren sollte, ist vermutlich die NFS-Clientsoftware nicht auf Ihrem PC installiert. Abhängig von der Distribution gibt es dafür unterschiedliche Wege. Unter Ubuntu z. B. kann man Software bequem über das Softwarecenter installieren. Schauen Sie bitte in die Hilfe Ihrer Distribution, wie zusätzliche Software installiert werden muss.

Unter /mnt ist nun das Homeverzeichnis des Users pi auf unserem Raspberry eingebunden. Die dort befindlichen Dateien können nun frei editiert werden. Kommt es dabei zu Problemen, hilft oft ein Blick mit ls -lisa auf die Berechtigungen der Dateien und Verzeichnisse.

Servomotor

Um das Dachfenster unseres Modellhäuschens zu öffnen, verwenden wir einen handelsüblichen Modellbauservo. Der Motor wird über das Tool Servoblaster angesteuert. Wie Sie im Schaltplan 1 (Abb. 2) gut sehen können, ist der Motor komplett galvanisch vom Raspberry Pi getrennt und wird, wie oben beschrieben, über eine separate Spannungsquelle betrieben.

Das Testen der einzelnen Komponenten ist ein wichtiger Bestandteil eines solchen Projekts. Leider lassen sich Servos nicht mit einem einfachen Logiksignal testen, da sie ein spezielles PWM-Signal benötigen. Der einfachste Weg, den Motor zu testen, ist daher das Tool Servoblaster. Mit ihm kann man bis zu 21 Servomotoren über die GPIO des Raspberrys bequem über die Kommandozeile steuern. Die Installation ist recht einfach. Um den Servoblaster für den Raspberry 1 herunterzuladen und zu installieren, sind folgende Schritte auszuführen:

git clone git://github.com/richardghirst/PiBits.git 
cd PiBits/ServoBlaster/user 
make 

Für den Raspberry Typ 2 ist eine gepatchte Version des Servoblasters nötig; sie kann hier heruntergeladen werden.

tar -xvzf ServoBlaster-20150219.tgz 
cd ServoBlaster
make

Als ob das nicht schon genug wäre, gibt es bei einigen Kernel-Firmware-Kombinationen immer noch einen Fehler (mknod /dev/servoblaster-mb c 100 0), sodass man den Patch noch einmal patchen muss, damit es geht. Falls Sie von diesem Problem betroffen sind, müssen Sie im servod folgende Zeile ändern:

if (mknod(filename, S_IFCHR|0600, makedev(100, 0)) < 0) {

Die 100 muss durch eine 249 ersetzt werden. Danach wird noch einmal ein make ausgeführt, um die Änderungen zu kompilieren.

Um den Userspace-Treiber für einen Servomotor zu laden, müssen wir die folgende Zeile verwenden:

sudo ./servod --p1pins=11 --pcm

Die Option –pcm verhindert, dass der Servoblaster den internen PWM-Generator des Raspberry Pi verwendet, der normalerweise für die Soundausgabe verwendet wird. Eine weitere wichtige Option, die man kennen sollte, ist — invert, mit der das Ausgangssignal invertiert wird. Das ergibt Sinn, falls man einen einstufigen Transistorverstärker zur Pegelanpassung des Servosignals verwenden möchte.

Sollten wir in die Verlegenheit kommen, den Servoblaster beenden zu müssen, killen wir einfach alle servod-Prozesse mit sudo killall servod.

Der servod erstellt uns einen Gerätetreiber, der recht einfach zu bedienen ist. Mit der folgenden Anweisung wird dem Servo 0 der Wert 140 zugewiesen, was normalerweise in etwa der Mittelposition des Motors entspricht:

echo 0=140 > /dev/servoblaster 

Jetzt können wir einfach testen, ob unser Aufbau soweit funktioniert. Unterschiedliche Servomotor-Modelle verhalten sich auch leicht unterschiedlich. Man muss immer etwas herumprobieren, um die Werte für die gewünschten Positionen zu ermitteln.

Display

Als Display verwenden wir ein normales, wenn auch etwas altmodisches Nokia-5110-Display. Es hat eine Auflösung von 84 x 48 Pixel. Um das Nokia-Display anzusteuern, gibt es verschiedene C-Bibliotheken im Internet; leider hat sich keine einzige Java-Bibliothek finden lassen. Das soll uns hier aber nicht aufhalten. Wir verwenden einfach die vorhandene freie C-Bibliothek aus dem Internet und übersetzen sie in Java. Die teilweise übersetzte Bibliothek liegt übrigens ebenfalls auf der Heft-DVD und auf der Website zum Magazin. Die Bibliothek ist nur so weit übersetzt, wie wir es für unser kleines Projekt benötigen; das C-Original bietet einiges mehr an Funktionen. Der nicht übersetzte Sourcecode ist auskommentiert, aber in der Bibliothek noch vorhanden. Falls jemand einer dieser Funktionen verwenden möchte, kann man sie einfach noch in Java übersetzen.

Damit die übersetzte Bibliothek funktioniert, muss erst einmal der passende Treiber aktiviert werden. Das erledigen wir wie schon beim I2C über die Raspi-Config (sudo raspi-config). Dort gehen wir wieder in die „8 Advanced Options“, wo wir dann „A6 SPI“ auswählen und dort alles aktivieren. Danach müssen wir beim Beenden wie gewohnt rebooten. Auch beim SPI-Treiber werden wir noch einmal selbst Hand anlegen, damit es funktioniert. In der Datei /etc/modules (sudo nano /etc/modules) benötigen wir noch zwei zusätzliche Einträge:

spi_bcm2835 
spidev

Auch ist es ist nötig, in der /boot/config.txt (sudo nano /boot/config.txt) noch zwei zusätzliche Einträge zu hinterlassen:

dtparam=spi=on 
dtoverlay=spi-bcm2835 

Damit diese Änderungen wirksam werden, müssen wir noch einen Reboot durchführen.

Die Hardware zur Ansteuerung des Displays ist auf der einen Seite leicht aufzubauen, weil das Display mit den 3,3 Volt der GPIO der Raspberrys ohne Pegelwandlung zurechtkommt. Auf der anderen Seite gibt es verschiedene Versionen des Nokia-Displays, die – wie sollte es auch anders sein – unterschiedliche Pinbelegungen haben. Daher ist es wichtig, sich das Datenblatt des Displays genau anzusehen und sich beim Aufbau an den Namen der Pins zu orientieren und nicht an den Nummern. Im Schaltplan ist zu sehen, wie das Display angeschlossen werden muss. Um die Funktion des Displays zu testen, müssen wir ein erstes kleines Programm schreiben. Es kann einfach, wie im ersten Teil beschrieben gebaut und gestartet werden. Bitte achten Sie darauf, dass sich die Java-Datei PCD8544.java im gleichen Verzeichnis befindet (Listing 5). Die PCD8544.java ist die angepasste Bibliothek, die auf der Heft-DVD und auf der Website zu dieser Ausgabe zu finden ist.

import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.RaspiPin;


public class DisplayTest {
  // Pinbelegung des Displays
  final static Pin dc = RaspiPin.GPIO_04;
  final static Pin rst = RaspiPin.GPIO_05;
  static byte contrast = (byte)0xff;
  public static void main(String[] args) throws Exception {
    // init and clear lcd
    PCD8544 pcd = new PCD8544();
    pcd.LCDInit(dc,rst,contrast);
    pcd.LCDclear();
    pcd.LCDdrawstring(0, 0, "Hallo Pi");
    pcd.LCDdisplay();
  }

}// class

Endlich Java

Nachdem wir nun alle Einzelkomponenten getestet haben, können wir jetzt damit starten, alles zusammen zum Laufen zu bringen. Nachdem unser Dachfenstersteuerprogramm alle nötigen Initialisierungsschritte erledigt hat, fragt das Programm jede Sekunde den Temperatursensor ab und vergleicht den Messwert mit dem Vorgabewert. Ist die Temperatur über dem eingestellten Wert, wird das Fenster geöffnet. Sinkt sie unter den eingestellten Wert, wird es wieder geschlossen.

Im realen Einsatz sollte man darüber nachdenken, den Sensor seltener abzufragen, weil er sich dadurch erwärmt und die Messwerte verfälscht. In einem realen Projekt reicht es sicherlich, den Sensor einmal in der Minute abzufragen. Nach jeder Messung wird das Display aktualisiert.

Der Vorgabewert kann über die zwei Taster verändert werden. Dies ist mit zwei Event Listenern, die an die IO-Ports gebunden sind, realisiert. Sobald ein Taster gedrückt wurde, wird das Display aktualisiert. Das war auch schon das Programm für unser Dachfensterprojekt (Listing 6).

import com.pi4j.io.gpio.*;
import com.pi4j.io.gpio.event.*;
import com.pi4j.io.i2c.*;
public class OpenWindows {
  final static Pin dc = RaspiPin.GPIO_04;
  final static Pin rst = RaspiPin.GPIO_05;
  private static final int i2cBus = 1;
  private static final int address = 0x5c;
  static double value=22.0;
  static byte contrast = (byte)0xff;
  static boolean running=false;
  static double hum=0;
  static double temp=0;
  static PCD8544 pcd=null;
  public static void main(String[] args) throws Exception {
    final GpioController gpio = GpioFactory.getInstance();
    final GpioPinDigitalInput upButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_DOWN);
    final GpioPinDigitalInput downButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN);
    upButton.addListener(new GpioPinListenerDigital() {
      @Override
      public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
        if ((event.getState() == PinState.HIGH) && !running) {
          running = true;
          OpenWindows.value = OpenWindows.value + 1;
          System.out.println("Up Button : " + OpenWindows.value);
          OpenWindows.show();
          running = false;
        }
      }
    });
    downButton.addListener(new GpioPinListenerDigital() {
      @Override
      public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
        if ((event.getState() == PinState.HIGH) && !running) {
          running = true;
          OpenWindows.value = OpenWindows.value - 1;
          System.out.println("Down Button : " + OpenWindows.value);
          OpenWindows.show();
          running = false;
        }
      }
    });
    pcd = new PCD8544();
    pcd.LCDInit(dc, rst, (byte)contrast);
    byte[] wb = new byte[]{(byte) 0x03, (byte) 0x00, (byte) 0x04};
    byte[] rb = new byte[8];
    I2CBus bus = I2CFactory.getInstance(I2CBus.BUS_1);
    I2CDevice dev = bus.getDevice(address);
    while (true) {
      try {
        // wecken
        try {
          dev.read();
        } catch (Exception e) {
          Thread.sleep(100);
        };
        // messen
        dev.read(wb, 0, 3, rb, 0, 8);
        int crc = ((rb[6] & 0xff) << 8) | rb[7] & 0xff;
        hum = (((rb[2] & 0xff) << 8) | rb[3] & 0xff);
        temp = (((rb[4] & 0xff) << 8) | rb[5] & 0xff);
        hum = hum / 10;
        temp = temp / 10;
      } catch (Exception e) {//System.out.println(e); }
      show();
      if (temp>value){
        System.out.println("open");
        String[] cmd = {"/bin/bash","-c","echo 0=180 > /dev/servoblaster"  };
        Process p=Runtime.getRuntime().exec(cmd);
      }
      else {
        System.out.println("close");
        String[] cmd = {"/bin/bash","-c","echo 0=90 > /dev/servoblaster"  };
        Process p=Runtime.getRuntime().exec(cmd);
      }
      Thread.sleep(1000); 
    }//while
  }//main
  private static void show(){
    pcd.LCDclear();
    pcd.LCDdrawstring(0, 0, "Temp :" + temp);
    pcd.LCDdrawstring(0, 9, "Hum  :" + hum);
    pcd.LCDdrawstring(0, 17, "Value:" + value);
    System.out.println("Temp :" + temp);
    System.out.println("Hum  :" + hum);
    System.out.println("Value:" + value);
    pcd.LCDdisplay();
  }
}//class

Fazit

Dieses Projekt zeigt, was man alles aus unserem kleinen Freund – dem Raspberry Pi – herausholen kann. Das Programm beweist, dass man mit der Bibliothek Pi4J sehr elegant auf Hardware zugreifen kann. Wir haben uns alle wichtigen Teile der GPIO einmal angesehen und haben damit den Grundstein für eigene Experimente gelegt. An dieser Stelle sollte auch erwähnt werden, dass bei Raspberry-Projekten normalerweise nicht so viele manuelle Eingriffe und Patches nötig sind. Das Problem liegt darin begründet, dass viele Komponenten noch nicht richtig mit der leicht geänderten Hardware des Raspberry Pi 2 umgehen können; sowohl die Firmware als auch die Kernelversion spielen hier eine große Rolle. Der Servoblaster zum Beispiel lässt sich unter dem Pi 1 einfach installieren und läuft super. Um die SPI- und I2C-Treiber zu laden, ist normalerweise auch nicht so viel Aufwand nötig.

Ach, und falls sie sich gewundert haben, warum aus einem Java-Programm heraus Shell-Kommandos abgesetzt werden: Das liegt schlicht und einfach daran, dass die SoftPWM-Funktionen der Bibliothek Pi4J beim Raspberry Pi 2 nicht funktionieren. Obwohl die Hardwareunterstützung für den Pi Typ 2 etwas hakelig ist, wünsche ich ihnen viel Spaß bei eigenen Experimenten!


Im dritten Teil der Artikelserie starten wir ein erstes Projekt: den Bau eines Dachfenstersteuerung. Zunächst widmen wir uns der Programmierung benötigter Hardware wie Taster und Temperatursensor.

Entwickler Magazin

Entwickler Magazin abonnierenDieser Artikel ist im Entwickler Magazin erschienen.

Natürlich können Sie das Entwickler Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -