Forum: Mikrocontroller und Digitale Elektronik Eingang Zeit versetzt einschalten


von FABIAN M. (boogeymann)


Lesenswert?

Moin,

ich habe einen arduino UNO und folgenden CODE:
1
#include <LiquidCrystal.h>
2
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Für Sainsmart LCD Keypad Shield
3
4
#define STARTLICHTSCHRANKE A1  // Lichtschranke zum Starten der Zeit
5
#define STOPPLICHTSCHRANKE A2  // Lichtschranke zum Stoppen der Zeit
6
#define UNTERBRECHUNGSPEGEL LOW // welcher Pegel signalisiert eine Unterbrechung der Lichtschranke?
7
#define UNTERBRECHUNGSPEGEL1 LOW
8
9
10
void setup() {
11
  lcd.begin(16,2);
12
  lcd.print(" <Ball>");
13
  pinMode(STARTLICHTSCHRANKE,INPUT);
14
  pinMode(STOPPLICHTSCHRANKE,INPUT);
15
}
16
17
void showtime(long zeit, boolean endzeit)
18
{
19
  static int lastSecond=-1;
20
  char buf[17];
21
  int sekunden=zeit/1000;
22
  if (sekunden==lastSecond && !endzeit) return; // keine Aktualisierung notwendig
23
  lastSecond=sekunden;
24
  int tausendstel=zeit%1000;
25
  int minuten=sekunden/60;
26
  sekunden=sekunden%60;
27
  if (endzeit)
28
    snprintf(buf,sizeof(buf),"%2d:%02d,%03d",minuten,sekunden,tausendstel);
29
  else 
30
    snprintf(buf,sizeof(buf),"%2d:%02d",minuten,sekunden);
31
  lcd.setCursor(6,0);
32
  lcd.print(buf);
33
}
34
35
36
void loop() {
37
  while (digitalRead(STARTLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) ; // warten auf Unterbrechung der Start-Lichtschranke
38
  unsigned long startZeit=millis(); // Jetzt wurde gestartet
39
  lcd.clear();
40
  lcd.print("Zeit:");
41
  while (digitalRead(STOPPLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL1) showtime(millis()-startZeit, false); // warten auf Unterbrechung der Stopp-Lichtschranke
42
  showtime(millis()-startZeit,true); // Endzeit anzeigen
43
  while(1); // Endlosschleife - Warten auf Reset
44
}

Ich habe hier EINE Lichtschranke die ein Relai schaltet (NUR EIN Relai)
Wie bekomme ich das hin das wenn bei Startlichtschranke ein HIGH kommt 
das der andere HIGH für STopplichtschranke erst in 5 Sekunden aktiv wird 
?

Momentan ist es so wenn ich einen Ball durch die Lichtschranke rolle, 
dass das Relai natürlich Schließer und Öffner aktiviert. Ist ja auch so 
weit ok ich möchter das Relai aber quasi für STart und 
stopplichtschranke verwenden ?

: Verschoben durch User
von Karl H. (kbuchegg)


Lesenswert?

FABIAN M. schrieb:

> Momentan ist es so wenn ich einen Ball durch die Lichtschranke rolle,
> dass das Relai natürlich Schließer und Öffner aktiviert. Ist ja auch so
> weit ok ich möchter das Relai aber quasi für STart und
> stopplichtschranke verwenden ?

Indem das Programm 5 Sekunden lang nach der Aktivierung der 
Startlichtschranke schlicht und ergreifend einfach nichts tut ausser die 
Zeit zu verkünden?

d.h im Grunde dasselbe wie hier
1
  while (digitalRead(STOPPLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL1) showtime(millis()-startZeit, false); // warten auf Unterbrechung der Stopp-Lichtschranke
nur dass die while Schleife nicht durch die Lichtschranke verlassen 
werden kann, sondern erst dann, wenn 5 Sekunden um sind?
Man könnte auch die 5 Sekunden Regel mit in die bisherige Bedingung 
einnehmen. Solange
a) nicht 5 Sekunden vergangen sind
b) oder die Lichtschranke noch nicht ausgelöst hat
mache ....
Macht genau dasselbe wie eine eigene 5 Sekunden schleife. In Abwandlung 
könnte man sagen: Du kommscht da nischt raus!

: Bearbeitet durch User
von Fabian (Gast)


Lesenswert?

Hamm
Ne ich möchte den Ball durchrollen mir schnappen und wieder durchrollen 
und dann die Zeit nehmen.

Momentan ist es aber so, dass die Lichtschranke bei durchrollen 2 mal 
schaltet und dem nach die Zeit startet aber nach 4 Millisekunden wieder 
stoppt weil das relai schaltet.
Ich möchte den Ball durchrollen dann kommt ein high Signal egal wie oft 
das relai einen Ausgang gibt.

Nach 5 Sekunden möchte ich das gleiche bei stoppen der zeit

von Karl H. (kbuchegg)


Lesenswert?

Fabian schrieb:
> Hamm
> Ne ich möchte den Ball durchrollen mir schnappen und wieder durchrollen
> und dann die Zeit nehmen.

Hab ich dann schon richtig verstanden.

> Momentan ist es aber so, dass die Lichtschranke bei durchrollen 2 mal
> schaltet und dem nach die Zeit startet aber nach 4 Millisekunden wieder
> stoppt weil das relai schaltet.

Logisch. Weil die Lichtschranke ja immer noch unterbrochen ist. Dein 
Programm beschöftigt sich ja nicht mit dem Wechsel des Zustands der 
Lichtschranke, sondern damit ob der Strahl unterbrochen ist oder nicht. 
Wenn du in einem Zeitabstand von 1 Millionstel Sekunde nach der 
Lichtschranke siehst, dann ist die selbstverständlich immer noch 
unterbrochen. So schnell rollt dein Ball nicht. Und auch ein Relais 
schaltet nicht so schnell. Du scheinst ein wenig zu unterschätzen, wie 
schnell dein Arduino eigentlich ist. Für den sind 10 Millionstel 
Sekunden ein Klacks. In der Zeit arbeitet der rund 100 Befehle ab! Und 
wir reden da von Millionstel und noch nicht einmal von Millisekunden.

Du hast also 2 Möglichkeiten.
Entwederr sagst du: ist mir wurscht, wenn die Lichtschranke noch 
unterbrochen ist, 5 Sekunden sind noch nicht vergangen, also kann die 
festgestellte Unterbrechung noch nicht die richtige sein.
Oder aber du könntest dir auch sagen:
Na ja. Unterbrechen ist ja schön und gut. Aber nachdem der Ball 
durchgerollt ist, muss die Lichtschranka ja auch irgendwann wieder nicht 
unterbrochen sein. Darauf könnte man warten. Und erst dann die nächste 
Unterbrechung ist die, die dann wieder zählt.

: Bearbeitet durch User
von FABIAN M. (boogeymann)


Lesenswert?

ich glaub ich steh auf dem Schlauch :(
Könntest du das in einem Code ausdrücken ;-)

von Karl H. (kbuchegg)


Lesenswert?

1
...
2
  while ( millis() - startZeit < 5000    // noch keine 5 Sekunden vergangen?
3
          ||                             // oder
4
          digitalRead( STOPPLICHTSCHRANKE) != UNTERBRECHUNGSPEGEL1 )  // die Lichtschranke hat
5
                                          // (noch) nicht ausgelöst
6
  {
7
    showtime( millis()-startZeit, false); //  -> zeige einfach nur die Zeit an
8
                                          //  und ansonsten mach gar nichts
9
  }
10
....


"Oder" ist das Zauberwort.
Deine Lichtschranke kann machen was sie will. Solange
1
    .... millis() - startZeit < 5000 ....
erfüllt ist, kommt das Programm aus dieser while Schleife nicht raus. 
Dieser Teil der Bedingung regelt also, dass der Code in den ersten 5 
Sekunden völlig unabhängig davon ist, was die Lichtschranke macht. Für 
mindestens 5 Sekunden verbleibt der Code auf jeden Fall in der 
while-Schleife. Und erst danach (wenn die erste Teilbedingung nicht mehr 
erfüllt ist) hängt es davon ab, wie die Lichtschranke steht, ob die 
Schleife weiter macht, oder ob sie abgebrochen wird.

Man hätte es auch so schreiben können
1
  ....
2
  while (digitalRead(STARTLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) ; // warten auf Unterbrechung der Start Lichtschranke
3
  unsigned long startZeit=millis(); // Jetzt wurde gestartet
4
  lcd.clear();
5
  lcd.print("Zeit:");
6
7
  // die ersten 5 Sekunden interessiert uns die Lichtschranke nicht
8
  // einfach nur die Zeit anzeigen
9
  while (milis()-startZeit < 5000)
10
    showtime(millis()-startZeit, false);
11
12
  // und erst jetzt hat die Lichtschranke wieder was zu sagen
13
  while (digitalRead(STOPPLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL1)
14
    showtime(millis()-startZeit, false);
15
16
  showtime(millis()-startZeit,true); // Endzeit anzeigen
17
  ....

Man könnte auch nicht auf eine fixe Verzögerung von (beispielsweise) 5 
Sekunden setzen, sondern sich sagen: Ok, nachdem die Lichtschranke das 
erste mal ausgelöst hat, warte ich im Programm darauf, dass sie wieder 
abfällt.
1
  ....
2
  while (digitalRead(STARTLICHTSCHRANKE)!=UNTERBRECHUNGSPEGEL) ; // warten auf Unterbrechung der Start Lichtschranke
3
  unsigned long startZeit=millis(); // Jetzt wurde gestartet
4
  lcd.clear();
5
  lcd.print("Zeit:");
6
7
  // die Lichtschranke hat angezogen. Jetzt muss sie erst mal wieder frei werden
8
  // ehe dann die nächste Unterbrechung wieder zählt
9
  while (digitalRead(STOPPLICHTSCHRANKE) == UNTERBRECHUNGSPEGEL1 )
10
    showtime(millis()-startZeit, false);
11
12
  // und erst jetzt hat die Lichtschranke wieder was zu sagen
13
  // wenn sie jetzt wieder anzieht, dann gilt das als 2.te Unterbrechung
14
  while (digitalRead(STOPPLICHTSCHRANKE) != UNTERBRECHUNGSPEGEL1)
15
    showtime(millis()-startZeit, false);
16
17
  showtime(millis()-startZeit,true); // Endzeit anzeigen
18
  ....
Viele Wege führen nach Rom. Aber wenn du alle 10 Sekunden das Licht im 
Haus gegenüber beobachtest und der Nachbar wegen Behinderung das Licht 
nur alle  3 Minuten ein bzw. aus schalten kann, dann wird es eben so 
sein, dass du viele male hintereinander das Licht als eingeschaltet 
sehen wirst, einfach deswegen weil du öfter hinsiehst als der Nachbar 
schalten kann. Willst du also am Abend die Anzahl wissen, wie oft der 
eingeschaltet hat, dann musst du jeweils abwarten, bis er nach einem 
Einschalten wieder ausgeschaltet hat, ehe du beim nächsten mal, wenn du 
das Licht brennen siehst, zu deinem Zähler 1 dazuzählst.
Du musst lernen zwischen Zuständen 'Licht IST eingeschaltet', 
'Lichtschranke IST angezogen', 'Lichtschranke IST abgefallen' und 
Vorgängen 'Licht WURDE eingeschaltet', 'Lichtschranke HAT geschlossen', 
'Lichtschranke HAT geöffnet' zu unterscheiden. Mittels digitalRead 
stellst du den aktuellen Zustand fest! Daraus musst du dir eine 
Strategie entwickeln, wie du Vorgänge erkennen kannst. Das kann durch 
einen vorher nachher Vergleich geschehen, das kann aber auch sein, in 
dem du die Reihenfolge der Zustände (und zwar alle!) im Vorhinein kennst 
und das Programm darauf trimmst, diese Reihenfolge zu überwachen.
Du willst nicht wissen, wie lange die Lichtschranke unterbrochen war. 
Das wäre die Feststellung wie lange ein bestimmter Zustand 
(Lichtschranke unterbrochen) angedauert hat. Du willst wissen, wie lange 
es gedauert hat von einem Vorgang (die UNterbrechung) bis zum nächsten 
Vorgang (erneute Unterbrechung). Dazwischen muss aber eben eine gewisse 
Mindestzeit liegen oder aber: dazwischen muss die Lichtschranke 
logischerweise auch einmal nicht unterbrochen sein. Und auch dieses 
Nicht-Unterbrochen-sein ist ein Zustand, der zwangsweise zwischendurch 
einmal auftreten muss, damit die Sequenz insgesamt richtig ist.

Jetzt mal ganz davon abgesehen, dass der ganze Programmaufbau an sich so 
ist, wie man es nicht macht.

: Bearbeitet durch User
von FABIAN M. (boogeymann)


Lesenswert?

Ich danke dir ganz hezlich fü die tolle und ausführliche Erklärung!!!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.