Counter ICs

Über den Beitrag

Counter ICs sind Bauteile, die an einem Eingang, der meist Clock oder Clock Input genannt wird, Wechsel des Logiklevels detektieren und in Abhängigkeit der Anzahl dieser Ereignisse eine bestimmte Ausgabe erzeugen. Ausgabe heißt hier einfach nur, dass bestimmte Ausgänge LOW oder HIGH geschaltet werden, was man dann entsprechen auswerten kann. Im Bereich der Arduino und Raspberry Pi Bastler liest man relativ wenig über die Teile, wahrscheinlich weil man das meiste auch ohne sie über digitalRead Befehle o.ä. realisieren kann. Die Counter haben aber den Vorteil, dass sie im Hintergrund vor sich hinzählen können während der Sketch ggf. mit anderen Dingen beschäftigt ist. Auch gibt es Situationen, in denen man vielleicht nicht sofort auf jedes Einzelereignis reagieren möchte, sondern nur auf jedes x-te.

In dem Beitrag gehe ich auf drei verschiedene Counter ein, nämlich:

  • den IC 4040 – ein 12-Bit Counter, der bis 212 – 1 zählt
  • den IC 4017 – ein 10-Bit Counter, der bis 9 zählt
  • den IC 4033 – ein spezieller Counter zum Ansteuern von 7-Segmentanzeigen

Bei den ersten beiden Vertretern der Counter ICs werde ich neben der Zählfunktion auch zeigen wie man sie zur Quasi-Porterweiterung bzw. zum Quasi-Multiplexen nutzen kann. 

Der IC 4040

Es gibt diese Counter ICs von verschiedenen Herstellern als DIP16 mit unterschiedlichen Bezeichnungen wie CD4040BE, HCF4040BEY oder 74HC4040. Ich verwende hier deswegen die allgemeine Bezeichnung IC 4040. Man bekommt den IC 4040 für 30-70 Cent in Elektronikshops. Ein Datenblatt gibt es z.B. hier. Empfohlen wird eine Versorgungsspannung zwischen 3 und 20 Volt. Der maximale Ausgangsstrom liegt bei 25 mA, also ausreichend um LEDs zu betreiben. 

Pinout

Pinout des Counter ICs 4040
Pinout des IC 4040

Die Funktion ist denkbar einfach. Ein Wechsel an CP (Clock Input) von HIGH nach LOW erhöht den Zähler um 1. Ein HIGH Signal an MR löst einen Reset aus und der Zähler geht wieder auf Null. In Abhängigkeit des Zählerstandes werden die Ausgänge Q0 bis Q11 wie folgt geschaltet: 

Ausgänge des IC 4040 in Abhängigkeit vom Zähler; 0 = LOW, 1 = HIGH
Ausgänge des IC 4040 in Abhängigkeit vom Zähler; 0 = LOW, 1 = HIGH

IC 4040 mit Taster hochzählen

Zum „Kennenlernen“ stelle ich hier erstmal eine einfache Schaltung vor, bei der der Zähler per Taster hochgezählt wird. Durch die vielen LED Anschlüsse ist die Schaltung etwas unübersichtlich, aber eigentlich ist sie ganz einfach. Über Taster an den Arduino Pins 7 und 8 werden die Signale fürs Hochzählen bzw. den Reset eingelesen. Die Pins 12 und 13 sind mit CP bzw. MR verbunden. 

Schaltung für das Hochzählen des Counter ICs 4040 per Taster
Hochzählen des Counter ICs 4040 per Taster

Der Sketch dazu muss wohl nicht groß erklärt werden. Die delay(300); Anweisungen dienen der Tasterentprellung. Viel Spaß dann beim Hochzählen bis 4095…

int countTasterPin=7;
int resetTasterPin=8;
int resetPin=12;
int clockInput=13;


void setup() {
  pinMode(countTasterPin, INPUT);
  pinMode(resetTasterPin,INPUT);
  pinMode(resetPin,OUTPUT);
  pinMode(clockInput, OUTPUT);
}

void loop() {
  if(digitalRead(resetTasterPin)){
    digitalWrite(resetPin, HIGH);
    digitalWrite(resetPin, LOW);
    delay(300);
  }
  if(digitalRead(countTasterPin)){
    digitalWrite(clockInput,HIGH);
    digitalWrite(clockInput,LOW);
    delay(300);
  }
}

 

