In Schleife auf Geber warten

Hallo zusammen,

nachdem ich hier schon eine Weile mitlese und die Suchfunktion nach einer Lösung für mein Anfängerproblem erfolglos strapaziert habe, traue ich mich mal zu fragen:

Basierend auf dem ShiftOut-Tutorial habe ich eine entsprechende Schaltung mit einem 74HC595 aufgebaut, die auch soweit funktioniert. (Zum Ausprobieren habe ich derzeit noch LEDs angeschlossen, im späteren Betrieb sollen aber über einen ULN2803 Relais geschaltet werden.)
Das Ein- und Ausschalten der Ausgänge soll mit dem Ablauf einer Maschine synchronisiert werden. Dazu sind auf einer Welle zwei entsprechende Geber montiert. Wenn Geber 1 einen Kontakt schließt, sollen die Ausgänge des 595 deaktiviert werden (digitalWrite(latchPin, LOW);) In dieser Phase soll das nächste Muster in die Register geschoben werden. Erst wenn Geber 2 schließt, sollen die Ausgänge des 595 wieder aktiviert werden (digitalWrite(latchPin, HIGH);).
Die Geber sind potenzialfreie Kontakte und schließen Pin 2 bzw 3 gegen Gnd.
Hat jemand eine Idee, wie ich das zuwege bringe?
Ich hab' das nicht funktionierende Gebastel mal wieder rausgenommen und Lücken gelassen.

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
//Pin connected to DS of 74HC595
int dataPin = 11;
//Pins mit Geberanschluß 
int gebera = 2;
int geberb = 3;

int muster[] = {8,192,96,48,24,12,6,3,85};

void setup() {
  // Pins setzen
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
  // 
  // 


  for (int numberToDisplay = 1; numberToDisplay < muster[0]+1; numberToDisplay++) {
    // Hier soll gewartet werden, bis Geber 1 in Position ist
    
    
    // die im vorherigen Durchlauf gesetzten Ausgänge am 595 abschalten
    digitalWrite(latchPin, LOW);    
    // Muster in 595 schreiben
    shiftOut(dataPin, clockPin, MSBFIRST, muster[numberToDisplay]);  

    // Einschalten per Latch nach Kontaktschluß
    // hier soll die Ausführung unterbrochen werden, bis der Geber 2 in Position ist.
    
    
    //
    digitalWrite(latchPin, HIGH);
    // Pause kann entfallen, wenn auf den nächsten Geber gewartet wird
    // delay(100);
  }
}

Ich danke im Voraus ganz herzlich.
Grüße, Michael

So ganz klar ist mir die Sache noch nicht, ich vermute es gibt da noch ein paar Mißverständnisse.

Fangen wir einmal bei der Anforderung an: Du hast ein paar Relais an einem oder mehreren 74hc595. Diese Relais sind entweder offen oder geschlossen, werden aber immer vom 74hc595 bedient. Der interessant Punkt hier ist, daß du nicht mit Tristateausgängen herumbastelst. Dann sind da noch die zwei Geber. Wenn Geber 1 geschlossen wird, werden diverse Relais eingeschalten. Wenn Geber 2 geschlossen wird, sollen alle Relais ausgeschalten werden. Also: Gebert 1 -> Daten, Geber 2 -> lauter 0 schreiben.

Nun zur Verwendung des 74HC595. Der hat einen seriellen Eingang (Pin14 am 74HC595), einen Clock-Eingang (Pin11 am 74HC595) die beide von shiftOut bedient werden sowie einen Latch-Eingang (Pin12 am 74HC595). Den Latch-Eingang muß dein Programm bedienen und der hat genau eine einzige Funktion: Wenn der von LOW auf HIGH geschalten wird, werden die zuvor gesendeten seriellen Daten auf die Ausgänge geschalten. Sonst nichts. Direkt danach kannst den Latch-Eingang wieder auf LOW setzen, damit er fürs nächste Mal bereit ist.

Dein Programm sollte demnach etwa so aussehen:

const int dataPin = ???;
const int clockPin = ???;
const int latchPin = ???;
const int gebera = 2;
const int geberb = 3;
int lastGebera = HIGH; // HIGH = offen, LOW = geschlossen
int lastGeberb = HIGH; // HIGH = offen, LOW = geschlossen

const int musterMax = 9;
int8_t muster[musterMax] = {8,192,96,48,24,12,6,3,85};
int musterZaehler = 0;

