Sehr dringend Hilfe für Stoppuhr benötigt

Kannst du mal den genauen Artikel posten den du im Einsatz hast? Das komische Datenblatt bringt nicht viel.

Die Lichtschranken?

Kemo B232Z

Datenblatt
Seite 4, 2. Reihe Platine B232/E1
Seite 4, unten links = Schaltplan Empfänger E1

Pin1 +5V
Pin2 GND
Pin3 Out

Bei der Originaluhr (Platine B232E2, oben links) kippt das Signal ein bistabiles Flipflop, damit die LS umgeschaltet werden.

tilloriemer:

  1. Angeschlossen am Arduino, mit laufendem Sketch
    a) bei nicht unterbrochener Lichtschranke = 1,68 Volt
    b) bei unterbrochener Lichtschranke = ? Volt (nicht messbar, Kontak mit Messpunkt schaltet Sketch um, LS-Unterbrechung wirkt nicht mehr)

  2. Enden der Lichtschranke nicht angeschlossen, nur am Multimeter
    a) bei nicht unterbrochener Lichtschranke = 0.03 Volt
    b) bei unterbrochener Lichtschranke = 1.x Volt (nicht richtig messbar, fällt sofort wieder zurück)

Eventuell ist der eingebaute PullUp-Widerstand doch zu schwach.

Hast Du Widerstände 4.7K (4700 Ohm) oder etwas vergleichbares in der Bastelkiste?

Keine Gewähr für die Richtigkeit und/oder Folgeschäden an Deiner Lichtschranken-Schaltung:
Ich würde mal von der +5V Betriebsspannung einen 4.7K Widerstand zum Arduino-Eingang als zusätzlichen externen PullUp-Widerstand schalten. Offenbar kann der interne PullUp die Spannung nur auf 1,68 Volt hochziehen, aber das ist zu wenig, um vom Arduino als HIGH Pegel erkannt zu werden.

Der Arduino benötigt ein Eingangssignal, das zwischen 5V (HIGH) und 0V (LOW) wechselt und ein Signal, das nur zwischen 1.67V und 0V wechselt reicht nicht aus. Minimum für High-Pegel wäre ca. 0,6 mal Betriebsspannung, also ca. 3V. Also ich würde es wohl mal mit dem "stärkeren" 4700 Ohm PullUp am Eingangspin riskieren. Aber eine Garantie kann ich nicht übernehmen. Ich bin eher Spezialist fürs Programmieren als für Hardwareschaltungen.

Habe die Messwerte korrigiert, hatte zuerst mit der Kontrolldiode gemessen. Am Ausgang liegen 4,9 V, bei LS-Unterbrechung sinkt dieser Wert kurz gegen 4,8, steigt aber sofort wieder.

tilloriemer:
Habe die Messwerte korrigiert, hatte zuerst mit der Kontrolldiode gemessen. Am Ausgang liegen 4,9 V, bei LS-Unterbrechung sinkt dieser Wert kurz gegen 4,8, steigt aber sofort wieder.

OK, 4.9V sind völlig OK und entsprechen einer USB-Stromversorgung, die meist bei knapp 5V liegt.
Der PullUp reicht aus.

Aber jetzt würde mich der zweite Wert bei unterbrochener Lichtschranke noch interessieren. Wie ändert sich die Spannung bei unterbrochener Lichtschranke?

Miss mal die Spannungen mit einem Test-Sketch, bei dem nur die PullUp-Widerstände aktiviert werden, aber der sonst nichts macht:

#define STARTLICHTSCHRANKE A1  // Lichtschranke zum Starten der Zeit
#define STOPPLICHTSCHRANKE A2  // Lichtschranke zum Stoppen der Zeit

void setup() {
  pinMode(STARTLICHTSCHRANKE,INPUT_PULLUP);
  pinMode(STOPPLICHTSCHRANKE,INPUT_PULLUP);
}

void loop() {
}

Was macht die Spannung, wenn dieser Sketch läuft und die Lichtschranke angeschlossen ist?

Wenn die Spannung nur kurz nach unten wegzuckt, kann es vielleicht sein, dass Du gar kein Signal abgreifst, das zwischen HIGH und LOW wechselt, wenn die Lichtschranke unterbrochen wird, sondern ein Signal, bei dem andere Informationen übertragen werden? Kann das eine serielle Schnittstelle sein, über die irgendwas übertragen wird, und zwar nur im Augenblick des Umschaltens?

