6 shift register, 3 data Pins - möglich?

Wie im Titel schon beschrieben, hatte ich vor 6 shift register (je 2 hintereinander) mit 3 data Pins anzusteuern.
Alle shift register sollen einen gemeinsamen latch und clock Pin haben, nur 3 getrennte data Pins.
Im Anhang mein Vorhaben als Schaltplan.

Bevor gefragt wird wofür ich dies so machen möchte und nicht einfach alle hintereinander schalte:
Ich möchte damit RGB LEDs ansteuern und so für mich eine übersichtliche Trennung zwischen Rot, Grün und Blau haben.

Wenn dies nicht geht, muss wohl alle hintereinander schalten.. aber rein logisch spricht für mich da nichts gegen?

Das sollte gehen

Okay, dann bin ich doch nicht komplett blöd :')
Ich frage mich, warum dies dann nicht bei mir funktioniert..
Es wird immer nur die letzte "shift register Reihe" verwendet.. Wenn ich data1 und data2 vertausche, dann ist wiederum das die andere "Reihe".

Hab ich im Programm etwas nicht beachtet? :confused:

const byte allePins[] = {0, 1, 2, 4, 5, 6, 7, 8};
const byte alleLayers[] = {0, 1, 2};
int layer1 = 0;
int layer2 = 1;
int layer3 = 2;
int layer4 = 3;

int clockPin = 8;
int latchPin = 7;
int data1 = 4;
int data2 = 5;
// int data3 = 6;

byte dataArray1;
byte dataArray2;

byte Array01[6];   byte Array01_1[6];


void setup() {
  for (int i = 0; i < sizeof(allePins); i++) {
    pinMode(allePins[i], OUTPUT);
  }
  for (int i = 0; i < sizeof(alleLayers); i++) {
    digitalWrite(alleLayers[i], LOW);
  }

  //------------------------------------------------------------ArrayRotor
  Array01[0] = 0x84; /*10000100*/    Array01_1[0] = 0x21; /*00100001*/
  Array01[1] = 0x0C; /*00001100*/    Array01_1[1] = 0x30; /*00110000*/
  Array01[2] = 0x03; /*00000011*/    Array01_1[2] = 0xC0; /*11000000*/
  Array01[3] = 0x12; /*00010010*/    Array01_1[3] = 0x48; /*01001000*/
  Array01[4] = 0x22; /*00100010*/    Array01_1[4] = 0x44; /*01000100*/
  Array01[5] = 0x44; /*01000100*/    Array01_1[5] = 0x22; /*00100010*/
}

void loop() {
  rotor();
}