void setup() {
  // Pins setzen
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  // Geber Pins konfigurieren und internen Pull-up aktivieren 
  pinMode(gebera, INPUT);
  pinMode(geberb, INPUT);
  digitalWrite(gebera, HIGH);    
  digitalWrite(geberb, HIGH);    

  // 74hc595 vorbereiten.
  shiftOut(dataPin, clockPin, MSBFIRST, 0);  
}

void loop() {
  // Geber lesen.
  int curGebera = digitalRead (gebera);
  int curGeberb = digitalRead (geberb);

  if (curGebera != lastGebera && curGebera == LOW) {
    // Geber A ist gerade aktiviert worden

    // Vorbereitete Daten rausschreiben
    digitalWrite(latchPin, HIGH);    
    digitalWrite(latchPin, LOW);    

    // Shift-Register fuer Geberb vorbereiten
    shiftOut(dataPin, clockPin, MSBFIRST, 0);  
  }
  else if (curGeberb != lastGeberb && curGeberb == LOW) {
    // Geber B ist gerade aktiviert worden

    // Vorbereitete Daten rausschreiben
    digitalWrite(latchPin, HIGH);    
    digitalWrite(latchPin, LOW);    

      // Shift-Register fuer Gebera vorbereiten
    shiftOut(dataPin, clockPin, MSBFIRST, muster[musterZaehler]);  

    // Naechstes Muster auswählen.
      musterZaehler = (musterZaehler + 1) % musterMax;
  }
  // Zustand merken
  lastGebera = curGebera;
  lastGeberb = curGeberb;

  // Sollten die Geber prellen, dann hier noch ein passendes delay() einfügen
  // delay (20);
}

Der Code ist wie immer ungetestet. Die Fehler bekommst du Gratis als Denksportaufgabe.

Korman

Hallo und Danke,

da ist einiges zum Nachdenken bei.
Als erstes hast Du mein grundlegendes Mißverständnis bezüglich der Funktion des Latches korrigiert. Ich hatte angenommen, durch Zurücksetzen des Latchpins würden die Ausgänge des 74HC595 auch wieder deaktiviert. Ich hätte bei meinem Testaufbau ein paar Delays mehr einbauen sollen, dann hätte ich das sogar ohne Oszilloskop bemerken können.

Dass es einen anderen Aspekt gibt, der mißverständlich ist, hast Du auf Anhieb bemerkt.
Ich hatte in der Problemstellung von Relais geschrieben. Ich hatte gedacht die Vereinfachung tut der Sache keinen Abbruch. Die zu schaltenden Relais sind genaugenommen Elektromagnete. Aus Sicht der Schaltung zwar mit Relais vergleichbar, die Einbindung in die Taktung der mechanischen Funktionen ist aber von Bedeutung. Ich beschreibe mal etwas genauer. Eine Reihe senkrecht ausgerichteter Blechstreifen, die in einer passenden Führung sitzen, werden durch einen exzentergesteuerten Hubmechanismus angehoben. Wenn sie oben am Umkehrpunkt sind, sollen die Magnete einzelne Blechstreifen oben festhalten, während sich der Hubmechanismus für einen Exzenterumlauf senkt. Der kritischere der beiden Geber ist der, der das Erreichen des oberen Umkehrpunktes meldet. (Latch = On). Es gibt einen frühesten Zeitpunkt, zu dem die Magnete wieder loslassen dürfen. Deshalb habe ich den zweiten Geber ins Spiel gebracht. Er sollte bewirken, daß so früh wie möglich das Latch wieder freigegeben wird, damit genug Zeit zum Schreiben des neuen Bitmusters bleibt. Wenn das Zurücksetzen des Latches kein Abschalten der Magnete bewirkt, sollte ich mir im Grunde den zweiten Geber sparen. Wenn die Ausgänge des 74HC595 frühestens beim nächsten Setzen des Latches auf Hoch wieder Abschalten, ist alles gut. Das Latch kann gleich wieder auf Low, das nächste Muster eingeschoben werden, und erst wenn das Hubelement wieder oben ist, wird neu geschaltet. Bei den Elementen, die vorher oben waren, wird sogar die Fallhöhe reduziert, weil der Hubzapfen nah am Hubelement ist.

Ich werd' morgen mal rangehen und mit nem Schalter den Geber simulieren.

Auf jeden Fall schonmal herzliches Dankeschön.
Gruß, Michael