IC 4040 per Sketch hochzählen

Wenn man die Taster weglässt und den Zähler per Sketch vorgibt, sieht es zum Beispiel so aus:

int clockInput=12;
int resetPin=13;

void setup() {
  pinMode(resetPin,OUTPUT);
  pinMode(clockInput, OUTPUT);
  Serial.begin(9600);
  digitalWrite(resetPin,HIGH);
  digitalWrite(resetPin,LOW);
  delay(1000);
  for(int i=0; i<42; i++){
    digitalWrite(clockInput, HIGH);
    digitalWrite(clockInput, LOW);
  }
  delay(2000);
  digitalWrite(resetPin,HIGH);
  digitalWrite(resetPin,LOW);
  delay(1000);
  for(int i=0; i<2835; i++){
    digitalWrite(clockInput, HIGH);
    digitalWrite(clockInput, LOW);
  }
}

void loop() {
}

 

IC 4040 zur Porterweiterung einsetzen

Man kann den IC 4040 auch zur Porterweiterung benutzen. Ich habe das mal an einem ESP8266 ESP-01 Modul ausprobiert. „Richtige“ Porterweiterungen hatte ich hier beschrieben. Aber wieso „richtig“? Ist das denn hier falsch? Da man beim Hochzählen keine Zahl auslassen kann, gehen natürlich auch Ausgänge, die man eigentlich auf LOW haben möchte immer wieder kurz an und wieder aus. Bei den recht trägen LEDs fällt das nicht so ins Gewicht, bei anderen Anwendungen unter Umständen schon. Insofern würde ich diese Methode hier als „Quasi-Porterweiterung“ bezeichnen. 

Schaltung für die Porterweiterung am ESP-01

Schaltung für die Portwerweiterung am ESP-01 mit Hilfe des Counter ICs 4040
Schaltung für die Portwerweiterung am ESP-01 durch den IC 4040
Schöner Kabelsalat - IC 4040 als Porterweiterung am ESP-01
Schöner Kabelsalat – IC 4040 als Porterweiterung am ESP-01

GPIO0 und GPIO2 des ESP-01 Moduls werden als Clock Input bzw. Resetgeber eingesetzt. Wie man ein ESP-01 Modul programmiert, habe ich hier beschrieben. Der Rest ist nicht neu. 

Sketch zur Porterweiterung am ESP-01

Auch dieser Sketch ist nicht sonderlich komplex. Es werden die LEDs 0 bis 11 definiert. Ihr Status ist in der Variable „ledStatus“ gespeichert. Die Funktion „switchLED“ verändert den Status entsprechend den übergebenen Parametern. Dann wird ein Reset durchgeführt und bis zum Wert von ledStatus hochgezählt. 

Beim Schalten der oberen LEDs sieht man dann doch ein kurzes Leuchten der unteren LEDs. Beim Einschalten der LED 11 geht die LED 0 ja immerhin 1024 mal an und wieder aus. Diesen unerwünschten, kurzen Leuchteffekt kann man nochmal deutlich mindern, indem man anstelle der langsamen digitalWrite() Befehle direkt auf die Ports des ESP-01 zugreift. Das funktioniert etwas anders als an den Arduino Ports: GPOS = (1 << 0); schaltet GPIO0 HIGH, GPOC = (1<<0); schaltet GPIO0 LOW. Probiert es einfach mal aus. 

#define LED0 0
#define LED1 1
#define LED2 2
#define LED3 3
#define LED4 4
#define LED5 5
#define LED6 6
#define LED7 7
#define LED8 8
#define LED9 9
#define LED10 10
#define LED11 11
int clockInput=0;
int resetPin=2;
word ledStatus = 0;

void setup() {
  pinMode(resetPin,OUTPUT);
  pinMode(clockInput, OUTPUT);
  reset4040();
  delay(1000);

  for(int i=0; i<=11; i++){
    switchLED(i,1);
    delay(200);
  }
  delay(1000);
  for(int i=11; i>=0; i--){
    switchLED(i,0);
    delay(200);
  }
  delay(1000);
  switchLED(LED0,1);
  delay(1000);
  switchLED(LED11,1);
  delay(1000);
  switchLED(LED4,1);
  delay(1000);
  switchLED(LED5,1);
  delay(1000);
  switchLED(LED0,0);
  delay(1000); 
  switchLED(LED11,0);
  delay(1000);
  switchLED(LED4,0);
  switchLED(LED5,0);
}

