Typische 7-Segment-Anzeigen bestehen aus sieben LEDs (meist plus einer weiteren für den Dezimalpunkt), die einzeln angesteuert werden und über eine gemeinsame Anode (common anode) oder Kathode (common cathode) verfügen. Um eine Anzeige zu steuern, werden also sieben (bzw. acht) Digitalpins des Mikrocontrollers belegt. Bei Verwendung einer einzelnen Anzeige ist das noch halbwegs praktikabel, bei mehreren nicht mehr. Zum Bereitstellen zusätzlicher Ausgabeports kann man Schieberegister wie das 74HC595 nutzen. Hierbei werden die Steuerdaten bitweise seriell zum Schieberegister übertragen, das diese dann auf Anforderung an einem Stück (parallel) auf acht Datenpins ausgibt. Man kommt für die Ansteuerung des 74HC595 mit drei Leitungen aus, selbst wenn man mehrere Register hintereinander schaltet, um z.B. zwei 7-Segment-Anzeigen oder eine Gruppe von Relais zu steuern.
7-Segment-Anzeige SMA42056
Ich verwende im folgenden zwei Anzeigen vom Typ SMA42056 mit gemeinsamer Kathode (Datenblatt). Wie der Name vermuten lässt, sind die beiden Kathoden-Pins miteinander verbunden – es genügt also, einen der beiden mit Masse zu verbinden. Wie Standard-LEDs werden auch diese Displays nicht direkt, sondern nur über einen passenden Vorwiderstand angeschlossen. Dessen Berechnung erfolgt unten.
Die Segmente bzw. LEDs werden mit den Buchstaben A bis G bezeichnet, die wie folgt den Pins zugeordnet sind:

Pin | Segment |
---|---|
1 | E |
2 | D |
3 | gemeinsame Kathode |
4 | C |
5 | Dezimalpunkt (DP; decimal point) |
6 | B |
7 | A |
8 | gemeinsame Kathode |
9 | F |
10 | G |
Schieberegister 74HC595

Das 74HC595 (Hersteller: Texas Instruments; vollständige Bezeichnung: SN74HC595N; Datenblatt) besteht aus zwei Registern: einem Schieberegister zur bitweisen seriellen Dateneingabe und einem Speicher- oder Ausgaberegister. Durch ein Steuersignal werden die acht Daten-Bits aus dem Schieberegister ins Speicherregister übernommen und parallel an den acht Pins QA bis QH ausgegeben. Die Steuerung erfolgt über die Pins SER (serielle Daten), SRCLK (Takt für das Schieberegister; shift register clock) und RCLK (Takt für das Speicherregister; (storage) register clock). SRCLR (Reset des Schieberegisters; shift register clear) wird mit VCC verbunden, OE (output enable) mit Masse. Um mehrere Register hintereinander zu schalten, wird der Ausgang QH’ (Pin 9) des ersten mit dem Eingang SER des folgenden Registers verbunden. (Eine ausführliche Beschreibung der Funktionsweise des 74HC595 kann man bei mikrocontroller.net nachlesen.)
Berechnung des Vorwiderstands für die LEDs
Die Ausgabepins des 74HC595 können zusammen maximal einen Strom von 70 mA liefern (jeder einzelne max. 35 mA) – pro LED also 10 mA (8,75 mA bei Verwendung des Dezimalpunkts). Der Vorwiderstand muss die Differenzspannung zwischen Durchlassspannung der LED (VF = 1,8 V) und Versorgungsspannung (VCC = 3,3 V) von der LED abhalten. Sein Wert errechnet sich nach dem Ohmschen Gesetz als
R = U / I = (VCC – VF) / I = (3,3 V – 1,8 V) / 8,75 mA = (1,5 / 0,00875) Ω = 171 Ω.
Als nächsthöhere passende Widerstandsgröße ergibt sich also ein Wert von 200 oder 220 Ω (bei einer Betriebsspannung von 5 V sind es 366 Ω, also nimmt man einen 470 Ω-Widerstand). Statt selbst zu rechnen, kann man auch einen Online-Rechner wie den LED-Vorwiderstandsrechner auf elektronik-kompendium.de verwenden; dort gibt es auch eine ausführliche Erläuterung.
Die Durchlassspannung wird auch als Flussspannung bezeichnet; meist findet man den Wert unter dem englischen Begriff forward voltage im Datenblatt der LED.
Materialliste
- ESP32
- Breadbord (groß, 830 Kontakte; alternativ zwei kleine mit je 400 Kontakten)
- 2 7-Segment-Anzeigen SMA42056 (common cathode)
- 2 Schieberegister 74HC595
- 2 Widerstände 200 oder 220 Ω
- 1 Temperatursensor DS18B20
- 1 Widerstand 4,7 KΩ
- ca. 40 Kabel und/oder Steckbrücken
Die einfache Variante (die ich gewählt habe) ist, je eine der gemeinsamen Kathoden der Anzeigen über den Vorwiderstand mit Masse zu verbinden. Je nach Anzahl leuchtender Segmente leuchtet die Anzeige dann aber mit leicht unterschiedlicher Lichtstärke. Für mich ist das kaum sichtbar, aber falls es stört, verbindet man die Kathode direkt mit Masse und setzt in jede Steuerleitung zu den LEDs einen Vorwiderstand ein; statt zwei werden also 14 bzw. 16 (mit Dezimalpunkt) Widerstände benötigt.
Schaltung
Um etwas zum Anzeigen zu haben, verwende ich Messwerte des Temperatursensors DS18B20, den ich in einem anderen Beitrag vorgestellt habe. (Wer sich diesen Teil der Schaltung sparen möchte, zählt stattdessen z.B. in einer Schleife Zahlenwerte von 0-99 hoch.) Im Programm gebe ich auch eine Nachkommastelle der Temperatur aus und nutze deshalb den Dezimalpunkt der linken Anzeige. Werden nur ganzzahlige Werte dargestellt, muss man die entsprechenden Segmente der Displays nicht verbinden.

