Guten Tag liebe Community,
ich habe mit Hilfe der Software Tinkercas eine Schaltung erstellt bei
der ich mit Hilfe eines Arduino Uno die Zeitdifferenz zwischen zwei
Rechtecksignalen messen möchte. Jedoch klappt es bei mir nicht. Ich habe
in etlichen Foren nach Lösungen gesucht und versucht ähnliche Fälle bei
meinem Problem anzuwenden. Jedoch ohne Erfolg. Kann mir einer sagen, was
ich da Falsch mache ? Ich generiere mit zwei Drucktaster Signale.
Zunächst klicke ich auf den ersten Drucktaster und danach auf den
zweiten und möchte "einfach nur" die Zeitdifferenz messen. Ich habe auch
nichts in Richtung Interrupt gemacht, da ich völliger Anfänger bin. Kann
mir jemand sagen was da nicht stimmt ?
Hallo Klaus,
danke für deine Antwort. Ich habe es geändert, jedoch funktioniert es
trotzdem nicht. Es wird mir nur ne 0 immer angezeigt und ab und zu ne
"4294967295".
Na, das erste Proramm misst ja garnichts, sondern kopiert nur den
Zustand der Tasten an die beiden Ausgänge.
Das zweite misst durchaus den Abstand und soll ihn in Millisekunden
anzeigen.
Wegem dem delay(100) allerdings nur mit 100ms Auflösung.
Lass das delay doch mal ganz weg.
Oh, und es sollte wohl eher
1
dauer = ende - start;
heissen. Sonst wird dauer negativ, was macht die Simulation da bei einer
unsigned-Variablen?
Sven P. schrieb:> Ich generiere mit zwei Drucktaster Signale
Zwei Drucktaster n , Mehrzahl!
Der angehängte Programmkot beinhaltet keinerlei Zeiten, der schaltet
lediglich zwei LEDs und auch das erst, wenn man ihn korrigiert.
Vielen Danke für die Rückmeldungen,
ich habe das Delay komplett weggelassen und die Rechnung korrigiert.
Jedoch erhalte ich andauern die Zahl "0". Also es wird keine Differenz
angezeigt. Hier mein aktueller Code:
Sven P. schrieb:> while(buttonState1 == HIGH);> start = millis();>> while(buttonState2 == HIGH);> ende = millis();
Ist WHILE denn hier der richtige Befehl?
Anfänglich hattest Du doch IF verwendet.
Kannst Du mit der Oberfläche nicht debuggen?
Dann geh doch mal step für step den Code durch.
mfg Klaus
Sven P. schrieb:> while(buttonState1 == HIGH);
^ Semikolon muss weg
> start = millis();>> while(buttonState2 == HIGH);
^ hier ebenso
> ende = millis();
Ich finde das mit Klammersyntax besser und eindeutiger:
while(buttonState1 == HIGH)
{
start = millis();
}
Sven P. schrieb:> Jedoch erhalte ich andauern d die Zahl "0".
Was würde ich jetzt tun:
Ich baue serial.print(start)
und
serial.print(ende) in die Hauptschleife ein und gucke, ob die sich
ändern.
Wenn nicht, baue ich weitere Ausgaben, ob die Taster überhaupt erkannt
werden, z.B. auf Deine zwei LEDs.
Programmieren lebt davon, dass Du eigene Strategien entwickelt,
Fehlfunktionen einzugrenzen.
Klaus R. schrieb:> Ist WHILE denn hier der richtige Befehl?
Ich bezweifele es.
GEKU schrieb:> == HIGH
ist die Polarität der Taster richtig? Sonst hätte er in der While
Schleife auf Ewig hängen bleiben müssen!
Wenn nicht probiert != HIGH oder == LOW
Klaus R. schrieb:>> Sonst hätte er in der While>> Schleife auf Ewig hängen bleiben müssen!>> Natürlich, also unbedingt IF verwenden, mit {}.
Wenn ich das richtig verstanden habe, bleibt while solange auf Taste1
hängen, bis diese aktiv wird. Danach hängt while in Taste2 fest, bis
auch diese betätigt wird.
Könnte Sinn geben, je nachdem, was man erreichen will.
Das würde man zügig heraus bekommen, wenn man Tasten und Timer serial
ausgeben lässt, so furchtbar komplex ist das Programm ja mal nicht.
Vielen Danke für die zahlreichen Antworten. So wie ich es nun verstanden
habe, soll ich die while-Schleife durch eine If-Schleife ersetzten. Das
habe ich gemacht. Sobald ich den ersten Taster (auf Pin 2) drücke
erscheinen die Zahlen "4294967101" und anschließend habe ich 5 Sekunden
gewartet bis ich den zweiten Taster (auf Pin 3) gedrückt habe. Ich würde
nun erwarten, dass irgendwas im Bereich von "5000" angezeigt wird.
Jedoch kommt ein vollkommen anderer Wert raus, wie in der Abbildung zu
sehen.
Klaus R. schrieb:> Ich denke Du verwendest WHILE fehlerhaft.
Die Frage ist, ob er die ArduinoLoop nutzen , oder in dieser eine
eigene Loop verwenden will.
Im ersten Fall:
1
voidloop()// rotiert ständig in loop
2
{
3
if(digitalRead(2)==HIGH)// Schnappschuss wenn Taste 1 gedrückt wurde
4
start=millis();
5
6
if(digitalRead(3)==HIGH)// Schnappschuss wenn Taste 2 gedrückt wurde
7
{
8
ende=millis();
9
dauer=ende-start;
10
Serial.println(dauer);
11
}
12
}
Im zweiten Fall:
1
voidloop()
2
{
3
while(digitalRead(2)==LOW);// wartet in der lokalen Schleife bis Taste 1 gedrückt wurde
4
start=millis();
5
6
while(digitalRead(3)==LOW);// wartet in der lokalen Schleife bis Taste 2 gedrückt wurde
7
ende=millis();
8
dauer=ende-start;
9
Serial.println(dauer);
10
11
}// loop wird fortgesetzt, nachdem Taste 1 und 2 gedrückt worden ist
Sven P. schrieb:> void loop()> {> if(digitalRead(2)==HIGH)> {> start = millis();> }>> if(digitalRead(3)==HIGH)> {> ende=millis();> }>> dauer = start - ende;>> Serial.println(dauer);>> }
So geht es nicht.
So sollte es gehen:
1
intCondition=0;
2
//Folgezeile Kommentar entfernen, wenn bei ungedrücktem Taster HIGH am Eingang
3
//Condition = HIGH;
4
//Folgezeile Kommentar entfernen, wenn bei ungedrücktem Taster LOW am Eingang
5
//Condition = LOW;
6
7
while(digitalRead(2)==Condition){}
8
start=millis();
9
while(digitalRead(3)==Condition){}
10
ende=millis();
Kurze Erläuterung:
Er bleibt in der 1. while Schleife hängen bis der Taster gedrückt wird.
Drücken des Tasters unterbricht die while Schleife. Dadurch wird die
Variable start gesetzt und er bleibt in der 2. while Schleife hängen.
Hier gleiche Funktion wie in der 1. Schleife. Allerdings wird hier beim
Beenden der Schleife ende gesetzt.
Anschließend käme Deine Berechnung der Differenz und Ausgabe des
Ergebnisses. Das delay kannst Du weg lassen. Danach bleibt er dann
wieder in der 1. Schleife hängen.
Die Variable Condition am besten global definieren und in setup() mit
dem entsprechenden Wert belegen. Man braucht sie auch nicht wenn man den
passenden Wert in der while-Schleife einträgt.
Zeno schrieb:> Die Variable Condition am besten global definieren und in setup() mit> dem entsprechenden Wert belegen. Man braucht sie auch nicht wenn man den> passenden Wert in der while-Schleife einträgt.
Was soll der Wert in einer Variablen, die sowieso im Programm nicht
geändert werden kann. Ein #define für den Präprozessor ist da deutlich
zielführender und universeller, auch wenn man den Wert in der Bedingung
für den while-Block direkt festlegen möchte, was hier defacto der Fall
ist.
Wolfgang schrieb:> Was soll der Wert in einer Variablen, die sowieso im Programm nicht> geändert werden kann. Ein #define für den Präprozessor ist da deutlich> zielführender und universeller, auch wenn man den Wert in der Bedingung> für den while-Block direkt festlegen möchte, was hier defacto der Fall> ist.
Es führen viele Wege nach Rom und ja man kann auch #define verwenden.
Auch wenn Dein Post mal wieder der typische C-Zeigefinger "Das macht man
nicht so", der von mir hin geschriebene Code wird funktionieren, sogar
wenn man das Ganze in loop() rein schreibt, auch wenn das nicht
sonderlich elegant wäre.
Ich habe es eigentlich nur zur Erklärung eingefügt, weil sich es sich so
leichter schreiben ließ. Ich denke mal das es für den TO so auch
verständlicher ist.
Das man es auch im while machen kann hatte ich ja geschrieben.
Zeno schrieb:> Auch wenn Dein Post mal wieder der typische C-Zeigefinger "Das macht man> nicht so" ...
Sei beruhigt, von C habe ich nicht sonderlich viel Ahnung und enthalte
mich gewöhnlich bei solchen Stilfragen. Aber manche Dinge fallen selbst
mir als Quereinsteiger auf. ;-)
Danke für eure Hilfe, der Code funktioniert nun und es zähl fleißig die
Differenz. Jedoch zählt es sie falsch. Nach 10 sek. ist die Anzeige
gerade mal bei "2100 ms". Kann mir einer sagen woran das liegt ? wenn
"millis()" Millisekunden entsprechen, so müsste es ja bei "10000" sein.
Sven P. schrieb:> Danke für eure Hilfe, der Code funktioniert nun und es zähl fleißig die> Differenz. Jedoch zählt es sie falsch.
Das Programm zählt nicht die Differenz, sondern es holt sich bei den
Tastenereignissen als Timestamp den Zählerstand vom
Millisekunden-Systemtimer. Die Dauer wird erst später ausgerechnet.
Prüfe also erstmal die Timestamps unter Berücksichtigung der Tatsache,
dass der Zähler auch mal überlaufen kann.
Zeno schrieb:> Es führen viele Wege nach Rom
Bei dem Vorgehen, landet er aber nicht in Rom, sondern kommt nur bis
Castrop-Rauxel, weil er in einer Schleife überlaufende Werte erwischt.
Damit wird er zwangsläufig auch negative Zeiten heraus bekommen.
Dann kommt die Frage hoch, ob da die Relativitätstheorie zugeschlagen
hat!
Kai D. schrieb:> Damit wird er zwangsläufig auch negative Zeiten heraus bekommen.
Wie sollen bei Verrechnung von unsigned Variablen negative Zahlen heraus
kommen?
Sven P. schrieb:> Danke für die Antwort, aber leider verstehe ich nicht was du meinst :(
Gehe Stück für Stück bei der Fehlersuche vor:
Prüfe erstmal die Werte für start und ende auf Plausibilität
Kai D. schrieb:> Bei dem Vorgehen, landet er aber nicht in Rom, sondern kommt nur bis> Castrop-Rauxel, weil er in einer Schleife überlaufende Werte erwischt.> Damit wird er zwangsläufig auch negative Zeiten heraus bekommen.>> Dann kommt die Frage hoch, ob da die Relativitätstheorie zugeschlagen> hat!
Nö er muß nur die Variablen start und ende passend definieren. Die
Funktion millis() liefert unsigned long zurück, d.h. es kommt erst nach
1193 Stunden bzw. 49 Tagen zum Überlauf. Innerhalb dieser Zeit wird er
wohl beide Taster gedrückt haben.
Also die Variablen auf unsigned long setzen.
Den Überlauf kann relativ einfach abfangen, wenn man prüft ob start >
ende ist. Wenn dem so ist, dann muß etwas anders die Differenz
berechnen. Die Differenz wäre nach einem Überlauf 4294967296-start+ende.
Zeno schrieb:> Also die Variablen auf unsigned long setzen.
Was meinst du wohl, was hier passiert:
Sven P. schrieb:> unsigned int long start;> unsigned int long ende;> unsigned int long dauer;Zeno schrieb:> Den Überlauf kann relativ einfach abfangen, wenn man prüft ob start >> ende ist.
Warum willst du beim Überlauf des millis()-Timers irgendetwas abfangen?
Mir scheint, da fehlen ein paar Grundlagen.
Rechne mal mit unsigned long Arithmetik aus, was bei der Rechnung
1
unsignedlongintt_start;
2
unsignedlongintt_end;
3
unsignedlongintt_delta;
4
...
5
t_start=4294967286;// 0xffffffF6
6
t_end=4;// 0x00000004
7
t_delta=t_end-t_start;// -> 0x0000000E
heraus kommt.
Die Differenz wird richtig als 14 berechnet.
Wolfgang schrieb:> Was meinst du wohl, was hier passiert:>> Sven P. schrieb:>> unsigned int long start;>> unsigned int long ende;>> unsigned int long dauer;
Hatte ich übersehen - wirgendwie nur auf long.
Wolfgang schrieb:> Mir scheint, da fehlen ein paar Grundlagen.
Mir schein Du bist ein biss'l arrogant. Ein einfacher Hinweis das es
auch so funktioniert wäre völlig ausreichend gewesen.
Rein mathematisch würde das nicht funktionieren. Von einer natürlichen
Zahl kannst Du keine größere natürliche Zahl abziehen, das wäre ja
negativ und das kennt dieser Zahlenbereich nicht. Bei ganzen Zahlen
ginge es zwar aber es käme das falsche heraus und dazu noch negativ.
Allerdings gibt es in der Mathematik auch keine Begrenzung des
Zahlenbereiches.
Das das hier richtig umgesetzt wird war mir bisher nicht bewußt. Ich
habe es bisher immer so gemacht wie beschrieben. Funktioniert auch ist
halt nur etwas umständlicher.
Zeno schrieb:> Rein mathematisch würde das nicht funktionieren.
Natürlich funktioniert das auch mathematisch. Man muss nur die
Rechenregeln beachten. Beim Datentyp unsigned long gilt
Zeno schrieb:> Rein mathematisch würde das nicht funktionieren.
Doch.
> Von einer natürlichen> Zahl kannst Du keine größere natürliche Zahl abziehen, das wäre ja> negativ
Das ist korrekt. Nur leider völlig am Problem vorbei. Computer rechnen
nämlich nicht mit natürlichen Zahlen (dazu müssten sie unendlich breite
Register haben), sondern in einem zyklischen Zahlenraum, der eine
Teilmenge entweder der natürlichen oder der ganzen Zahlen umfaßt.
Und in solchen zyklischen Zahlenräumen gelten andere Rechenregeln. Jeder
Programmierer sollte diese aus dem Effeff beherrschen, sonst fällt er
früher oder später auf die Schnauze.
Wolfgang schrieb:> Wie sollen bei Verrechnung von unsigned Variablen negative Zahlen heraus> kommen?
Na, so:
Zeno schrieb:> Rein mathematisch würde das nicht funktionieren. Von einer natürlichen> Zahl kannst Du keine größere natürliche Zahl abziehen, das wäre ja> negativ und das kennt dieser Zahlenbereich nicht.
Doch kann man, wie die Antwort zeigte:
Wolfgang schrieb:> Natürlich funktioniert das auch mathematisch. Man muss nur die> Rechenregeln beachten
Wobei:
Zeno schrieb:> Den Überlauf kann relativ einfach abfangen
Muss aber auch erst einmal getan werden. Erst mal gibt es einen
Unterlauf.