void loop() {
  switchLED(LED11,1);
  delay(1000);
  switchLED(LED11,0);
  delay(500);
}

void reset4040(){
  digitalWrite(resetPin,HIGH);
  digitalWrite(resetPin,LOW);
}

void switchLED(word num, bool ledon){
  if(ledon){
    ledStatus |= (1<<num);
  }
  else{
    ledStatus &= ~(1<<num);
  }
  reset4040();
  for(int i=0; i<ledStatus; i++){
    //digitalWrite(clockInput, HIGH);
    //digitalWrite(clockInput, LOW);
    GPOS = (1 << 0);
    GPOC = (1 << 0);
  }
}
   

 

Der IC 4017

Der nächste Vertreter der Counter ICs, den ich hier vorstellen möchte ist der IC 4017. Auch diesen gibt es als DIP16 mit unterschiedlichen Bezeichnungen. Ich habe hier einen CD4017BE von Texas Instruments eingesetzt. Der empfohlene Bereich für die Spannungsversorgung liegt zwischen 3 und 18 Volt. Ein Datenblatt gibt es zum Beispiel hier

Der große Unterschied zum IC 4040 liegt darin, dass es sich bei dem IC 4017 um einen Dekadenzähler handelt, der von Null bis Neun zählt. Von seinen 10 Ausgangspins ist immer nur ein einziger HIGH:

Ausgänge des IC 4017 in Abhängigkeit vom Zähler; 0 = LOW, 1 = HIGH

Ausgänge des IC 4017 in Abhängigkeit vom Zähler; 0 = LOW, 1 = HIGH

Erwähnenswert ist auch, dass der Ausgang 0 im Ausgangszustand HIGH ist. Das muss so sein, denn der IC 4017 ist dafür ausgelegt, dass man mehrere davon hintereinanderschalten kann um dann bis 100, 1000, 10000, usw. zählen zu können. Würde nach der 9 keine 0 kommen, so könnte man keine 10 darstellen. 

Schließlich sei noch erwähnt, dass beim IC 4017 der Wechsel von LOW nach HIGH an CP den Zähler inkrementiert. 

Pinout

Pinout des Counter ICs 4017
Pinout des IC 4017

Der IC 4017 hat neben den Ausgangspins 0 bis 9 und der Spannungsversorgung folgende Anschlüsse:

  • MR: Resetpin, high-aktiv
  • CP: Clock Input
  • CE: Clock Enable, low-aktiv
  • TC: Carry Through

TC kann an den Clock Pin eines weiteren IC 4017 angeschlossen werden. Wird im ersten IC 4017 der Zähler 9 überschritten gibt es ein Signal an den folgenden IC 4017 und im ersten IC 4017 geht der Ausgang 0 auf HIGH. 

Den IC 4017 zum Multiplexing einsetzen

Neben der eigentlichen Aufgabe, dem Zählen, kann man den IC 4017 auch zum Multiplexing einsetzen. Hier gilt wie beim IC 4040 natürlich auch wieder die Einschränkung, dass man beim Hochzählen auch die Ausgänge kurz einschaltet, die man eigentlich auf LOW haben will. Hier geht allerdings, sofern man nicht mehrere IC 4017 hintereinanderschaltet, jeder Ausgang auf dem Wege zum „Zielausgang“ nur einziges Mal kurz an und wieder aus, was bei Ansteuerung von LEDs nicht sichtbar ist.

Schaltung zum Multiplexing am ESP-01

Der Schaltplan ist einfach: 

  • GPIO0 und GPIO2 steuern den Clock Input und den Reset
  • CE liegt an GND
  • TC ist nicht verbunden, da hier nur ein einzelner IC 4017 verwendet wird
  • Den Ausgang 0 habe ich für diesen Zweck nicht verbunden, da er ja schon beim Einschalten HIGH ist.

Man könnte auf den Gedanken kommen dann eben TC als zehnten Ausgang zu nehmen – der ist allerdings auch beim Start HIGH, geht bei Zähler 6 auf LOW und dann nach der 9 wieder HIGH. 

 