Im Diagramm verwende ich rote Leitungen für Verbindungen mit der Versorgungsspannung und schwarze für Masse. Die Leitungen innerhalb der beiden Gruppen aus Schieberegister und 7-Segment-Anzeige sind jeweils nach dem gleichen Muster eingefärbt, z.B. QA zu Pin 7 gelb, QB zu Pin 6 blau usw. Man sieht schon am Fritzing-Diagramm, dass es auf dem Breadboard mit so vielen Kabeln etwas unübersichtlich wird. Im realen Aufbau wird das noch deutlicher. Zum Ausprobieren und Lernen ist das ok, bequemer in der Nutzung von 7-Segment-Anzeigen sind fertige Module z.B. mit dem TM1637 (vierstellige Displays für Zeitanzeigen u.ä.) oder MAX7219 (acht Stellen mit Dezimalpunkten). Auch Module mit zwei LEDs und zwei Schieberegistern (also genau wie im hier aufgebauten Beispiel) sind für weniger als 4 € bei chinesischen Versendern erhältlich. Nützlicher dürften die Schieberegister bei anderen Einsatzzwecken sein, die mehr digitale Ausgabepins erfordern als am ESP32 verfügbar sind.
Programmierung
Besondere Bibliotheken müssen für die 7-Segment-Anzeige nicht installiert werden. Für die Abfrage des Temperatursensors DS18B20 müssen die Bibliotheken OneWire und DallasTemperature vorhanden sein.
Die Zeichen, die auf einer 7-Segment-Anzeige darstellbar sind, sind als achtstellige Bitfolgen codiert – Segment A als niederwertigstes Bit (20), Segment B als zweitniedrigstes (21) bis zu Segment G (26) und dem Dezimalpunkt (27). Im Programm sind diverse darstellbare Zeichen angegeben – wenn man nur die Hexadezimalziffern 0-9 und A-F braucht, kann man den Rest auskommentieren. Einen Dezimalpunkt nach einem Zeichen erhält man, indem in der Bitfolge das höchstwertige Bit durch eine ODER-Verknüpfung mit dem Wert 0x80 (27 = 128) gesetzt wird.
Beim Schieben der Daten in das Register wird zuerst das rechts stehende Zeichen ausgegeben, dann das linke. Nach jedem Bit wird der serielle Takt (Leitung SRCLK) kurz auf HIGH und dann auf LOW gesetzt, um die Daten im Register (und Register übergreifend) eine Stelle weiterzuschieben und das neue Bit zu übernehmen. Sind die Daten übertragen, werden sie durch HIGH-Setzen des Speichertakts (RCLK) ausgegeben.
Je nach gemessener Temperatur werden folgende Daten angezeigt:
- – –: kein Sensor gefunden
- Lo: Temperatur unter 0 °C
- Hi: Temperatur über 100 °C
- einstellige Temperaturen werden mit einer Nachkommastelle ausgegeben
- bei zweistelligen Temperaturen werden eine Sekunde lang die Vorkommastellen (Zehner und Einer) angezeigt, dann eine Sekunde lang die Einer mit einer Nachkommastelle
/* Anzeige von Zahlenwerten auf zwei 7-Segment-Anzeigen vom Typ SMA42056 * unter Verwendung von Schieberegistern 74HC595 * * 2019-05-26 Heiko (unsinnsbasis.de) */ // Einbinden der benötigten Bibliotheken für den Sensor DS18B20 #include <OneWire.h> #include <DallasTemperature.h> // GPIO-Pin für DS18B20 #define GPIO_PIN 23 // Steuerpins für Schieberegister SN74HC595 #define SER_PIN 18 // GPIO-Pin für serielle Daten #define RCLK_PIN 19 // GPIO-Pin: storage register clock #define SRCLK_PIN 21 // GPIO-Pin: shift register clock // OneWire-Objekt erstellen ... OneWire ow(GPIO_PIN); // ... und einen Zeiger darauf an ein Sensor-Objekt übergeben DallasTemperature ds_sensor(&ow); DeviceAddress addr; // ID des Sensors // Kodierung der Zeichendarstellung auf dem 7-Segment-Display byte seven_seg_code[30] = // G F E D C B A // HEX digits 0-9, A-F { 0x3f, // 0 1 1 1 1 1 1 - 0 0x06, // 0 0 0 0 1 1 0 - 1 0x5b, // 1 0 1 1 0 1 1 - 2 0x4f, // 1 0 0 1 1 1 1 - 3 0x66, // 1 1 0 0 1 1 0 - 4 0x6d, // 1 1 0 1 1 0 1 - 5 0x7d, // 1 1 1 1 1 0 1 - 6 0x07, // 0 0 0 0 1 1 1 - 7 0x7f, // 1 1 1 1 1 1 1 - 8 0x6f, // 1 1 0 1 1 1 1 - 9 0x77, // 1 1 1 0 1 1 1 - A 0x7c, // 1 1 1 1 1 0 0 - b 0x39, // 0 1 1 1 0 0 1 - C 0x5e, // 1 0 1 1 1 1 0 - d 0x79, // 1 1 1 1 0 0 1 - E 0x71, // 1 1 1 0 0 0 1 - F 0x80 // decimal point /* uncomment if needed */ , // 13 additional characters // for words like: Lo, Hi, PUSH (PU5H), PULL, UP... 0x38, // 0 1 1 1 0 0 0 - c 0x76, // 1 1 1 0 1 1 0 - H 0x74, // 1 1 1 0 1 0 0 - h 0x04, // 0 0 0 0 1 0 0 - i 0x0e, // 0 0 0 1 1 1 0 - J 0x38, // 0 1 1 1 0 0 0 - L 0x5c, // 1 0 1 1 1 0 0 - o 0x73, // 1 1 1 0 0 1 1 - P 0x67, // 1 1 0 0 1 1 1 - q 0x50, // 1 0 1 0 0 0 0 - r 0x3e, // 0 1 1 1 1 1 0 - U 0x1c, // 0 0 1 1 1 0 0 - u 0x40 // 1 0 0 0 0 0 0 - minus sign /* */ }; // 1 Byte bitweise an das Schieberegister ausgeben // nach der Übertragung jedes Bits SRCLK kurz auf HIGH setzen, // dann auf LOW void shift_to_74hc595(byte data) { int i; // Datenbyte bitweise ausgeben (höchstes Bit zuerst) for(i=0; i<8; i++) { digitalWrite(SER_PIN, 0x80 & (data << i)); digitalWrite(SRCLK_PIN, HIGH); delay(1); digitalWrite(SRCLK_PIN, LOW); } } // Anzeigen aktualisieren // die Zeichen werden nacheinander von rechts nach links(!) ausgeben // - rechtes Zeichen rausschieben // - linkes Zeichen rausschieben // - Taktung kurz auf HIGH, dann auf LOW void display_2_digits(byte left, byte right) { shift_to_74hc595(right); shift_to_74hc595(left); digitalWrite(RCLK_PIN, HIGH); delay(1); digitalWrite(RCLK_PIN, LOW); } void setup(void) { Serial.begin(115200); ds_sensor.begin(); // Sensor initialisieren pinMode(RCLK_PIN, OUTPUT); pinMode(SRCLK_PIN, OUTPUT); pinMode(SER_PIN, OUTPUT); // Anzeigen initialisieren: alles aus digitalWrite(SRCLK_PIN, LOW); digitalWrite(RCLK_PIN, LOW); display_2_digits(0x00, 0x00); Serial.println("Setup done"); } void loop(void) { byte i; float temp; // ROM-Adresse des Sensors auf dem OneWire-Bus ermitteln if (!ow.search(addr)) { Serial.println("-- Kein Sensor gefunden --"); // Text "--" anzeigen display_2_digits(seven_seg_code[29], seven_seg_code[29]); } else { // Abfrage der Temperatur starten ds_sensor.requestTemperatures(); temp = ds_sensor.getTempC(addr); Serial.print("Temperatur: "); Serial.print(temp, 1); // eine Nachkommastelle Serial.println(" °C"); ow.reset_search(); // OneWire-Suche zurücksetzen if (temp < 0.0) { // Text "Lo" display_2_digits(seven_seg_code[22], seven_seg_code[23]); delay(2000); } else if (temp >= 100.0) { // Text "Hi" display_2_digits(seven_seg_code[18], seven_seg_code[20]); delay(2000); } else if (temp < 10.0) { // bei einstelligen Temperaturen Wert mit Dezimalkomma und // einer Nachkommastelle anzeigen display_2_digits(seven_seg_code[((int)temp % 10)] | 0x80, // gerundete Nachkommastelle seven_seg_code[(int)(round(temp * 10)) % 10]); delay(2000); } else { // bei zweistelligen Werten eine Sekunde lang die // Vorkommastellen anzeigen (Zehner und Einer) ... display_2_digits(seven_seg_code[(int)(temp / 10)], seven_seg_code[(int)temp % 10]); delay(1000); // ... dann Einer mit Dezimalkomma und eine Nachkommastelle display_2_digits(seven_seg_code[((int)temp % 10)] | 0x80, seven_seg_code[(int)(round(temp * 10)) % 10]); delay(1000); } } }
Datenblätter


