Mit dem Port Expander MCP23017, der neu in das Sortiment von AZ-Delivery aufgenommen wurde, stehen 16 zusätzliche GPIOs zur Verfügung. Es gibt aber auch einfache Tricks, wie man mehr Taster/Tasten abfragen kann bzw. mehr LEDs zum Leuchten bringt, als wir dafür GPIO-Pins belegen.
Den Anfang haben wir im Teil 1 mit den Keypads gemacht. Heute wollen wir die 7-Segment-Anzeigen betrachten, die ja je Ziffer aus 8 LEDs bestehen (8 wegen der 7 Segmente plus Dezimalpunkt). Für die Datums- und Uhrzeitanzeige benötigen wir eine vierstellige 7-Segment-Anzeige. Wenn man den gemeinsamen Anschluss für alle 8 LEDs mitzählt, benötigen wir also 4*9 = 36 Anschlüsse.
Tatsächlich gibt es Anzeigen mit 36 Beinchen, wie auf dem nächsten Bild zu sehen ist:
Dieses Display habe ich in dem Blog zum MCP23017 verwendet, der anlässlich der Neuaufnahme ins Sortiment erschien. Wie man sieht, viel Schaltungsaufwand, insbesondere wenn man noch einen Vorwiderstand (100 – 330 Ohm) vor jede LED schaltet.
Diese 7-Segment-Anzeigen gibt es in vielen Größen, Farben und Ausführungen, einige mit eingebauten Vorwiderstand, andere ohne. Einige funktionieren nach dem Prinzip der gemeinsamen Kathode (Common Cathode); dabei haben alle LEDS einen gemeinsamen GND-Anschluss. Zufälligerweise habe ich eines mit einer gemeinsamen Anode je Ziffer. Dann liegt der gemeinsame Anschluss je Ziffer an der Versorgungsspannung an. Das verwenden wir für einen interessanten Schaltungstrick bei der Ausführung mit 12 Beinchen:
Die Suche nach der Belegung der Beinchen beginnt im Internet und endet mit Ausprobieren.
Im Folgenden verwende ich die weitgehend standardisierte Bezeichnung der Segmente mit den Buchstaben A bis G sowie DP gemäß dem nächsten Bild.
Eine offizielle Bezeichnung der Beinchen habe ich im Datenblatt nicht gefunden. Deshalb habe ich einfach reihum durchgezählt: unten von links nach rechts 1 – 6 und oben von rechts nach links 7 – 12.
12 | 11 | 10 | 9 | 8 | 7 |
---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 |
Wie gesagt habe ich durch Ausprobieren herausbekommen, dass meine Anzeige vom Typ Gemeinsame Anode (Common Anode) ist und wie die einzelnen Beinchen belegt sind. Die Anode liegt für die erste Ziffer an Pin 12, für die zweite Ziffer an Pin 9, für die dritte Ziffer an Pin 8 und für die vierte Ziffer an Pin 6.
Der Schaltungstrick besteht nun zum einen darin, dass alle gleichen Segmente der vier Ziffern parallel geschaltet werden. Die folgende Tabelle zeigt die Belegung der 12 Beinchen:
Ziffer 1 | Seg A | Seg F | Ziffer 2 | Ziffer 3 | Seg B |
---|---|---|---|---|---|
12 | 11 | 10 | 9 | 8 | 7 |
1 | 2 | 3 | 4 | 5 | 6 |
Seg E | Seg D | DP | Seg C | Seg G | Ziffer 4 |
Die einzelnen Segmente leuchten also, wenn der Stromkreis über den Anschluss für die entsprechende Ziffer und den Anschluss für das jeweilige Segment geschlossen ist. Beispiel: Für die 1 als erster Ziffer müssen die GPIOs für die 1. Ziffer (Pin 12) auf HIGH und für die Segmente B und C (Pins 7 und 4) auf LOW geschaltet werden.
Um vier verschiedene Ziffern „gleichzeitig“ anzeigen zu können, kommt der andere Aspekt unseres Schaltungstricks zum Tragen, und der ist eine Kombination aus Programmiertechnik und Trägheit der LED und vor allem unserer Augen. Wir schalten die entsprechenden GPIOs für die vier Ziffern nacheinander so schnell, dass alle vier scheinbar „gleichzeitig“ leuchten. Wie beim Film oder Fernsehen, wo wir 24 bzw. 25 Bilder pro Sekunde nicht mehr als Einzelbilder, sondern als Film wahrnehmen.
Hierzu habe ich ein Python-Programm aus dem Internet für meine Zwecke modifiziert. Weitere Hinweise zum Urheber und eine Alternative für Displays mit gemeinsamer Kathode sind Teil des Programm-Codes.
#!/usr/bin/python
# Bertwert's code re-written for common anode 7-segment displays
# using BCM nomenclature instead of BOARD numbering
# numbering of the 4-digit 7-segment display:
# below the digits pins 1 to 6 from left to right
# above the digits pins 7 to 12 from right to left
# for common cathode 7-segments displays see Alex Eames version at
# https://raspi.tv
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# 7seg_segment_pins (11,7,4,2,1,10,5,3) + resistors (100 .. 330R)
segments = (23,16,20,27,17,24,21,22)
for segment in segments:
GPIO.setup(segment, GPIO.OUT)
GPIO.output(segment, 1)
# Common anodes for the four digits - pins (12,9,8,6)
digits = (6,13,19,26)
for digit in digits:
GPIO.setup(digit, GPIO.OUT)
GPIO.output(digit, 0)
# z = 0 # z and t introduced to get a clue
# t = time.time() # how often the loop is run
num = {' ':(1,1,1,1,1,1,1),
'0':(0,0,0,0,0,0,1),
'1':(1,0,0,1,1,1,1),
'2':(0,0,1,0,0,1,0),
'3':(0,0,0,0,1,1,0),
'4':(1,0,0,1,1,0,0),
'5':(0,1,0,0,1,0,0),
'6':(0,1,0,0,0,0,0),
'7':(0,0,0,1,1,1,1),
'8':(0,0,0,0,0,0,0),
'9':(0,0,0,0,1,0,0)}
try:
while True:
n = time.ctime()[11:13]+time.ctime()[14:16]
s = str(n).rjust(4)
for digit in range(4):
for loop in range(0,7):
GPIO.output(segments[loop], num[s[digit]][loop])
# z+=1
if (int(time.ctime()[18:19])%2 == 0) and (digit == 1):
GPIO.output(22, 0)
else:
GPIO.output(22, 1)
GPIO.output(digits[digit], 1)
time.sleep(0.001)
GPIO.output(digits[digit], 0)
except KeyboardInterrupt:
# print("z ",z, " in t = ",time.time()-t)
GPIO.cleanup()
print("... bye")
Die Pin-Belegung des Displays am Raspberry Pi sind in den Zeilen segments und digits zu entnehmen.
Anstelle eines Schaltplans hier ein Foto der Versuchsanordnung, bei dem man die Verkabelung gut sieht:
Gewöhnungsbedürftig war für mich insbesondere das Dictionary num, in dem die Zuordnung der Segmente zu den einzelnen Ziffern erfolgt, denn hier sehen wir die inverse Darstellung: bei 0 leuchten die jeweiligen Segmente.
Das Einschalten der LEDs erfolgt in den zwei verschachtelten for-Schleifen, die if-Abfrage sorgt für das Blinken des mittleren Dezimalpunktes.
Um eine Idee zu bekommen, wie häufig die Schleifen durchlaufen werden, habe ich die Zählvariable z und die Variable t für die Zeit eingefügt; hier sind diese Zeilen jedoch auskommentiert. Mein Raspi 3B hat die Schleifen rund 5000 Mal pro Sekunde ausgeführt.
Soweit der kleine Programmiertrick, um 36 verschiedene LEDs mit nur 12 Pins anzusteuern.
Beim Arduino hat uns Dean Reading schon den schwierigen Teil der Programmierung abgenommen und eine Programmbibliothek mit dem Namen SevSeg veröffentlicht. Der Sketch bleibt damit sehr übersichtlich. Allein die genaue Belegung der digitPins und segmentPins muss angepasst werden. Ich habe mich für die kürzesten Wege der Anschlusskabel entschieden (siehe Bild unter dem Sketch):
#include "SevSeg.h" // by Dean Reading
SevSeg sevseg;
void setup()
{
byte numDigits = 4;
byte digitPins[] = {7, 8, 9, 10};
byte segmentPins[] = {5, 13, 11, 3, 2, 6, 12, 4};
sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins);
}
void loop() {
sevseg.setNumber(1234,2);
sevseg.refreshDisplay();
sevseg.setBrightness(70);
}
Da ich keine Real Time Clock (RTC) am Arduino angeschlossen habe, werden nur die Zahlen 1234 mit zwei Nachkommastellen angezeigt.
Noch einfacher kann man es sich machen, wenn man ein fertiges Display-Modul mit einem speziellen IC auf der Rückseite der Anzeige und der dazu gehörigen Programm-Bibliothek für den Arduino oder Raspberry Pi verwendet. Dann benötigt man nur vier Anschlüsse: zwei für die Spannungsversorgung (meist 5 V und GND) sowie zwei für die Datenübermittlung.
Hierbei legen wir die wesentliche Leistung der Programmierung in die Hände von Profis, die uns fertige Programm-Bibliotheken an die Hand geben und damit von der Aufgabe des Multiplexing entbinden. Uns bleibt nur die Auswahl der richtigen Bibliothek, denn es gibt verschiedene Chips (ICs), die hier Verwendung finden.
Beginnen wir mit der vierstelligen 7-Segment-Anzeige im Sortiment von AZ-Delivery:
Hierin ist ein TM1637-Controller verbaut, der ein I²C-ähnliches Protokoll verwendet. Die beiden Datenleitungen werden jedoch beim Arduino nicht an die üblichen analogen Eingänge, sondern an zwei digitalen Eingängen angeschlossen. Alle wichtigen Informationen und insbesondere den Link zu den Programm-Bibliotheken finden Sie in der Rubrik „Wichtige Downloads & Links“ auf der Produktseite.
Die achtstellige 7-Segment-Anzeige im Sortiment von AZ-Delivery verwendet als Treiber-IC den Chip MAX7219. Dieser arbeitet mit dem SPI-Protokoll (Serial Peripheral Interface) und nutzt bei Arduino und Raspberry Pi die dafür vorgesehenen Anschlüsse. Da ja keine Daten vom Display zum Master gesendet werden, bleibt der Anschluss MISO unbelegt.
Auch hier finden Sie alle wichtigen Informationen und insbesondere den Link zu den Programm-Bibliotheken in der Rubrik „Wichtige Downloads & Links“ auf der Produktseite.
Das war unsere kleine Übersicht über die 7-Segment-Anzeigen mit Schwerpunkt auf dem Programmiertrick, um 32 LEDs mit nur 12 Anschlüssen individuell anzusteuern.
Auf vielfachen Wunsch geht es hier zum Download.