Counter ICs im Einsatz - der IC 4017 am ESP-01

Der Sketch zum Multiplexing am ESP-01

Der Sketch sollte selbsterklärend sein:

#define LED1 1
#define LED2 2
#define LED3 3
#define LED4 4
#define LED5 5
#define LED6 6
#define LED7 7
#define LED8 8
#define LED9 9

int clockInput=0;
int resetPin=2;
word ledStatus = 0;

void setup() {
  pinMode(resetPin,OUTPUT);
  pinMode(clockInput, OUTPUT);
  reset4017();
  delay(2000);

  for(int i=1; i<=9; i++){
    digitalWrite(clockInput, HIGH);
    digitalWrite(clockInput, LOW);
    delay(1000);
  }
  delay(1000);
  switchOnLED(LED1);
  delay(1000);
  switchOnLED(LED3);
  delay(1000);
  switchOnLED(LED5);
  delay(1000);
  switchOnLED(LED7);
  delay(1000);
  switchOnLED(LED9);
  delay(1000);
}

void loop() {
}

void reset4017(){
  digitalWrite(resetPin,HIGH);
  digitalWrite(resetPin,LOW);
}

void switchOnLED(byte num){
  reset4017();
  for(byte i=0; i<num; i++){
    digitalWrite(clockInput, HIGH);
    digitalWrite(clockInput, LOW);
  }
}

 

Der IC 4033

Und nun zum letzten Vertreter der Counter ICs, den ich hier vorstellen möchte, dem IC 4033. Auch er ist von verschiedenen Herstellern mit unterschiedlichen Bezeichnungen erhältlich, aber alle DIP16 Varianten, die ich mir angeschaut habe, besitzen denselben Pinout. Für diesen Beitrag habe ich den CD4033BE verwendet. Ein Datenblatt gibt es zum Beispiel hier. Der empfohlene Spannungsbereich liegt zwischen 3 und 18 Volt. Der IC 4033 unterscheidet sich nochmal grundsätzlich von den anderen Counter ICs 4017 und 4040, da er speziell für die Ansteuerung von 7-Segmentanzeigen konzipiert wurde. Der IC 4033 zählt dekadisch und der Zählerstand wird automatisch durch Aktivierung der entsprechenden Ausgänge a – g (siehe Schema) auf einem 7-Segmentdisplay als Ziffer dargestellt. 

7-Segmentschema
7-Segmentschema

Pinout

Pinout des Counter ICs 4033
Pinout des IC 4033

Der IC 4033 hat die folgenden Ein-/Ausgänge:

  • VSS / VDD: Spannungsversorgung
  • Clock: Eingang für die Zählsignale
  • Clock Inhibit: high-aktive Sperrung der Zählfunktion
  • a bis g: Ausgänge für die einzelnen Segmente (siehe Schema)
  • Reset: high-aktiver Reset
  • Carry Out: wird mit Clock des Zählers der nächsthöheren Dezimalstelle verbunden
  • Lamp Test: mit HIGH verbunden wird der Zählerstand ignoriert und alle Ausgänge a bis g gehen HIGH
  • Ripple Blanking In (RBI) / Ripple Blanking Out (RBO): damit wird gesteuert, ob redundante Nullen angezeigt werden oder nicht.

Der letzte Punkt bedarf noch einer Erklärung. Hat man beispielsweise sechs 7-Segmentdisplays und stellt eine „5607“ dar, bekommt man ohne weitere Vorkehrungen die Anzeige „005607“. Um die voranstehenden Nullen loszuwerden, verbindet man RBI des IC 4033 an der höchsten Ziffer (most significant digit), also hier die Hunderttausender Stelle mit LOW. RBO dieses IC 4033 wird mit dem RBI des IC 4033 der nächstniedrigeren Stelle, also hier den Zehntausendern, verbunden. RBO dieses IC 4033 wird dann mit dem RBI der nächstniedrigeren Stelle verbunden, usw.. Bei dieser Konfiguration bleibt bei der Darstellung der Zahl 0 auch das Display der Einser Stelle dunkel. Wenn man das verhindern möchte, hört man mit der Kaskadierung bei den Zehnern auf und verbindet RBI des IC 4033 für die Einser mit HIGH.

