Binärumrechner mit Arduino und I2C-LCDisplay - [Teil 1]

Teil 1 

Hallo liebe Bastler!

In den folgenden Beiträgen möchte ich Ihnen zeigen, wie wir einen 8-Bit-Binärkonverter aus einem Arduino Mikrocontroller, einem LCDisplay mit I2C-Adapter und einigen Schaltern umsetzen können. Wir werden damit Binärcodes in Hexadezimal- und Dezimalzahlen umrechnen.

Im ersten Teil gebe ich Ihnen einfache Tipps zum Umrechnen vom binären in das hexadezimale sowie dezimale Zahlensystem. Ich zeige Ihnen, wie man ein 20x4 LCDisplay mit nur zwei (respektive vier) Leitungen ansteuern kann. Dafür erkläre ich auch kurz die I2C-Schnittstelle. Außerdem laden wir die ersten Beispielprogramme für das Display auf den Arduino.

Im zweiten Teil zeige ich Ihnen, wie der Quellcode für unser Programm aussieht. Wir nutzen die Bitmanipulation sowie Portmanipulation. Das hilft uns, wenn wir alle Schalter gleichzeitig auslesen möchten. Dafür benötigen wir auch ein wenig boolesche Algebra, die ich ebenfalls kurz erläutern werde. Außerdem erzeugen wir eigene Symbole, die wir auf dem Display anzeigen können. Es ist äußerlich kein großes Projekt.

Daher werde ich mehr ins Detail gehen, um denen von Ihnen zu helfen, die noch nicht sicher im Umgang mit Arduino-Programmierung sind. Los geht’s.

Binärumrechnung

Zu Beginn möchte ich noch einmal auf die Theorie der Umrechnung zwischen binär, dezimal und hexadezimal eingehen. Das ist eigentlich sehr leicht. Binär hat zwei Wertigkeiten, 0 und 1. Dezimal zählt von 0 bis 9. Für jede Zehnerstelle wird eine 1 vorangestellt und dann wird wieder von 0 bis 9 gezählt. Das hexadezimale System zählt von 0 bis 15, wobei die Zahlen 10 bis 15 durch Buchstaben ersetzt werden. Wir nutzen 8 Bit und geben jedem Bit von rechts nach links eine Wertigkeit, die sich von 1 beginnend immer verdoppelt.

Wertigkeit 128 64 32 16 8 4 2 1


Geben wir nun jedem Bit noch die Möglichkeit, den Zustand 1 oder 0 einzunehmen.
 

Wertigkeit 128 64 32 16 8 4 2 1
Zustand 0 0 0 0 0 0 0 0


Als Nächstes stellen wir uns die Zustände als Schalter vor. Wir addieren die Wertigkeiten in der oberen Zeile zusammen. Aber nur die Werte, die in der unteren Zeile 'eingeschaltet' wurden.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 28
Zustand 0 0 0 1 1 1 0 0


Damit erhalten wir aus der binären Zahl 0001 1100 die dezimale Zahl 28. Man kann natürlich auch von dezimal in binär umrechnen. Nehmen wir an, wir möchten dezimal 7 in binär umrechnen. Wir schauen in die Tabelle von links nach rechts, ob die Wertigkeit in unsere Zahl passt. Immer dort, wo es nicht passt, setzen wir den Zustand auf 0.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 7
Zustand 0 0 0 0 0

In diesem Fall ist die 4 die erste Wertigkeit, die in unsere 7 passt. Also setzen wir deren Zustand auf 1. Wir müssen nun 4 von 7 abziehen, da 4 Wertigkeiten verbraucht wurden.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 3
Zustand 0 0 0 0 0 1

Die weiteren Wertigkeiten passen ebenfalls in unsere Zwischensummen. Somit werden sie auch auf 1 gesetzt.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 0
Zustand 0 0 0 0 0 1 1 1

Bleibt von unserer Dezimalzahl nichts mehr übrig, sind wir fertig und lesen nur noch die Binärzahl ab: 0000 0111.

Hinweis: Sind alle acht Zustände auf 1 gesetzt und man addiert die Wertigkeiten, erhält man die Zahl 255. Man kann also mit 8 Bit Werte von 0 bis 255 abbilden.

Hinweis: Binärzahlen mit einer 1 an der niedrigsten Stelle (hier rechts) sind ungerade Zahlen.

Nun möchten wir nicht nur zwischen binär und dezimal umrechnen, sondern das Ergebnis auch in hexadezimal angezeigt bekommen. Das Zahlensystem rechnet von 0 bis 15. Also 16 Werte. Allerdings werden die Werte 10 bis 15 mit Buchstaben dargestellt.

Dezimalwert 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hexadezimalwert 0 1 2 3 4 5 6 7 8 9 A B C D E F

Kleine Eselsbrücken: 12 (Cwölf, auch wenn es falsch geschrieben ist), 13 (Dreizehn) und 15 (Fünfzehn).