//------------------------------------------------------------shiftOut
void shiftOut(int myDataPin, byte myDataOut) {
  int i = 0;
  int pinState;
  digitalWrite(myDataPin, 0);
  digitalWrite(clockPin, 0);

  for (i = 7; i >= 0; i--)  {
    digitalWrite(clockPin, 0);
    if ( myDataOut & (1 << i) ) {
      pinState = 1;
    }
    else {
      pinState = 0;
    }
    digitalWrite(myDataPin, pinState);
    digitalWrite(clockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  digitalWrite(clockPin, 0);
}


//------------------------------------------------------------rotor
void rotor() {
  for (int i = 0; i < 6; i++) {
    dataArray1 = Array01[i];
    dataArray2 = Array01_1[i];
    digitalWrite(latchPin, 0);
    shiftOut(data1, dataArray1);
    shiftOut(data1, dataArray2);
    shiftOut(data2, dataArray1);
    shiftOut(data2, dataArray2);
    digitalWrite(latchPin, 1);


//mehrere Ebenen, welche mit MosFets geschaltet werden.
    for (int j = 0; j < 25; j++) {
      digitalWrite(layer1, HIGH);
      delay(1);
      digitalWrite(layer1, LOW);
      digitalWrite(layer2, HIGH);
      delay(1);
      digitalWrite(layer2, LOW);
      digitalWrite(layer3, HIGH);
      delay(1);
      digitalWrite(layer3, LOW);
      digitalWrite(layer4, HIGH);
      delay(1);
      digitalWrite(layer4, LOW);
    }
  }
}

Ahh, ich hätte mal mehr darüber nachdenken sollen. Auch siehe Datenblatt Seite 6:

Jedesmal wenn ein Puls am Clock Pin kommt wird ja geschoben. Die können also nicht für alle gleich sein.

Man sollte also eher vielleicht die Daten-Pins für alle gleich machen und jedem Register einen eigenen Clock Pin spendieren...vielleicht...

Mit Clock meine hier SH_CP (shift clock pin). Solange der dann Low bleibt passiert mit dem Register nichts. Auf ST_CP reagiert es aber kopiert nur dein Inhalt vom den Schiebe-Puffern auf die Ausgänge

Dein Problem ist, dass Du die 3 Reihen einzeln schieben willst, aber alle Clock-Pins verbunden sind. Du schiebst also immer alle Reihen. Daher musst Du auch immer alle 3 Datenleitungen richtig setzen, bevor Du einen Clockpuls erzeugst. Wenn Du das nacheinander machst, schiebst Du immer in die anderen Reihen falsche Daten, und nur die zuletzt angesteuerte Reihe hat die richtigen Daten.

Edit: Wenn man die Clockpins trennt und nur einen Datenpin hat, könnte man auch gleich alle Schieberegister in Reihe schalten. Denn so wie ich das verstehe, sollen ja immer alle Register mit Daten versorgt werden.

MicroBahner:
Denn so wie ich das verstehe, sollen ja immer alle Register mit Daten versorgt werden.

Er hat 3 * 2 Register. Die drei Gruppen sollen getrennt angesteuert werden. Wenn man alle in Reihe hängt muss man auch immer die Daten für alle liefern.

Wenn man gemeinsame Daten-Pins und Latch-Pins hats, kann man doch mit dem Clock-Pin bestimmen in welche Gruppe die Daten geschoben werden

Ich hatte es so verstanden, dass eine Reihe für rot, eine für grün und eine für blau ist, und er die Farbinfo logisch trennen möchte - also für jede Farbe einen eigenen Datenpin. Verändert werden aber immer alle.

Wenn die 3 Reihen aber zu unterschiedlichen Zeiten mit Daten befüllt werden, dann ist es in der Tat so, dass es getrennte Clockpins braucht.

MicroBahner:
Dein Problem ist, dass Du die 3 Reihen einzeln schieben willst, aber alle Clock-Pins verbunden sind. Du schiebst also immer alle Reihen. Daher musst Du auch immer alle 3 Datenleitungen richtig setzen, bevor Du einen Clockpuls erzeugst. Wenn Du das nacheinander machst, schiebst Du immer in die anderen Reihen falsche Daten, und nur die zuletzt angesteuerte Reihe hat die richtigen Daten.

Edit: Wenn man die Clockpins trennt und nur einen Datenpin hat, könnte man auch gleich alle Schieberegister in Reihe schalten. Denn so wie ich das verstehe, sollen ja immer alle Register mit Daten versorgt werden.

In diesem Beispiel sollen 2 Reihen das gleiche machen, aber es kommen auch noch Funktionen, wo dies nicht der Fall ist, deshalb die getrennten Daten Pins.

Das mit dem Clockpin habe ich nicht bedacht.
Aber ich könnte ja am ShiftOut arbeiten, so dass alle 3 Daten Pins gleichzeitig verarbeitet werden.

Ich versuche mal was...

Es hat funktioniert! :slight_smile:

Lasse jetzt im ShiftOut alle 3 Daten gleichzeitig verarbeiten, so dass ich nur nach die einzelnen Daten Angeben muss, die Pins verändern sich ja nicht mehr.

void shiftOut(byte myDataOut1, byte myDataOut2, byte myDataOut3) {
  int i = 0;
  int pinState1;
  int pinState2;
  int pinState3;
  digitalWrite(data1, 0);
  digitalWrite(data2, 0);
  digitalWrite(data3, 0);
  digitalWrite(clockPin, 0);

  for (i = 7; i >= 0; i--)  {
    digitalWrite(clockPin, 0);
    if ( myDataOut1 & (1 << i) ) {
      pinState1 = 1;
    }
    else {
      pinState1 = 0;
    }
    if ( myDataOut2 & (1 << i) ) {
      pinState2 = 1;
    }
    else {
      pinState2 = 0;
    }
    if ( myDataOut3 & (1 << i) ) {
      pinState3 = 1;
    }
    else {
      pinState3 = 0;
    }
    digitalWrite(data1, pinState1);
    digitalWrite(data2, pinState2);
    digitalWrite(data3, pinState3);
    digitalWrite(clockPin, 1);
    digitalWrite(data1, 0);
    digitalWrite(data2, 0);
    digitalWrite(data3, 0);
  }
  digitalWrite(clockPin, 0);
}

Hier, wie man das ShiftOut jetzt anspricht:

void rotor() {
  for (int i = 0; i < 6; i++) {
    dataArray1 = Array01[i];
    dataArray2 = Array01_1[i];
    digitalWrite(latchPin, 0);
    shiftOut(dataArray1, dataArray1, dataArray1);
    shiftOut(dataArray2, dataArray2, dataArray2);
    digitalWrite(latchPin, 1);

    for (int j = 0; j < 25; j++) {
      digitalWrite(layer1, HIGH);
      delay(1);
      digitalWrite(layer1, LOW);
      digitalWrite(layer2, HIGH);
      delay(1);
      digitalWrite(layer2, LOW);
      digitalWrite(layer3, HIGH);
      delay(1);
      digitalWrite(layer3, LOW);
      digitalWrite(layer4, HIGH);
      delay(1);
      digitalWrite(layer4, LOW);
    }
  }
}

Ergebnis: Alle 3 Reihen, führen gleichzeitig, die angegeben Daten aus.

Dank euch, dass ich auf den richtigen Pfad mit den Clock Pins gekommen bin.

Du kannst nicht 3 Shiftregister paralell mit shiftOut() benutzen, da shiftout nur 1 Datenpin bedient.
Du mußt die Übertragung manuell machen indem Du die Daten auf den 3 Datenpins schreibst und dann den Clock wechselst, also shiftout imitierst.

Bevor gefragt wird wofür ich dies so machen möchte und nicht einfach alle hintereinander schalte:
Ich möchte damit RGB LEDs ansteuern und so für mich eine übersichtliche Trennung zwischen Rot, Grün und Blau haben.

Ich sehe hier aber nur Nachteile gegenüber alle 6 Shiftregister in Reihe zu schalten und Dein Einwand ist nur ein Knoten in Deinen Gedankengängen.
Du kannst die Daten für die 3 Farben getennt verarbeiten aber dann alle 6 Byte hintereinander rausschicken. Das kompliziert die Sache nicht im geringsten.

einfach
Du hast die Daten in zB rot[2], gruen[2] und blau[2]

Beim Rausschicken einfach 6 x shiftout von rot[0],rot[1],gruen[0],gruen[1],blau[0],blau[1]. So bleibt alles schön getrennt und die Schieberegister können hintereinander geschaltet werden.

Ich nehme mal an Du hst einen Arduino UNO.
Laß die pins D0 und D1 frei. Die brauchst Du für die serielle Schnittstelle. auch wenn Du diese im endgültigen Sketch nicht benutzt ist sie für Debugingmeldungen notwendig. Wenn Di nicht gnügend Pins hast, die analogen Pins können auch als digitale verwendet werden (D14 bis D19)

Grüße Uwe

uwefed:
Du kannst nicht 3 Shiftregister paralell mit shiftOut() benutzen, da shiftout nur 1 Datenpin bedient.

Da er sein eigenes shiftOut geschrieben hat, geht das schon.
Ob's sinnvoll ist, ist eine andere Frage.

MicroBahner:
Da er sein eigenes shiftOut geschrieben hat, geht das schon.
Ob's sinnvoll ist, ist eine andere Frage.

Ich rede hier von der Arduino Funktion shiftOut(). Natürlich kann man Funktionen schreiben die ähnliches machen. Man kann sogar eine Funktion schreiben die 4 oder 8 bit paralell rausschreibt, wie es zB die Arduino- LiquidCrystal Bibliothek macht.

Grüße Uwe

Hallo,

das hilft aber dem Thread nicht wenn du plötzlich von der gleichnamigen Arduino Funktion redest wenn alle anderen von seiner eigenen Funktion reden. :slight_smile: :slight_smile:

Wenn der TO seinen Code aufräumt, kann man am Ende alles Index basiert mit for Schleifen erschlagen. Das wäre mein Tipp bevor der Code weiter ausgebaut wird. Das endet sonst im Kaos. Versprochen. Das fängt damit an wie weit man die Vorüberlegungen treibt. Die Rotormatrix sollte man gleich in Bit Schreibweise definieren und vielleicht auch gleich in einem 2 dimensionalen Array. Dann kann man wie erwähnt alles Index basiert in for erschlagen.

Bsp.
const byte Y_ROTOR = 6;
const byte X_ROTOR = 2; 

byte matrixRotor[Y_ROTOR][X_ROTOR] =    // 6/2
{
  //   eins,      zwei
  { B10000100, B00100001 },
  { B00001100, B00110000 },
  { B00000011, B11000000 },
  { B00010010, B01001000 },
  { B00100010, B01000100 },
  { B01000100, B00100010 },
};

Mit Y gehst du Zeilenweise und mit X Spaltenweise durch die Tabelle. Die Konstanten nutzt du mit für die for Schleifen. Sollte eine 3. Rotor dazukommen setzt du eine 3. Spalte rein.

Tja und dann würde ich eine Array aus 2 Byte Werten oder meinetwegen zwei Byte Einzelvariablen als Zwischenbuffer erstellen. Eine Auslesefunktion ermittelt Zeile für Zeile die beiden X Werte und speichert sie in obigen zwischen. Diese werden dann von der ShiftOut Funktion an die Datenpins angelegt. Das alles rotiert Byteweise immer über alles hinweg. Soweit meine Überlegungen dazu.