@jurs

Messung zwischen GND und Pin 3

  1. LS offen = 0.06 Volt

  2. LS unterrochen = kurzer Anstieg auf ca. 0,9 Volt

  • aber das Messgeräte ist offensichtlich zu träge, um das sehr kurze Signal komplett zu messen. Es müsste nach meinem Verständnis auf 1.6 Volt ansteigen.
  • Fallback auf 0,06 Volt bei weiterhin unterbrochener LS

Das sieht m. E. nicht danach aus, als wenn das Signal so wirklich verwertbar wäre.

Im Original (siehe: http://www.kemo-electronic.com/eam/b232/eam_b232.pdf) kippt das Signal ein Flipflop, um die 1. LS zu sperren und die 2. LS freizugeben. Hier laufen beide LS auf den gleichen Kontakt der Uhr auf. Das 1. Signal startet, das 2. Signal stoppt die Uhr.

Könnte in unserem Fall ein zusätzliches FF helfen, das Siganl weiter aufzubereiten, um das für den UNO nötige Schaltsignal (Spannungsdifferenz) zu bekommen?

tilloriemer:
Messung zwischen GND und Pin 3

  1. LS offen = 0.06 Volt

  2. LS unterrochen = kurzer Anstieg auf ca. 0,9 Volt

  • aber das Messgeräte ist offensichtlich zu träge, um das sehr kurze Signal komplett zu messen. Es müsste nach meinem Verständnis auf 1.6 Volt ansteigen.
  • Fallback auf 0,06 Volt bei weiterhin unterbrochener LS

Du hast das Abgreifen des Signals noch nicht im Griff.

Ich poste mal noch ein Testprogramm, und zwar für den SERIELLEN MONITOR zur Debug-Ausgabe:
(KEINE Ausgabe auf LCD!)

#define INPUTTYPE INPUT_PULLUP  // auf INPUT oder INPUT_PULLUP setzen
#define LICHTSCHRANKE A1  // Lichtschranke 

void setup() {
  Serial.begin(9600);
  pinMode(LICHTSCHRANKE,INPUTTYPE);
}

byte lastState;
void loop() {
  byte state=digitalRead(LICHTSCHRANKE);
  if (state != lastState)
  {
    if (state==LOW) Serial.print("L\n");
    else Serial.print("H\n");
    lastState=state;
  }
}

Teste mit dem Programm mal an Deinen Lichtschranken-Pins:
Wird H und L ausgegeben, wenn die Lichtschranke unterbrochen wird?

Variation: Ändere den INPUTTYPE mal von INPUT_PULLUP auf INPUT:

#define INPUTTYPE INPUT

Wieder testen: Wird H und L ausgegeben, wenn die Lichtschranke unterbrochen wird?

Ergibt der Test mit dem oben stehenden Code oder mit der beschriebenen Variation irgendwas auf dem seriellen Monitor aus, wenn die Lichtschranke unterbrochen wird?

Zumindest ist seit dem Posting von Mike60 auf den Artikel, in dem die Grafik http://www.ibrieger.de/sites/default/files/ls_unterbrechung.jpg verlinkt ist, ja klar, dass es bei Unterbrechung der Lichtschranke keine dauerhafte Pegeländerung gibt, sondern das Signal nur ein paarmal hin- und herzappelt.

#define INPUTTYPE INPUT_PULLUP = H, einmal beim Einschalten ohne dass die LS betätigt wird.

#define INPUTTYPE INPUT = H und L laufend schnell abwechselnd, ohne dass die LS betätigt wird.

Unterbrechung der LS zeigt bei beiden keine Veränderung der Ausgabe.

tilloriemer:
#define INPUTTYPE INPUT_PULLUP = H, einmal beim Einschalten ohne dass die LS betätigt wird.

#define INPUTTYPE INPUT = H und L laufend schnell abwechselnd, ohne dass die LS betätigt wird.

Unterbrechung der LS zeigt bei beiden keine Veränderung der Ausgabe.

Hm, also die beiden gängisten Typen von Ausgang (Open-Collector bzw. Push-Pull) sind es dann schon mal nicht.

Nur mit "INPUT" scheint das Signal zu floaten, möglicherweise mit 50 Hz, weil Du ein Netzbrummen auffängst.

Bleibt eigentlich nur noch übrig, das Signal auf LOW zu pullen, mit einem PullDown-Widerstand.
Per Software ist das nicht möglich.

Also wieder den 4.7K (4700 Ohm) Widerstand aus der Bastelkiste genommen, und als PullDown-Widerstand an den Eingangspin angeschlossen. Den 4700 Ohm Widerstand zwischen GND und dem Arduino Eingangspin geschaltet.

Dann den Sketch wieder setzen auf:

#define INPUTTYPE INPUT

Dann nochmal mit dem PullDown-Widerstand in der Schaltung messen.

#define INPUTTYPE INPUT_PULLUP

So, ich greife das Signal nun mal vor der Diode ab, dann bekomme ich, wenn ich die LS unterbreche, ein H mit 1.6 Volt und sofort wieder ein L.

Ok, wenn ich die Diode im Ausgang der LS umgehe, schaltet das alles sauber (grummel!) ... mit dem Stoppuhrensketch von gestern funktioniert es nun. Fehlt nur noch der Umbruch bei 60, dann wäre es optimal.

tilloriemer:
#define INPUTTYPE INPUT_PULLUP

So, ich greife das Signal nun mal vor der Diode ab, dann bekomme ich, wenn ich die LS unterbreche, ein H mit 1.6 Volt und sofort wieder ein L.

Das klingt doch gut.
Auch ein kurzes HIGH kann man als Start- oder Stopbedingung auswerten.
Dann sollte doch das Testprogramm aus Reply #14 von gestern laufen, wenn man den UNTERBRECHUNGSPEGEL als HIGH definiert.

Ich vereinfache das Programm aus Reply #14 nochmal und setze den UNTERBRECHUNGSPEGEL auf HIGH, dann sieht es so aus:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Für Sainsmart LCD Keypad Shield

#define STARTLICHTSCHRANKE A1  // Lichtschranke zum Starten der Zeit
#define STOPPLICHTSCHRANKE A2  // Lichtschranke zum Stoppen der Zeit
#define UNTERBRECHUNGSPEGEL HIGH // welcher Pegel signalisiert eine Unterbrechung der Lichtschranke?
#define INPUTTYPE INPUT_PULLUP


void setup() {
  Serial.begin(9600);
  lcd.begin(16,2);
  Serial.println("Messbereitschaft");
  lcd.print("Messbereitschaft");
  pinMode(STARTLICHTSCHRANKE,INPUTTYPE);
  pinMode(STOPPLICHTSCHRANKE,INPUTTYPE);
  delay(10);
}

void loop() {
  while (digitalRead(STARTLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) ; // warten auf Unterbrechung der Start-Lichtschranke
  unsigned long zeit=millis(); // Jetzt wurde gestartet
  Serial.println("gestartet");
  lcd.clear();
  lcd.print("gestartet");
  while (digitalRead(STOPPLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) ; // warten auf Unterbrechung der Stopp-Lichtschranke
  zeit=millis()-zeit; // Jetzt wurde gestoppt
  Serial.print("Zeit: ");
  Serial.println(zeit/1000.0,3);
  lcd.clear();
  lcd.print("Zeit: ");
  lcd.print(zeit/1000.0,3);
  while(1); // Endlosschleife - Warten auf Reset
}

tilloriemer:
Fehlt nur noch der Umbruch bei 60, dann wäre es optimal.

Was für ein "Umbruch bei 60"?

Dass Zeiten über 60 Sekunden in der Form "m:ss,xxx" angezeigt werden?

Klappt wunderbar.

Dass Zeiten über 60 Sekunden in der Form "m:ss,xxx" angezeigt werden?

Ja, genau das: mm:ss:xxx

Kann man die Zeitanzeige während der Messung einblenden?

tilloriemer:
Ja, genau das: mm:ss:xxx

Kann man die Zeitanzeige während der Messung einblenden?

Im Prinzip kannst Du alles programmieren.
Wenn die Lichtschranke am Ende nur ein sehr kurzes HIGH Signal abgibt, das danach sofort wieder auf LOW wechselt, darf die Ausgabeprozedur zwischendurch nur nicht zu lange dauern. Sonst müßte man die Signale per Interruptbehandlung erkennen und das einfache den Eingang "pollende" Programm in ein etwas komplexeres Programm mit schneller Interruptverarbeitung umschreiben. Das muß aber wohl nicht sein, weil die Zeitanzeige nur wenige einzelne Millisekunden dauert, aber das Lichtschrankensignal am Ende doch etliche zig bis hundert Millisekunden dauern sollte.

Ich habe mal eine Zwischenzeitanzeige in Minuten und Sekunden gemacht, und die tausendstel werden dann nur bei der Endzeit mit ausgegeben. Zum Ausgleich habe ich die Ausgabe auf "Serial" aus dem Programm gestrichen, die Ausgabe erfolgt nun nur noch auf LCD:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Für Sainsmart LCD Keypad Shield

#define STARTLICHTSCHRANKE A1  // Lichtschranke zum Starten der Zeit
#define STOPPLICHTSCHRANKE A2  // Lichtschranke zum Stoppen der Zeit
#define UNTERBRECHUNGSPEGEL HIGH // welcher Pegel signalisiert eine Unterbrechung der Lichtschranke?
#define INPUTTYPE INPUT_PULLUP


void setup() {
  lcd.begin(16,2);
  lcd.print("Messbereitschaft");
  pinMode(STARTLICHTSCHRANKE,INPUTTYPE);
  pinMode(STOPPLICHTSCHRANKE,INPUTTYPE);
  delay(10);
}

static inline void showtime(long zeit, boolean endzeit)
{
  char buf[17];
  int minuten=zeit/1000/60;
  int sekunden=(zeit/1000)%60;
  int tausendstel=zeit%1000;
  if (endzeit)
    snprintf(buf,sizeof(buf),"%2d:%02d,%03d",minuten,sekunden,tausendstel);
  else  
    snprintf(buf,sizeof(buf),"%2d:%02d",minuten,sekunden);
  lcd.setCursor(6,0);
  lcd.print(buf);
  
}

void loop() {
  while (digitalRead(STARTLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) ; // warten auf Unterbrechung der Start-Lichtschranke
  unsigned long startZeit=millis(); // Jetzt wurde gestartet
  lcd.clear();
  lcd.print("Zeit:");
  while (digitalRead(STOPPLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) showtime(millis()-startZeit, false); // warten auf Unterbrechung der Stopp-Lichtschranke
  showtime(millis()-startZeit,true); // Endzeit anzeigen
  while(1); // Endlosschleife - Warten auf Reset
}

Hmmm, mit diesem Sketch wird die Messung mit der 1. LS gestartet und nach 4 ms wieder beendet.

tilloriemer:
Klappt wunderbar.

Dass Zeiten über 60 Sekunden in der Form "m:ss,xxx" angezeigt werden?

Ja, genau das: mm:ss:xxx

Kann man die Zeitanzeige während der Messung einblenden?

Hattest du meinen Sketch mal umgebaut auf deine Thematik? Dort ist die Ausgabe der Zeitmessung mm:ss:xxx. Angezeigt wird dort die genaue ms aber auch erst beim Ende. Weil das sonst keiner erkennt. Jedoch kann man es Testweise versuchen, dass Display alle 100ms anzusteuern.

tilloriemer:
Hmmm, mit diesem Sketch wird die Messung mit der 1. LS gestartet und nach 4 ms wieder beendet.

Ich wüßte nicht, was jetzt anders sein soll.
Am Sketch kann ich nichts erkennen, was da anders laufen soll, außer dass jetzt zwischendurch das LCD ständig aktualisiert wird.

Entweder hast Du doch noch kein sauberes Signal zu fassen, oder eines, dass durch die geringe elektromagnetische Abstrahlung des LCDs während der Aktualisierung bereits kippt.

Oder es hapert an der Stromversorgung.
Ziehst Du für Dein Lichtschranken-Modul Strom aus dem 5V Pin des Arduino?
Wenn ja: Wieviel Milliampere saugst Du da denn für die Lichtschranken ab?

Es reicht schon, wenn die Sekunden laufen oder irgendwas sich bewegt (!!!), damit die DAUs später sehen, dass die Messung läuft und nicht unnötig resetten.

Die Lichtschranke hat eine separate Versorgung mit 9V am Sender, der Empfänger hängt am Arduino und zieht 6,5 mA.

tilloriemer:
der Empfänger hängt am Arduino und zieht 6,5 mA.

Das ist wenig und sollte völlig problemlos sein.

Jetzt frage ich mich, warum kippt das Signal der STOPPLICHTSCHRANKE, wenn während des Wartens das LCD ständig aktualisiert wird. Das ist mir unerklärlich.

Ändert sich etwas, wenn Du die Deklaration der Ausgabefunktion änderst von

static inline void showtime(long zeit, boolean endzeit)

in

void showtime(long zeit, boolean endzeit)

?