Winterprojekt: Setup Arduino-Programmierung

Der Arduino Uno ist eingetroffen. Nun kann es mit dem Winterprojekt weitergehen. Zuvor ist aber etwas Installationsaufwand zu treiben.

Für den Uno gibt es eine Entwicklungsumgebung, die weiterhin auch für andere Controller verwendbar ist. Auf der Homepage finden sich neben vielen Informationen und Anleitungen die Download-Seite mit dem Installer der IDE. Das ist die Abkürzung für integrierte Entwicklungsumgebung. Sie kann hier jeder passend zum jeweiligen Betriebssystem herunterladen.

Der Arduino unterhält sich technisch über eine serielle Schnittstelle, wie sie bei den ersten Mäusen benutzt wurde. Die gibt es heute aber an keinem Rechner mehr. Aber es gibt USB, den universellen seriellen Bus. Dafür bringt der Installer gleich einen passenden Treiber für die Kommunikation des Arduino mit dem Computer mit. Die USB-Geräte unterhalten sich auch seriell und deshalb sorgt der Treiber für eine Übersetzung zwischen den beiden seriellen Varianten.

Hinweis:
Bei einer Internetsuche können zwei Seiten gefunden werden: arduino.cc und arduino.org. Auch in die Welt der offenen Soft- und neuerdings auch Hardware sind die Menschen sich ebenfalls nicht immer einig. Das ist hier genauso. Ich bevorzuge die erste Adresse. Sie ist die ursprüngliche und ich vermute deshalb wirken mehr Menschen mit. Das lässt mehr Stabilität erwarten.

Aufbau

Steckt man ein neues USB-Gerät an einen Computer, dauert es immer einen Moment bis es erkannt wird. Die IDE muss den Arduino ebenfalls erkennen, folglich stecke ich ihn an den Rechner bevor ich die Umgebung starte.

Die Installation ist abgeschlossen. Der Uno ist mit dem Computer verbunden und anschliessend die IDE gestartet. Zeit das Zusammenspiel der beiden zu testen. Bei Programmiersprachen ist es üblich, zunächst ein “Hallo World” auszugeben. Klingt albern, zeigt aber deutlich: die Umgebung ist eingerichtet und funktioniert. Der Arduino hat keinen Bildschirm für eine Ausgabe, aber eine kleine Leuchtdiode auf der Platine. Das mitgelieferte Beispielsprogramm Blink läßt diese Diode blinken.

Arduino-IDE

Und da ist auch schon die erste Hürde. Der Arduino ist mit dem Rechner verbunden, bloß das die  Diode auf dem Board bereits zu blinken beginnt. Das heisst, der Hersteller verwendet dieses Programm offensichtlich für den Test des Aufbaus. Das stört aber nur bedingt. Das Blinken ist gleichmäßig und das Programm kann einen abweichenden Rhythmus vorgeben, so dass ein Unterschied zu erkennen ist.
Nun also erst mal die IDE starten. Im erscheinen Fenster ist ein Programmrumpf zu sehen. Darüber befinden sich Icons. Das Häkchen-Icon ganz Links überprüft die KorreStartfenster der IDEktheit eines Programmes. Es folgt das Icon, dass ein Programm auf das Board überträgt. Die folgenden dienen dem Öffnen, Speichern und beginnen neuer Programmdateien. Die IDE verrät die Funktion in einem Hilfetext, sobald der Mauszeiger über den Icon verweilt. Unter dem Programmcode-Fenster befindet sich die Konsole. Sie enthält die Ausgaben der Umgebung. Fortschritt beim Verarbeiten und Übertragen oder entdeckte Fehler im Code.

Beim öffnen eines neuen Programms – die Arduino IDE nennt dies Sketch – sind die Rümpe einer setup() und der loop()-Funktion zu erkennen. Für setup() gilt: der Name ist Programm. Hier können Variablen oder Hardware initialisieren werden. Die loop()-Funktion wird in einer Endlosschleife ausgeführt und enthält das, was der Controller verrichten soll.

Konfiguration