Um nun von binär in hexadezimal umzurechnen, zerteilt man die 8 Bit in jeweils 4 Bit. 8 Bit sind 1 Byte. Zwei mal 4 Bit sind zwei Halbbytes oder auch 'Nibbles' genannt. In der ursprünglichen Tabelle ersetzen wir die Wertigkeiten 128, 64, 32 und 16 durch 8, 4, 2, 1. 

Wertigkeit 128 64 32 16 8 4 2 1
Nibblewertigkeit 8 4 2 1 8 4 2 1
Zustand 0 0 0 0 0 0 0 0


Das Beispiel für die Binärzahl von vorher nutzen wir hier auch noch einmal.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 28
Nibblewertigkeit 8 4 2 1 8 4 2 1 1 | 12
Zustand 0 0 0 1 1 1 0 0

In der zweiten Zeile werden die Wertigkeiten für beide Seiten getrennt addiert, abhängig von den 'Schaltern' in der untersten Zeile. Das ergibt für die linke Seite 1 und für die rechte Seite 12. Da im hexadezimalen System Werte ab 10 durch Buchstaben ersetzt wer- den, entspricht die 12 dem Buchstaben C. Unser Ergebnis ist also 1C (hex).

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 28
Nibblewertigkeit 8 4 2 1 8 4 2 1 1 || 12
Zustand 0 0 0 1 1 1 0 0
Hex-Wert 1 C


Hinweis:
 An den zweistelligen hexadezimalen Zahlen erkennt man sofort, dass es sich um 8 Bit handelt.

Möchte man nun von hexadezimal in binär oder dezimal umrechnen, ist das der gleiche Vorgang wie weiter oben schon beschrieben. Man teilt die beiden hexadezimalen Werte auf und übernimmt sie in die letzte gezeigte Tabelle. Wir probieren das mit der Zahl AF (hex). 

Summe:
Wertigkeit 128 64 32 16 8 4 2 1
Nibblewertigkeit 8 4 2 1 8 4 2 1
Zustand
Hex-Wert A (10) F (15)

Man prüft dann die Wertigkeiten der Nibbles aus Zeile zwei von links nach rechts, ob die Werte dort hineinpassen. Wenn ja, setzt man eine 1 und zieht die Wertigkeit ab. Ist von den ursprünglichen beiden Zahlen nichts mehr übrig, hat man seine Binärzahl erhalten.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1
Nibblewertigkeit 8 4 2 1 8 4 2 1
Zustand 1 1
Hex-Wert 2 7


Als Letztes addiert man die Wertigkeiten der ersten Zeile abhängig von den Zuständen  und erhält das dezimale Ergebnis.

Summe:
Wertigkeit 128 64 32 16 8 4 2 1 175
Nibblewertigkeit 8 4 2 1 8 4 2 1
Zustand 1 0 1 0 1 1 1 1
Hex-Wert 0 0


Das Ergebnis aus AF(HEX) ist also 10101111(BIN) oder 175(DEZ).

Benötigte Hardware

Kommen wir nun zum praktischen Teil. Natürlich brauchen wir Hardware. Dazu gehören:

Anzahl Bauteil Anmerkung
PC mit der Arduino IDE und Internetverbindung
1 Steckbrett
1 Arduino Uno 3
1 8 Schalter (hier in Form von Dipswitches)
1 20x4 Liquid Chrystal Display (LCD)
1 I2C-Adapter für LCDs
1 Verbindungskabel

Schaltplan