Themenverwandte Beiträge
Wie der HC-SR501 sind auch der HC-SR505, der AM312 und der SR602 pyroelektrische Infrarotsensoren (a...
Mehrstellige 7-Segment-Anzeigen direkt per Schieberegister zum Anzeigen von Daten zu nutzen, bedeute...
Durch einen Artikel im Heise Newsticker bin ich auf den Longan Nano der chinesischen Firma Sipeed ge...
LittleFS ist ein Dateisystem für den Flash-Speicher verschiedener Mikrocontroller. Auf den ESP-Contr...
Hallo,
ich habe die Schaltung aufgebaut, Programm geladen bekomme aber nur 8.8. angezeigt (alle LED an). Hast Du eine Ahnung woran kann das liegen?
Danke
Hallo Thomas,
ich habe die Schaltung nun auch noch einmal aufgebaut, und sie funktioniert wie vorgesehen.
Überprüfe am besten noch einmal alle Kabel bzw. Steckverbindungen, insbes. + und – (3,3 V und Masse).
Bei meinen Breadboards gibt es verschiedene Varianten, was die Belegung der Stromschienen angeht: bei den meisten Boards ist sie wie im Fritzing-Diagramm zu sehen, also Masse (blau) in den Stromschienen oben, die Versorgungsspannung (rot, 3,3 Volt vom ESP32) jeweils in der unteren Reihe. Ich habe aber auch Breadboards, bei denen die Reihen genau andersherum angeordnet sind.
Mit Masse müssen die Pins unten in der Mitte der 7-Segment-Anzeigen verbunden sein (über einen Widerstand von 200 oder 220 Ohm) und an den 74HC595 jeweils oben die vierten Pins von links und unten die Pins ganz rechts. Spannung liegt an den 74HC595 in der oberen Reihe am ersten und vorletzten Pin. Die 7-Segment-Anzeigen haben keine direkte Masse-Verbindung.
Die 74HC595 sind so im Breadboard eingesetzt, dass die Kerbe auf der Oberseite des Chips nach links zeigt.
Die 7-Segment-Anzeigen SMA42056, die ich hier verwende, besitzen eine gemeinsamer Kathode (engl. common cathode) – es gibt aber auch (nicht ganz so gebräuchlich) welche mit gemeinsamer Anode (common anode). Bitte prüfe, welchen Typ du verwendest – meist ist die Angabe auf dem Gehäuse aufgedruckt – und suche dir per Suchmaschine das zugehörige Datenblatt. Eine englischsprachige Anleitung für Anzeigen mit gemeinsamer Anode gibt es z.B. auf https://www.instructables.com/Arduino-common-anode-7-segment-display/.
Ich hoffe, die Hinweise helfen weiter,
Heiko
Hallo Heiko,
danke für Deine Hinweise. ich habe alle Leitungen nochmal gesteckt (unter Spannung) die einzelnen LED Balken leuchten auf wenn ich die Leitungen stecke. Am Ende leuchten alle LED. Am seriellen Monitor wird die Temp. angezeigt, also die Datenerfassung klappt schonmal.