Zur Unterdrückung redundanter Nullen für die Stellen hinter dem Komma bei Kommazahlen verfährt man im Prinzip genauso, nur dass man mit der Prozedur an der geringwertigsten Stelle (least significant digit) beginnt. 

Entsprechend dem Zählerstand werden die Ausgänge so aktiviert, dass automatisch die richtige Zahl angezeigt wird. Das ist ebenso einfach wie bequem. Da die aktivierten Ausgänge „HIGH“ sind, nimmt man 7-Segmentdisplays mit gemeinsamer Kathode. 

Beispielschaltung für zwei 7-Segmentanzeigen

Als Beispiel zeige ich hier einen Schaltplan für zwei 7-Segmentanzeigen, die mit einem Arduino über den IC 4033 angesteuert werden. Dabei habe ich SC39-11GWA Displays von Kingbright verwendet. Damit es nicht zu unübersichtlich wird, habe ich jeweils nur eine Segmentleitung („d“) eingezeichnet. Auf dem Foto weiter unten seht ihr den Aufbau mit drei 7-Segmentdisplays.

  • Arduino Pin 9 wird mit dem Clock Eingang des für die Einser zuständigen IC 4033 verbunden
  • Arduino Pin 8 gibt das Resetsignal und wird mit Reset aller IC 4033 verbunden
  • Lamp Test kommt an GND
  • Clock Inhibit kommt an GND
  • Für diesem einfachen Fall kommt RBI des IC 4033 für die Einser an HIGH und RBI des anderen IC 4033 an LOW. 

Aber wo sind die Widerstände in den Leitungen zu den 7-Segmentdisplays? Der IC 4033 liefert nur eine begrenzte Menge Strom – es war nicht notwendig noch Widerstände einzubauen. Ob ihr welche braucht oder nicht hängt von eurer Versorgungsspannung und den verwendeten 7-Segmentdisplays ab. 

Schaltung von zwei 7-Segmentanzeigen mit zwei IC 4033
Schaltung von zwei 7-Segmentanzeigen mit zwei IC 4033
Schaltung von drei 7-Segmentanzeigen am IC 4033
Schaltung von drei 7-Segmentanzeigen mit IC 4033 – es wird schnell unübersichtlich

Ein Beispielsketch

Mit diesem einfachen Sketch wird die Anzeige von 0 bis 99 hochgezählt. Die Funktion displayNumber(), die ich hier aber nicht nutze, zeigt eine bestimmte Zahl an. 

 

int resetPin=8;
int clockInput=9;

void setup() {
  pinMode(resetPin,OUTPUT);
  pinMode(clockInput, OUTPUT);
  reset4033();
  delay(2000);
}

void loop() {
  for(int i=1; i<=99; i++){
    digitalWrite(clockInput, HIGH);
    digitalWrite(clockInput, LOW);
    delay(500);
  }
  reset4033();
  delay(2000);
}

void reset4033(){
  digitalWrite(resetPin,HIGH);
  digitalWrite(resetPin,LOW);
}

void displayNumber(byte num){
  reset4033();
  for(byte i=0; i<num; i++){
    digitalWrite(clockInput, HIGH);
    digitalWrite(clockInput, LOW);
  }
}

 

4 thoughts on “Counter ICs

  1. Hallo Wolfgang.
    Erst mal ein frohes und gesundes neue Jahr 2023,
    Dein Artikel über Counter ICs ist zwar schon etwas älter aber trotz dem für mich sehr interessant. Bringt mich auf einige Ideen für meine nächsten Projekte. Vielen Dank dafür. Wie immer gut beschrieben und kompetent erklärt.
    Ein Fehler hat sich eingeschlichen. In der ersten Fritzing Zeichnung vom 4040 hast du das IC zweimal mit Masse versorgt. Der Plus liegt auch an Masse. Halb so schlimm.
    Für das kommende Jahr wünsche ich dir alles Gute und mach genau so weiter.
    Veit

    1. Hallo Veit, vielen Dank. Ich bin immer froh, wenn Fehler gemeldet werden, selbst wenn es ein offensichtlicher ist. Habe es gleich geändert. Schönes Restjahr noch! 😉
      VG, Wolfgang

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert