Drei Schieberegister nacheinander.

Hallo und guten Morgen

Suche Hilfe zu Schieberegister 74HC595. Ich habe einen alten Sketch für die fortlaufende Anzeige bis 255 in binärform und also acht Leuchtdioden ausgegraben.
Nun wollte ich alles erweitern auf 32 Dioden und vier Shiftregister. Nur komme ich nicht über die Hürde von 16 Dioden. Der Zähler läuft wohl weiter (Kontrolle mit Serial.print) aber die Anzeige der Dioden fängt von vorne an.
Nachfolgend mein Sketch.

//Pin verbunden mit SH_CP (11) des 74HC595
int shiftPin = 8;
//Pin verbunden mit ST_CP (12) des 74HC595
int storePin = 9;
//Pin verbunden mit DS (14) des 74HC595
int dataPin = 10;
 
long counter = 65000;  // hochgesetzt um schneller an die Fehlerquelle zu gelangen
long counter2 = 0;
long counter3 = 0;
long counter4 = 0;
 
// Binärer Counter von 0 bis 255. 
// 1 = 000000001
// 2 = 000000010
// 3 = 000000011
// 4 = 000000100
// 5 = 000000101
// usw. Die LEDs zeigen alle Werte von 0 bis 255.
 
void setup() {
 // Pins 8,9,10 auf Ausgabe stellen
 pinMode(storePin, OUTPUT);
 pinMode(shiftPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 
 Serial.begin(9600);

}
 
 
void loop () 
{
 if(counter >255)
  {
  counter2 = counter / 255;
  }
  if (counter2 > 255)
   {
   counter3 = counter2 / 255;
   }
   if (counter3 > 255)
    {
    counter4 = counter3 / 255;
    }
 Serial.println(counter);
 digitalWrite(storePin, LOW);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter4);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter3);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter2);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter);
 digitalWrite(storePin, HIGH);
 delay(100);
 
 counter ++;
 if (counter > 16777216) {
   counter = 0;
 }
}

Sieht hier jemand wo ich eine Fehler eingebaut habe? Oder fuktioniert das so überhaupt nicht?

Ich bin für jeden hilfreichen Tip dankbar.

Tschüß
der Lokgeist

Meine Glaskugel sagt, dass hier was faul ist:

if (counter > 16777216)

Besser:

 if (counter > 16777216L)

Willst du auch negative Zahlen?
Nein? dann unsigned long.

Ansonsten kommt mir das alles irgendwie komisch vor...
32 Bit fortlaufend?
Dann schiebe die doch in einem Rums raus?
Wozu dann die 4 Counter? Einer reicht doch.

Wie hast du die 74HC595 angeschlossen?

Bitte lesen und lernen:
https://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister

Hallo combie,

keine negative Zahlen. Die Zahl sollte eigentlich 256x256x256=18609625 für drei Schieberegister heißen.
Zu den Countern. Ich dachte man müsse immer ein Register nach dem anderen befüllen und ausgeben.

Pst.

Das Ganze soll ein Gag werden und die vergangenen Sekunden in binärform anzeigen die in seinem Leben vergangen sind. Natürlich weiter fortlaufend.
Ich bin halt zu ungeübt für diese Aufgabenstellung. Es ist das erste mal dass ich was mit Schieberegistern mache.
Vieleicht doch noch ein kleiner Tip?

Tschüß
der Lokgeist

Vieleicht doch noch ein kleiner Tip?

Erstmal den von mir verlinken Artikel lesen.

Und diese auch:
https://www.arduino.cc/en/Reference/ShiftOut
https://www.arduino.cc/en/Tutorial/ShiftOut

Beachte das Kaskadieren.

Hallo combie,

besten Dank für Deine Mühe.
Den ersten Tip bei Mikrocontroller.net habe ich auch schon vorher mal gelesen gehabt. Aber da etwas auf den Arduino umzusetzen fällt mir schwer.
Die zwei anderen Tips sind zwar für den Arduino aber leider englisch was ich nicht behersche.
Auf YouTube giebt es volgendes Video:
Arduino Tutorial: Kapitel 3.1.3 - Lösung: Aufgabe 5 - Ein Schieberegister kommen selten allein
Eventuell komme ich ja damit doch noch zum Ziel. Nur funktionieren der angeführte Link zum Sketch leider nicht.

besten Dank
der Lokgeist

aber leider englisch was ich nicht behersche.

Oha....

Dann sind ja ca 99,8% der Computerliteratur für dich verdorben...

Mein Tipp:
Einfach trotzdem lesen!
Unbekannte Worte nachschlagen.
Das übt!

Lokgeist:
Suche Hilfe zu Schieberegister 74HC595. Ich habe einen alten Sketch für die fortlaufende Anzeige bis 255 in binärform und also acht Leuchtdioden ausgegraben.

long counter = 65000;

Ein Byte hat 8 Bit und Werte 0 bis 255. Integer mit 16 Bit geht bis 65535, Long mit 32 Bit bis 4294967295. Da ist also eine deutliche Diskrepanz zwischen den 8 Bit, die das Schieberegister kann und der Long-Variablen.

Referenz :

Syntax: shiftOut(dataPin, clockPin, bitOrder, value)
value: the data to shift out. (byte)

Es gibt nun mehrere Lösungsansätze, am besten nimmst Du den folgenden von Serenifly.

Man kann eine 16 Bit Zahl einfach mit Bit-Schieben aufteilen

unsigned int num = ...;

shiftOut(..., num);
shiftOut(..., num >> 8);

Geht auch mit 32 Bit. Dann muss man nur nochmal um 16 und 24 schieben

Hallo agmue,

ich hatte nun gerade Deinen Vorschlag mal umgesetzt auf mein Bedürfniss aber es gibt wieder keine Anzeige über die 16 Dioden.
Hier dann nochmal der neue Sketch:

//Pin verbunden mit SH_CP (11) des 74HC595
int clockPin = 8;  // shiftPin  clockPin
//Pin verbunden mit ST_CP (12) des 74HC595
int latchPin = 9;  // storePin  latchPin
//Pin verbunden mit DS (14) des 74HC595
int dataPin = 10;
 // Für mein Vorhaben also: 70 Jahre *365 Tage *24 Stunden *60 Minuten *60 Sekunden = 2.207.520.000 Sekunden
long counter = 100000000;  // hochgesetzt um schneller an die Fehlerquelle zu gelangen
//----------------------------------------------------------------
void bitAusgabe () {
  // Setzt und haelt latchPin waehrend der Datenuebertragung auf LOW.
  digitalWrite(latchPin, LOW);
  // Daten fuer vier 8-Bit-Register
  for (int j = 31; j >= 0; j--) {
    if (counter & (1 << j)) {
      digitalWrite(dataPin, HIGH);
    }
    else {
      digitalWrite(dataPin, LOW);
    }
    digitalWrite(clockPin, LOW);
    delayMicroseconds(100);
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(100);
  }
  // Setzt latchPin nach erfolgter Datenuebertragung auf HIGH.
  digitalWrite(latchPin, HIGH);
}
//---------------------------------------------------------------------
void setup() {
 // Pins 8,9,10 auf Ausgabe stellen
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 
 Serial.begin(9600);
}
//---------------------------------------------------------------------
void loop()
{
  for (counter ; counter < 4294967296; counter++)  //256*256*256*256 = 4.294.967.296
  {
    bitAusgabe();
    Serial.println(counter);
    Serial.println(counter, BIN);
    delay(10000);
  }
}

Warum geht es nicht über die 16 Dioden hinaus?
Wo mache ich den Fehler?

der Lokgeist

Erste Idee: counter < 4294967296L;

Das "L" für Long. Probier bitte mal.

Hallo an alle Helfer

Es funktioniert offensichtlich jetzt mit der dreimaligen Schiebefunktion.
Das zusätzliche "L" braucht man nicht. Wohl aber "unsigned long".

void loop() 
{
//for (counter ; counter < 4294967296; counter++) //256*256*256*256 = 4.294.967.296
//{  
 Serial.println(counter);
 Serial.println(counter, BIN);
 digitalWrite(storePin, LOW);
 //shiftOut(dataPin, shiftPin, MSBFIRST, counter >> 32);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter >> 24);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter >> 16);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter >> 8);
 shiftOut(dataPin, shiftPin, MSBFIRST, counter);
 digitalWrite(storePin, HIGH);
 delay(1000);
 //} 
}

Einige Versuche dahinter zu kommen scheinen auch auf das Konto der :frowning: defekten 17.Diode : >:( zu kommen. Ausgerechnet die. Wo ja die Startdiode des nächsten Registers ist.

Habt alle recht herzlichen Dank. Und das meine ich wörtlich!

der Lokgeist

Erstmal Glückwunsch!

Das zusätzliche "L" braucht man nicht.

Mit dem weglassen hättest du das falsche gelernt.
Nicht jeder Kompiler handelt das so ab.
Jeder Programmierer, oder sonst wie eingewiesene Person, wird darüber stolpern und denken "Och nöö, was passiert denn da?"

Tu dir und dem Kompiler einen Gefallen und setze das L, in deinem Fall das UL, also 4294967296UL, wenn du unsigned long meinst.
Der Programmtext ist dann viel leichter zu lesen.
Das Programm wird portabler, leichter auf andere Maschinen übertragbar.
Auch bei diesem Kompiler, welchen wir hier verwenden, ist das typisieren von Konstanten in vielen Situationen unabdingbar.

Tipp:
Dieses Quentchen, an dafür notwendiger, Disziplin wird reich belohnt!
(das sagt dir einer, der sich schon wegen solch einem Mist die Augen blutig gesucht hat)

counter < 4294967296

kann man sich übrigens immer sparen (mit oder ohne UL). Jeder unsigned long Wert ist < 4294967296 und läuft gegebenenfalls vorher über. Wofür man aber bei delay(1000) einige Geduld braucht.

( Ja, der arduino kann 64 bit integer, aber unsigned long long counter sehe ich nirgends ! )

Im Prinzip hat combie recht, ausser dass 4294967296, egal wie, nicht lesbar ist.
( Hab ich per copy-paste eingefügt, ehrlich !)

Im Prinzip hat combie recht, ausser dass 4294967296, egal wie, nicht lesbar ist.

0xFFFFFFFFUL

Besser?

Oder -1L ?
Wobei, das nur einen Vorteil hat, es ist knapp.
Sebstredend ist das auch nicht.

Im Grunde kann man den Counter einfach rum laufen lassen.......
Kein Vergleich nötig.
Die forschleife entsorgen, wegen Sinnfrei.
counter++ reicht.

C++14 (ab gcc 4.9) hat ein Hochkomma als Trennzeichen für Ziffern-Gruppen (bei uns sind da Tausender normal, aber das ist nicht überall so). Vielleicht kommt das ja auch irgendwann mal auf dem Arduino :slight_smile:

EDIT:
Wobei das korrekteste bei sowas diese Makros sind:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html
Etwas runter scrollen zu "Limits of specified-width integer types"