Bevor das Blink-Programm gestartet wird, ist die Entwicklungsumgebung noch zu konfigurierten. Im Menü “Werkzeuge” stelle ich unter “Platine” den “Arduino/Genunio Uno” ein. Unter Port ist die serielle Schnittstelle auszuwählen, die der Treiber zur für die Kommunikation mit dem Board bereitstellt. Bei meinem Mac heisst sie “/dev/usbmodem411” auf Windows erscheint ein “COM” gefolgt von einer Nummer. Im Idealfall weisst die IDE darauf hin, dass mit Port ein Board verbunden ist.

Blinkprogramm aktivieren

Das Test-Programm, “Blink”, ist eins von mehren mitgelieferten Beispielen. Es ist wie im Bild gezeigtPfad zum Blinkprogramm im Datei-Menü zu finden. Die Beispiele liefern Vorlagen für die verschiedenen Themen, in denen sich angehende Bastler zu unterschiedlichen Themen orientieren können.

Alldieweil ist das Testprogramm Blink geöffnet. An Pin 13 ist die Leitdiode (LED) auf dem Board angeschlossen. Deshalb definiert die setup()-Funktion diesen Pin als Ausgang. In loop() wird nun

  1. die LED eingeschaltet,
  2. eine Sekunde gewartet,
  3. die LED ausgeschaltet,
  4. wieder eine Sekunde gewartet
  5. und das ganze beginnt von vorn.

Damit eine die Wirkung des Programmes zu sehen ist, verändere ich das An-/Aus-Verhältnis der LED zu

void loop() {
  digitalWrite(13, HIGH);
  delay(200); // warte nur kurz
  digitalWrite(13, LOW);
  delay(800); // pausiere deutlich länger
}

Noch einem Klick auf das Hochladen-Icon, anschliessend sind in der Konsole die IDE-Aktivitäten zu verfolgen: Übersetzen und Packen des Programmes und die folgende Übertragung. Sobald sie startet, ist ein “Flimmern” zweier Kontrolle-LEDs auf dem Board zu erkennen. Anschließend blinkt die Diode auf dem Board nicht mehr gleichmäßig, sondern blitzt entsprechend kurz auf.

Ein Programm wurde übertragen, anschliessend wird es ausgeführt und die LED blitzt.

Winterprojekt: selbstgebaute Digitaluhr

Wie wäre es mit einer gelbgebauten Digitaluhr? Die Segelsaison ist zu Ende. Es folgt die Jahreszeit der kurzen Tage. Nach einem herrlichen Absegeln darf feuchtes und kaltes Wetter gerne draußen bleiben. Drinnen kann ich mich nun mit anderen Dingen beschäftigen.
Segelboot im Oktober

Computer und Programmieren sind mein Beruf. Sie sind aber auch mein Hobby, wobei es nicht immer wilde virtuellen Welten sein müssen. Also zurück zu den Nullen und Einsen. Der Bau einer einfachen Digitaluhr wäre eine schöne Reminiszenz an meinen Einstieg in die Computerwelt,

Der Ursprung

Meine ersten Erfahrungen mit Computern, habe ich als junger Teen gemacht. Für 50 DM! erstand ich einen Sinclair ZX81. Der hatte immerhin 2 KB (in Worten: zwei Kilobyte) RAM-Speicher. Die Busleitungen der 8-Bit-CPU waren am Erweiterungsport verfügbar. Zwei statische Speicherchips mit ein paar Logikgatter und schon hatte dieser Computer ganze 16KB. Um das zu vergegenwärtigen : mein Handy hat einen Speicher von 16 GB. Das ist tausendmal mehr. Dabei ist es bereits drei Jahre alt.

Mit ein den “Peek”- und “Poke”-Befehlen aus dem Betriebs-Basic-Sprachsatz konnte mit ZX81 auch mal was angesteuert werden. Mit Steckboard oder Lochrasterplatinen und ein wenig Löten hatte ich einfach mal eine Experiment aufgebaut.Basismaterial für eine Digitaluhr

Der Spaß kehrt zurück

Kleine Computer für hardwarenahe Experimente gibt es wieder: die Mikrocontroller. Diese Chips vereinen alle Komponenten eines Computers und mehr auf einem Chip. Dieser benötigt nur noch eine Stromversorgung und los geht’s. Sie sind preiswert und steuern heute so mache Spül- oder Waschmaschine.

Für die Programmierung ist allerdings eine Programmierumgebung erforderlich und ein Programmer, der ein Programm auf den Chip transferiert. Das klingt nach mehr Zeit und Geld als man für kleine Experimente ausgeben mag.

Dieses Problem gab es auch mal ein einer italienischen Universität. Für Steuerungsaufgaben sollten Mikrocontroller eingesetzt werden. Die Studenten hatten allerdings keine Erfahrung mit Elektronik oder Programmierung.

Deshalb ersonnen kluge Köpfe eine standardisierte Umgebung, den Arduino und seine Entwicklungsumgebung. Der Arduino ist ein kleines Board mit Mikrocontroller, USB-Schnittstelle und Pfostenleisten. Die Pfostenleisten sind mit den die Mikrocontroller-Ein- und Ausgängen verknüpft. Über Sie ist die Außenwelt einfach und schnell mit dem Mikrocontroller verbunden. Dabei können diese Input-/Output-Verbindungen digitale und analoge Signale ausgeben und einlesen, wie es ein Programm vorgibt. Die Baupläne des Board und die Entwicklungsumgebung sind frei und kostenlos verfügbar. Diverse Hersteller vertreiben fertige Boards.

Über einen normalen USB-Anschluß ist der Arduino mit einem Computer verbunden. Die Entwicklungsumgebung überträgt darüber die Programme zum Arduino. Mit der Entwicklungsumgebung, die das Programmieren des Arduino wirklich kinderleicht macht, können Profis schnell Prototypen entwickeln. Oder aber Hobbyisten ein wenig experimentieren. Genau das habe ich vor.

Das Ziel – die selbstgebaute Digitaluhr

Der Arduino soll meine Basis für meine einfache Digitaluhr werden.

Im Hinterkopf habe ich ein Wecker. Die Uhr zeigt die Zeit an, ich muss sie stellen können und vielleicht bekommt sie auch eine Weckfunktion. Einige Besonderheiten möchte ich dabei schon haben. Die Ziffernanzeige soll blau sein. Das Standard-Rot gibt es ständig bei Anzeigen. Außerdem soll sie eine Spezialität meines derzeitigen Weckers haben: die Zeit soll beim stellen auch zurückdrehbar sein.

Der typische Wecker hat zwei Knöpfe für langsamen und schnellen Vorlauf. Beide drücken setzt die Uhr auf 0 Uhr. Meinem aktueller Wecker hat sowohl einen Vor- als auch einen Rücklauf. Um 23 Uhr ins Bett gehen und noch gerade den Wecker auf Winterzeit eine Stunde zurückdrehen? Mit dem Rücklauf ist das ganz einfach. Wie oft habe ich vorher neu ansetzen müssen, weil ich nicht zeitig genug von schnellen auf langsamen Vorlauf gewechselt bin?

Vielleicht wird mein Eigenbau meinen Wecker nicht ersetzen, aber eine Digitaluhr mit blauer Anzeige…. blau macht doch glücklich 😉

Tutorial – JavaFX Custom Dialog

JavaFX enthält ab Version 8 auch Dialogklassen. Dazu gehören die vorgefertigten Standarddialoge Alert (Warnung), TextInputDialog (Texteingabe) und ChoiceDialog (Auswahl). Über deren Verwendung ist im Internet auch einiges zu finden. Das Erstellen eigener Dialoge wird dagegen kaum beschrieben. Am Beispiel eines Login-Dialogs soll dieser Blog das ändern. Der Beispielcode erstellt die Dialogoberfläche einmal programmatisch und einmal per FXML. Der Beispielcode ist auf Github  zu finden.

Das Basisvorgehen in JavaFX

Für eigene Dialoge bietet sich ein Blick auf die Struktur der vorgefertigten Dialoge an

Klassenstruktur der Dialoge
Klassenstruktur der Java FX Dialoge und der darstellenden DialogPane

Am einfachsten leitet sich der eigene Dialog – wie bei den vorhandenen Dialogen – von der Klasse javafx.scene.control.Dialog<R> ab. <R> ist der Rückgabetyp. Für die Darstellung der Oberfläche inklusive der Buttons ist die DialogPane-Eigenschaft des eigenen Dialogs zu setzen oder zu bestücken. Abschließend benötigt der eigene Dialog noch einen Konverter, um die relvanten Daten aus den Eingabefeldern in ein Rückgabeobjekt zu transferieren.

Der Aufruf einer eigenen Dialogklasse ist dann z.B.

CodedLoginDialog codedDialog = new CodedLoginDialog();
Optional result = codedDialog.showAndWait();
result.ifPresent(login -> System.out.println(login));

Bei Abbruch des Dialogs enthält das Optional keinen Wert, die Ausgabe findet entsprechend nicht statt. Die Javadoc zur Dialog-Klasse zeigt weitere Aufrufvarianten.

Erstellen der Dialogoberfläche

DieDialogPaneeines Dialogs bestimmt das Aussehen.

Dialoglayout
Standardlayout der DialogPane

Das wichtigste dürfte der Content sein. Im Bild ist ihm eine Grid mit Labeln und Eingabefeldern eines Logins zugewiesen.

Diverse optionale Ergänzungen sind möglich:

  • Zusätzlich zum Titel des Dialogs ist noch ein Headertext möglich.
  • Ein Bild/Icon (graphic-Eigenschaft) ist im Bild nicht dargestellt. Dessen Position hängt vom Headertext ab. Ist ein Headertext angegeben, erscheint ein Bild rechts vom Headertext, andernfalls links vom Content.
  • Ein expandierbarer Content sorgt wie im Bild für einen Button, der auf Anforderung den Inhalt des expandable Contents anzeigt.

Programmatische Oberfläche

In der eigenen Dialogklasse ist der Content der DialogPane zu befüllen

this.grid = new GridPane();
...

final DialogPane dialogPane = getDialogPane();
dialogPane.setContent(grid);

...

FXML-Oberfläche

Seit der Version 8 des SceneBuilder bietet dieser die Möglichkeit eine DialogPane grafisch zu erstellen und als FXML-File zu speichern.

Mit Hilfe des FXMLLoader erhält eigenen Dialog die gewünsche DialogPane:

DialogPane dialogPane =
    (DialogPane)FXMLLoader.load(
        getClass().getResource("/fxml/DialogPane.fxml"));

...

setDialogPane(dialogPane);

Buttons ergänzen

Die Buttons eines Dialoges speichert die DialogPane in der Eigenschaft Buttontypes. Es gibt diverse vordefinierte Buttons, die der Buttontype-Collection hinzugefügt werden können. Im Beispiel enthält der Dialog einen Abbruch und einen Ok-Button:

dialogPane.getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK);

Obwohl in der DialogPane verborgen, sind die vordefinierten Button im Nachgang noch anpassbar, z.B. der Text des Ok-Buttons

Button okButton = (Button)dialogPane.lookupButton(ButtonType.OK);
    okButton.setText("Login");

Der Konverter

Nach dem Ok soll der Dialog nun auch die Eingaben verpackt in der Ergebnisklasse zurück liefern. Das ist Aufgabe des Konverters, der in eigenen Klassen entsprechend zu definieren ist

setResultConverter((dialogButton) -> {
    ButtonData data =
        dialogButton == null ? null : dialogButton.getButtonData();
    return data == ButtonData.OK_DONE
        ? new Login(usernameField.getText(), passwordField.getText())
        : null;
});

Ist im Beispiel der Dialog mit dem Ok-Button beendet worden, so legt das Lambda einen neues Ergebnisobjekt an und übergibt dem Konstruktur die Daten aus den Eingabefeldern.

Für die Konvertierung benötigt das Lambda referenzen auf die Eingabefelder. Bei der programmatischen Erstellung der Oberfläche sind diese schnell als Attribute der neuen Dialog-Klasse deklariert. Anders verhält es sich, wenn die Oberfläche per FXMLLoader erstellt ist. In diesem Fall muss die Dialogklasse die Referenzen im FXML-Objektbaum suchen. Die gewünschten Elemente können im FXML per Id gekennzeichnet werden