Hier sehen Sie schon einmal den Schaltplan für unser Projekt:

    Abbildung 1: Schaltplan

    Was ist I2C?

    Da wir im nächsten Abschnitt die I2C (I squared C, also I quadrat C) -Schnittstelle verwenden, möchte ich darauf noch kurz eingehen. Was ist das eigentlich? Es handelt sich dabei um ein serielles Datenbussystem, dessen Vorteil ist es, mehrere Geräte miteinander zu verbinden und sie in diesem 'Netzwerk' zu adressieren. Dadurch sind nur zwei Datenleitungen notwendig.

    Es basiert auf dem Master-Slave-Prinzip. Der Master initiiert den Datenaustausch, der oder die Slaves sprechen darauf an. Im Idealfall haben die einzelnen Geräte zwei Eingänge (SDA und SCL) sowie zwei Ausgänge (ebenfalls SDA und SCL).  So können sie in einer Kette hintereinander angeschlossen werden. Der Master nutzt dann die Geräteadressen, um jedes einzelne Gerät anzusprechen. Nachteil hierbei ist allerdings, dass die Kabellängen sehr eingeschränkt sind. Man kann damit keine meterlangen Strecken überwinden.

    Display ansteuern

    Damit wir eine Ausgabe erhalten, schließen wir zuerst das Display an. Mit dem I2C- Adapter ist es möglich, mit nur zwei Leitungen (Daten und Takt) sowie Spannungsversorgung (5V und Masse) das Display in Betrieb zu nehmen. Man spart sich die aufwendige Verkabelung, die sonst notwendig ist.

    Allerdings kann es sein, dass man den Lötkolben zur Hand nehmen muss. Der Adapter passt wie ein Shield auf die Rückseite des Displays. Beim Anbringen muss man darauf achten, dass die vier Anschlüsse GND, VCC, SDA und SCL auf der von vorn gesehen linken Seite zeigen. So wie es auch in Abbildung 1 zu sehen ist. Abbildung 2 zeigt die Rückseite mit dem montierten Adapter (auch Backpack genannt).

    Abbildung 2: I2C Backpack

    Die Anschlüsse SDA und SCL liegen beim Arduino Uno auf den Pins A4 (SDA) und A5 (SCL). Nutzt man andere Boards, muss man eventuell das Datenblatt hinzuziehen. Es ist möglich, dass es dann eine andere Pinbelegung gibt.
    Wir schließen nun also das Display an den Arduino an und testen zuerst, ob wir ein 'Bild' erhalten.

    Dafür starten wir die Arduino IDE und installieren zuerst die Bibliothek
    liquid_- chrystal_i2c. Wir öffnen den Bibliotheksverwalter unter dem Menüpunkt 'Werkzeuge'. Dort geben wir in die Suche den Namen der Bibliothek ein und suchen in der Liste nach dem passenden Eintrag. Wählt man ihn aus, kann man auf installieren klicken. Anschließend steht die Bibliothek zur Verfügung.

     Abbildung 3: Bibliotheksverwalter

    Wählt man nun aus dem Menü Datei die Beispiele und scrollt nach unten, findet man den Eintrag für diese Bibliothek und kann die mitgelieferten Beispiele laden. Wir öffnen das Projekt HelloWorld und laden es auf den Arduino hoch. Man kann sich dann auch gleich ein wenig mit der Umgangsweise des Displays vertraut machen. Dazu später mehr.

    Wir brauchen nun noch 8 Schalter, die unsere 8 Bit repräsentieren. Im Grunde sind Bits nichts anderes als logische Schalter. Daher passt das hier ganz gut.

    Um ein wenig Platz zu sparen, verwende ich Dipswitches. Man kann natürlich auch acht separate Schalter jeder beliebigen Form verwenden. Im Schaltplan sind es acht Dips. Mehr benötigen wir nicht. Wir nutzen die digitalen Pins 0 bis 7 des Arduino und schließen dort jeweils die eine Seite der Schalter an. Die anderen werden an die Masse angeschlossen (Pull-up- Widerstände schalten wir per Software hinzu).

    Es ist auch darauf zu achten, dass wir später die Bits von rechts nach links 'lesen'. Also sollte auch der Schalter rechts außen an Pin 0 des Arduino angeschlossen werden. Dann von rechts nach links die restlichen Pins.

    Tipp: Wenn die Pins 0 (RX) und 1 (TX) verwendet werden, können beim Upload auf den Arduino Probleme auftreten. Auch der serielle Monitor ist dadurch beeinträchtigt. Man könnte auf andere Pins ausweichen. Ich möchte aber die Portmanipulation nutzen und bleibe daher auf den Pins 0 bis 7, die alle auf dem Port D liegen.
    Zum Hochladen ziehe ich die beiden Pins einfach kurz ab und stecke sie später wieder drauf. Den seriellen Monitor nutzen wir nicht.

    Ein weiteres Codebeispiel für das Display ist das Projekt CustomChars. Dort wird gezeigt,wie man eigene Symbole erzeugt. Jedes Feld des Displays besteht aus 5x8 kleinen Pixeln. Unter folgendem Link:
    https://i.stack.imgur.com/1TKZH.gif  
    findet man eine Übersicht, bei der alle Zeichen aufgeführt sind, die im Speicher des Displays zur Verfügung stehen. Man kann die ersten 8 Speicherplätze selbst füllen. Dafür erzeugt man ein Array, in dem für jede Zelle eines Feldes eine 1 oder 0 geschrieben wird. Man kann es auch in hexadezimaler Form umsetzen.

    Dadurch wird der Quellcode kleiner, aber nicht unbedingt lesbarer.
    In Binärform kann man die Symbole unter Umständen auch direkt erkennen. Unter diesem Link:
    https://maxpromer.github.io/LCD-Character-Creator/
    kann man eigene Symbole erzeugen und den automatisch generierten Quellcode in sein Projekt kopieren. Wir werden uns später einen Kreis, ein Schaltersymbol für 'aus' und ein weiteres Schaltersymbol für 'an' generieren.

    Vorschau

    Sie haben nun einen Einblick in die Umrechnung zwischen Zahlensystemen erhalten. Außerdem können wir ein LCDisplay mit dem I2C-Backpack sehr einfach mit dem Arduino ansteuern und eigene Zeichen ausgeben. Im zweiten Teil zeige ich Ihnen, wie wir den Quellcode umsetzen.

    Wir nutzen Port- und Pinmanipulation. Außerdem erstellen wir uns eine Binär-Dezimal-Hexadezimal-Tabelle auf dem Display. Wir nutzen ein wenig boolesche Algebra, um Bitmasken zu verrechnen.

    Einen Kommentar hinterlassen

    Alle Kommentare werden vor der Veröffentlichung moderiert