<TextField fx:id="usernameField"...

um anschließend nach dem Laden im Elementbaum der DialogPane gesucht zu werden

final TextField usernameField =
   (TextField)dialogPane.lookup("#usernameField");

Validierung

Die Eingaben eines Dialogs sollten natürlich nur weiter gegeben werden, wenn sie sinnvoll sind. Über Data-Binding könnten nun Hinweise, Markierungen, etc. in den Content eingeblendet werden. Aber auch der Ok-Button sollte nur bei vollständigen Eingaben überhaupt aktiv sein. In Beispiel muss mindestens ein User angegeben sein, bevor ein Login möglich ist.

Zuvor wurde der Text des Ok-Buttons angepasst. Aber auch die übrigen Buttoneigenschaften sind ansprechbar

okButton.setDisable(true);
usernameField.textProperty().addListener(
            (event, oldValue, newValue)
                -> okButton.setDisable(newValue.trim().isEmpty()));

Fazit

Solange das vorgegebene Layout der für die eigenen Zwecke ausreicht, sind eigene Dialoge seit Java 8 recht einfach zu erstellen.

Begegnung mit dem Kaufomat

In einem Supermarkt entdeckte ich jüngst eine Selbstbedienungskasse. Da nicht viel los war, konnte ich mich mit dieser Gerätschaft in aller Ruhe befassen. Der Kauf einer einzelnen Milchtüte kann schließlich nicht so kompliziert sein – dachte ich.

Auf in den Kampf: auf der Oberfläche des Kaufomaten prangt ein Start-Knopf. Langeweile soll aber auch nicht aufkommen, es gibt noch einen zweiten. Ja, ich möchte meine eigene Tasche verwenden. Das heißt, eigentlich möchte ich keine eigene Tasche verwenden, den ein Tetra Pak kann ich gerade so noch tragen. Allerdings möchte ich mir keine Tragetasche von einem Automaten aufschwatzen lassen, also wähle ich „ich habe eine eigene Tasche“. Nun ist zu lesen, ich möge meine Tasche auf die dafür vorgesehene Ablage legen. Ok, mangels Tasche lass ich das jetzt doch mal.

Das „Start“ prangt immer noch auf dem Touchscreen, also versuche ich es als nächstes mit Anfangen. Was nun folgt, ist dann doch nicht mehr überraschend und geht recht zügig von der Hand. Ich möchte die Waren scannen.  „Piep“ und das war es auch schon. Noch der Maschinen sagen, das es ans Zahlen geht und auf in die nächste Fragerunde: Wie möchte ich bezahlen? Bar zahlen zu können, find ich etwas überraschend. Da ich die Karte ohnehin schon in der Hand habe, bleibt es dabei.

„Sie benutzen eine eigene Tasche“. Da ist es. Diese Maschine hat mich durchschaut. Das Silikon hat es gemerkt. Wozu auch immer, der Sinn der Taschenfragen erschloss sich mir nicht wirklich.

Ein bisschen erinnert mich das an ein von mir gesehenes Video, in dem ein Onlinekauf beschrieben ist. Dargestellt mit einer gewöhnliche Kasse und Kassierer.

Kassierer : „Bitte geben Sie Ihren Kundennummer an.“
Der Käufer – verunsichert – nennt eine Zahlenkolonne.
Kassierer : „Diese Kundennummer ist uns nicht bekannt. bitte wiederholen sie die Eingabe, …“

Schon mal im Internet bestellt? Die Idee ist klar und das Ergebnis des Films auch: der Käufer sucht irgendwann entnervt und ohne Einkäufe das Weite.

Was also soll ich von diesen Kaufomaten halten? Wenn alle Kassen voll sind, ist er eine zusätzliche Kasse, ok. Aber – wie ich finde – nur für wenige Teile. Bei einem Großeinkauf ausladen, scannen und dann wieder verpacken…. das geht dann mit der Unterstützung eines Menschen doch besser. Und – ist der Laden mal nicht voll – ist mir ein Schwatz mit dem Menschen allemal lieber (c: