Hey ich hab da mal ein Problem ich hab ein Programm geschreiben um mit
den HC-SR 04 Entfernungen auszumessen. Das klappt auch super. Nun hab
ich gemerkt das ab und zu mal in der Messung ein wert aus der reihe tanz
und dachte mir ich mach 2 Messungen mehr und zieh den höchsten und
geringsten wert vom Mittelwert ab. Da ganze funktioniert auch, aber ich
bekomm beim Build immer 2 Warnings und 2 Messages.
kann mir vielleicht mal erklären warum ich die bekomme und was eine
abhilfe wäre:
1
voidHC_SR_04()
2
{
3
unsignedchari,k;
4
unsignedshortTimedifferenz,Ergebnis=0;
5
unsignedshortMessung[8];
6
unsignedshortmin=65535,max=0;
7
for(i=0;i<=9;i++)
8
{
9
wiederholung:;
10
complete_hc=0;
11
PORTB|=(1<<HC_TRIGGER);
12
_delay_us(40);
13
PORTB&=~(1<<HC_TRIGGER);
14
while(complete_hc==0)
15
;
16
if(Timestart==Timestop)
17
{
18
Error();
19
gotowiederholung;
20
}
21
elseif(Timestart<Timestop)
22
{
23
Timedifferenz=(Timestop-Timestart);
24
}
25
elseif(Timestart>Timestop)
26
{
27
Timedifferenz=(Timestop-Timestart+65535);
28
}
29
else
30
{
31
Error();
32
gotowiederholung;
33
}
34
35
36
Messung[i]=Timedifferenz;
37
38
39
}
40
41
for(k=0;k<=9;k++)
42
{
43
Ergebnis=Ergebnis+Messung[k];
44
if(Messung[k]<=min)
45
{
46
min=Messung[k];
47
}
48
if(Messung[k]>=max)
49
{
50
max=Messung[k];
51
}
52
53
}
54
Ergebnis=Ergebnis-(min+max);
55
Ergebnis_HC=Ergebnis/8;
56
if(error_counter!=0)
57
{
58
error_counter--;
59
}
60
61
}
das ist der Code.
Und hier die Fehler :
(247,31): warning: iteration 8u invokes undefined behavior
[-Waggressive-loop-optimizations]
Ergebnis = Ergebnis+ Messung[k];
^
(245,2): info: containing loop
for (k=0;k<=9;k++)
^
(240,14): warning: iteration 8u invokes undefined behavior
[-Waggressive-loop-optimizations]
Messung[i] = Timedifferenz;
^
(211,2): info: containing loop
for (i=0;i<=9;i++)
^
Sebi schrieb:> (247,31): warning: iteration 8u invokes undefined behavior> [-Waggressive-loop-optimizations]> Ergebnis = Ergebnis+ Messung[k];
k geht bis 9, Messung aber nur bis 7. Das andere dürfte was ähnliches
sein.
Aus dem Grund verteilt man solche Zahlen besser nicht auf das ganze
Programm sondern definiert sich einmal eine symbolische Konstante und
verwendet die an allen Stellen, so dass man immer nur genau eine Stelle
anpassen muss, wenn man die Größe mal ändern möchte.
Rolf M. schrieb:> Aus dem Grund verteilt man solche Zahlen besser nicht auf das ganze> Programm sondern definiert sich einmal eine symbolische Konstante und> verwendet die an allen Stellen, so dass man immer nur genau eine Stelle> anpassen muss, wenn man die Größe mal ändern möchte.
oder verwendet countof(), um sicher zu gehen, dass beides
zusammengehört.
Und vom goto würd ich mich auch verabschieden. So passieren nämlich auch
solche Fehler wie oben: Das erste if und das else am Schluss
unterscheiden sich nicht:
Sebi schrieb:
Dass dein Array Messung[] zu klein ist hast du jetzt gelernt.
Nun zu den anderen Problemen deines Programmes:
a)
1
if(Timestart==Timestop)
2
{
3
Error();
4
gotowiederholung;
5
}
6
elseif(Timestart<Timestop)
7
{
8
Timedifferenz=(Timestop-Timestart);
9
}
10
elseif(Timestart>Timestop)
11
{
12
Timedifferenz=(Timestop-Timestart+65535);
13
14
// macht das gleiche wie:
15
// Timedifferenz = Timestop-Timestart-1;
16
// also nicht wirklich hilfreich
17
}
18
else
19
{
20
// warum diese zusätzliche else condition?
21
// das wäre der gleiche Fall wie der erste:
22
// if (Timestart == Timestop)
23
24
Error();
25
gotowiederholung;
26
}
Da also
Timedifferenz = (Timestop-Timestart+65535)
eh falsch ist, kannst du die ganze Berechnung auf das hier
runterbrechen:
1
if(Timestart==Timestop)
2
{
3
Error();
4
gotowiederholung;
5
}
6
else
7
Timedifferenz=Timestop-Timestart;
Selbst bei einem Überlauf zwischen Timestop und Timestart kommt das
richtige Ergebnis heraus.
Bei zwei Überläufen allerdings nicht mehr, und das ist eventuell auch
der Grund für deine seltsamen Ausreißer.
In welchem Wertebereich befindet sich denn Timedifferenz üblicherweise?
b)
Sebi schrieb:> und dachte mir ich mach 2 Messungen mehr und zieh den höchsten und> geringsten wert vom Mittelwert ab.
Warum? Was soll das bringen?
Um Ausreisser herauszunehmen sortiert man üblicherweise die Messwerte
der Größe nach, und nimmt sich einen (oder mittelt ein paar Werte) aus
der Mitte des sortierten Feldes. Die Ausreisser bleiben dadurch komplett
unberücksichtigt.
c)
Ergebnis = Ergebnis+ Messung[k];
Hier addierst du 10 16-bit Werte in einer Variablen, die selbst nur
16-bit breit ist.
Das funktioniert nur, wenn die zu addierenden Werte so klein sind, dass
"Ergebnis" nicht überläuft (also im Mittel <= 6553).
Ist das sichergestellt?
d)
Ergebnis_HC = Ergebnis / 8;
Hier stimmt dann der Teiler nicht. Müsste 10 sein.
Nachtrag:
Achso, jetzt verstehe ich. Du suchst dir den kleinsten und größten Wert
und gehst davon aus, dass dies die Ausreisser sind. Daher ziehst du
diese von der Summe ab, und teilst durch 8.
Kann man hilfsweise so machen.
Trotzdem mal prüfen, ob 10 Messwerte aufaddiert ohne Überlauf in
"Ergebnis" passen.
Also der Teiler ist richtg da ich min und max aus der Rechnung nehme:
1
Ergebnis=Ergebnis-(min+max);
2
Ergebnis_HC=Ergebnis/8;
das mit den 16bit werten passt auch der max wert einer Messung liegt bei
300.
400*10 Messung sind 4000 liegt unterhalb der 65535.
Die andern tipps hab ich schon umgestzt besten dank.
mal so ne frage wie würde den der Code aussehen wenn ich 20 messungen
pro durchlauf mache und nur die 10 in der mitte zur Mittelwert Bildung
nutze?
Sebi schrieb:> mal so ne frage wie würde den der Code aussehen wenn ich 20 messungen> pro durchlauf mache und nur die 10 in der mitte zur Mittelwert Bildung> nutze?
Du musst die 20 Array-Einträge nach der Messung der Größe nach
sortieren, und nimmst aus dem sortierten Array dann die Werte 5..14.
Ich würde aber erstmal gucken, ob dein Problem mit den Ausreissern nicht
schon dadurch verschwindet, dass du dein Array groß genug machst.
Es liegt momentan ziemlich nahe, dass die letzten 2 Werte einfach nur
Müll sind, da sie momentan in anderweitig benutztem Speicher liegen.
Sebi schrieb:> das mit den 16bit werten passt auch der max wert einer Messung liegt bei> 300.
naja, wenn der Maxwert da liegt und Du "Ausreißer" hast, dann teste das
auch. Also zumindest < 400 oder so. Und m.E. auch ohne goto, also z.B.:
1
for(i=0;i<10;/*nur bei Erfolg ++ am Ende */)
2
{
3
complete_hc=0;
4
PORTB|=(1<<HC_TRIGGER);
5
_delay_us(40);
6
PORTB&=~(1<<HC_TRIGGER)
7
while(!complete_hc){}
8
Timedifferenz=(Timestop-Timestart);
9
if((Timedifferenz<1)||(Timedifferenz>400))
10
{
11
Error();
12
}
13
else
14
{
15
Messung[i++]=Timedifferenz;
16
}
17
}
statt 1 den minmalen plausiblen Wert eingeben. Wenn 0 falsch ist, wird
es 3 oder 5 vermutlich auch sein, oder?
ich gebe zu, eine vergewaltigung der for-Schleife. Aber der Preis einer
separaten inneren Schleife wäre mir in diesem Fall zu hoch. Und i-- im
Errorfall auch.
Habs jetzt geändert alles, jedoch hab ich immer noch nach ca. 15
Ergebnissen leichte ausreißer(also nach 150 Messungen). Wenn ich jetzt
ne aus 20 Messungen die 12 Aus der mitte nehme reicht da Bubblesort für
aus oder ist es für 20 Messungen zu Zeit intensiv? was wäre dann den
eine schnellere alternative ?
Sebi schrieb:> reicht da Bubblesort für aus
JA!
Wenn Du 1000 Messungen hast, kannst Du über optimierung nachdenken. Aber
nur zu:
1) Quick-Bubble-Sort ;-)
2) nur die 3 kleinsten rausfiltern und die 3 größten. Also wie bisher,
nur dann 3 mal.
3) die min- und max-Tests mit einbauen, dann sollten es noch weniger
sein.
Aber es gibt auch eine Standard-C-Funktion zum sortieren: qsort(). Die
kannst Du kaum durch eigenes basteln schlagen.
Sebi schrieb:> nach ca. 15 Ergebnissen leichte ausreißer(also nach 150 Messungen).
Du solltest Dir die Rohwerte ausgeben lassen, um zu wissen, was da
passiert.
Wenn (als Beispiel) 10 Werte im Bereich von 190 bis 210 wild verteilt
liegen, ist es etwas anderes als wenn Du manchmal auch 999 oder 1 misst.
Bei ersterem reicht die Mittelung, bei solltest Du den Fehler
korrigieren oder Kriterien zu dessen Erkennung herausarbeiten.
Achim S. schrieb:> Und m.E. auch ohne goto, also z.B.:
Ja, das goto ist hässlich.
Und Ausreisser gleich bei der Erfassung zu erkennen, und gleichzeitig
auch sicherzustellen, dass der Wertebereich für die spätere
Aufsummierung nicht überschritten wird, ist eine wirklich sehr gute
Idee.
Statt einem halben "for" fände ich dann "while" allerdings irgendwie
schöner:
1
i=0;
2
while(i<10)
3
{
4
complete_hc=0;
5
PORTB|=(1<<HC_TRIGGER);
6
_delay_us(40);
7
PORTB&=~(1<<HC_TRIGGER)
8
while(!complete_hc)
9
;
10
11
Timedifferenz=(Timestop-Timestart);
12
if((Timedifferenz<1)||(Timedifferenz>400))
13
Error();
14
else
15
Messung[i++]=Timedifferenz;
16
}
Achim S. schrieb:> 2) nur die 3 kleinsten rausfiltern und die 3 größten. Also wie bisher,> nur dann 3 mal.
Das könnte man auch so erledigen, indem man die 3 größten und die 3
kleinsten Werte im Array einfach mit 0 überschreibt.
Beim Mittelwert-bilden über das gesamte Array fallen genau diese Werte
dann also automatisch aus der Summe raus.
Das mit der while gefällt mir auch schon besser vielen Danke. Wie groß
der Ausreißer ist schau ich später mal nach gibt es für bubblesort auch
eine fertige Funktion wie für qbubblesort und in welcher h sind die den?
qsort ist nicht quick-bubblesort, sondern einiges komplizierter und
effektiver, bei größeren Datenmengen. Habe ich aber jahrelang auch
gedacht und es "eben selbst implementiert", um den Overhead der compare
Funktion zu sparen.
Quick-bubblesort ist ja nur, den inneren Zähler jedesmal 1 weniger
zählen zu lassen.
Achim S. schrieb:> Aber es gibt auch eine Standard-C-Funktion zum sortieren: qsort(). Die> kannst Du kaum durch eigenes basteln schlagen.
Doch, kann man, und zwar recht problemlos. Denn in C artet jeder
Vergleich und jeder Tausch in einen Funktionsaufruf aus, und dann auch
noch über einen Zeiger. Zudem ist Quicksort bei kleinen Listen (bis etwa
100 Elemente) langsam. Und rekursiv, was man embedded auch nicht will.
Abhilfe: man implementiert einen Shellsort mit der Sequenz nach Ciura.
Shellsort ist iterativ, in-place, bei diesen Längen schneller als
Quicksort, hat keine Pathologien, braucht keine Funktionsaufrufe.
Manche embedded-libs implementieren qsort zwar ohnehin von selber als
Shellsort, aber der Overhead durch die Funktionaufrufe bleibt.
So hab jetzt einige ratschläge befolgt. bei großen Entfernungen also
alles ab 10 cm Entfernung klappt es jetzt. jedoch schwanken die werte
bei nahen Hindernissen kleiner 10cm gerne um 2-3 cm.
Also hab jetzt ein Messobjekt 1.50m entfernt.
Ergebniss liegt zwischen 1.49 und 1.51m das ist ok da der Timer auf eine
Genauigkeit +- 1cm eingestellt ist.
Bei messungen unter 10cm hier jetzt mal 6cm habe ich Ergebnisse im
Bereich vom 3-8cm. jemand eine Idee warum?
Habs gefunden,
habe die Auflösung noch etwas erhöht auch 3.33mm Genauigkeit.
hab jetzt bei Entfernungen bis 1m eine Genauigkeit von +/-0.666cm
und bei Entfernungen von 1m bis 3m eine Genauigkeit von +/- 1.333cm
die Ungenauigkeit die ich jetzt noch hab ist dann Mathematischer Natur.
Alternativ könnte man nur die 3 max und min werte in zwei Arrays
speichern und bei jedem neuen Wert schauen ob es in das min- oder
max-Array gespeichert werden soll, oder zu der laufende Summe
hinzuaddiert.
Wenn der neue Wert zB in das max-Array gespeichert wird, wird statt der
gemessene Wert das kleinste Element aus dem max-Array zu die Summe hinzu
addiert.
z.B.
max[] = {200, 250, 300} und value = 275
Dann wird 200 zu der Summe hinzu addiert, und max[] enthält danach {250,
275, 300}.
Die min und max Arrays werden während den Messungen sortiert gehalten
(insertion sort).
Hallo,
der uC braucht eine gewisse Zeit um Anweisungen auszuführen. Diese Zeit
sollte man bei der Fehler Berechnung miteinbeziehen (Start Stop
abfrage). Bei großen Distanzen wird der Fehler klein sein. Je kleiner
die Distanz wird umso größer wird der Fehler.
ms
MCUCR|=(1<<ISC00);// prepare interrupt for low to high transition
3
4
(...)
5
6
timer_state=2;
7
PORTB|=(1<<HC_TRIGGER);
8
_delay_us(60);
9
PORTB&=~(1<<HC_TRIGGER);
10
while(timer_state>0)
11
;
und der Interrupt:
1
ISR(INT0_vect)
2
{
3
unsignedshortt=timer0;
4
5
if(timer_state==2)
6
{
7
Timestart=t;
8
MCUCR&=~(1<<ISC00);// prepare interrupt for high to low transition
9
timer_state=1;
10
}
11
elseif(timer_state==1)
12
{
13
Timestop=t;
14
MCUCR|=(1<<ISC00);// prepare interrupt for low to high transition
15
timer_state=0;
16
}
17
}
So nimmst du in deiner Interrupt routine immer direkt nach
Flankenwechsel erstmal die Zeit, ohne dass noch andere Instruktionen
verarbeitet werden müssen.
Danach entscheidest du dann, ob und was du mit dieser Zeitinformation
machst.
Das sollte die Genauigkeit verbessern.
Ja, so gehts auch. Ich würde halt nur das MCUCR Register immer in einem
definierten Zustand halten.
MCUCR ^= (1<<ISC00);
ist relativ zufällig beim allerersten mal.
Ich muss ja mal sagen, dass mir dieser Thread hier sehr gefällt.
Der Ton ist durchweg freundlich, viele nützliche Tipps von allen Seiten,
TO lernt schnell und viel, und das Ergebnis kann sich sehen lassen.
Minimal,es macht 8 Takte im Debug Modus(bei 16 Mhz) weniger fehler, bei
einem timer der sich alle 20us erhöht kann es bei dem ein oder anderen
das kippen zwischen den Ergbnissen verhindern.
An der Hardware ist der wert jetzt bei gleicher Entfernung konstant.
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
6
5
5
5
5
5
5
5
5
5
5
5
5
4
4
4
4
4
4
hier mal die Ergebniss aus der Uart in cm also keine Ausreisser mehr.
hier jetzt auch mal bei 1.495m Entfernung Schreibtisch zu Deckenhöhe:
148
148
148
148
148
149
148
148
schaut auch sehr gut aus angenommen ist der Schall bei 20 Grad Celsius
im Raum sind 20.8 Grad von daher Top.
Eine kleine frage hab ich noch:
Kann man ein Reset auch anders Ausführen, als über den WD, also über ein
direkten befehl?
im Moment hab ich das jetzt so gemacht:
1
voidRESET()
2
{
3
WDTCR|=(1<<WDE);/* WatchDog Aktivieren */
4
_delay_us(16300);/* Wartezeit bis WD-Signal benötigt, bevor WD Auslöst, um WD auszulösen und Reset durchzufuehren */
Sebi schrieb:> Minimal,es macht 8 Takte im Debug Modus(bei 16 Mhz) weniger fehler, bei> einem timer der sich alle 20us erhöht kann es bei dem ein oder anderen> das kippen zwischen den Ergbnissen verhindern.
Ah ok.
Also ein "Fehler" von 0.5us.
Auch wenn es in deinem Fall jetzt keine wirkliche Rolle spielt, würde
ich es prinzipiell so machen um die Fehlerquellen von vorneherein so
gering wie möglich zu halten.
Sebi schrieb:> Kann man ein Reset auch anders Ausführen, als über den WD, also über ein> direkten befehl?
Klar, du kannst direkt zur Resetadresse springen wenn du das unbedingt
willst.
Sebi schrieb:> Gibt es eig eine Möglichkeit das delay für den Trigger durch was anders> zu ersetzten mit selben Effekt ?
Es gibt da viele Möglichkeiten, allerdings ist das ja keine allzu
schlechte Lösung, wenn dein uC während der Messung nichts anderes tun
muss.
Allerdings fällt mir bei dieser Gelegenheit ein weiteres Problem auf:
Der Sensor kann max. 50 Messungen pro Sekunde machen.
Die Berechnung der Zeitdifferenz wird vernachlässigbar wenig Zeit
brauchen, so dass deine Abtastung u.U. viel zu schnell abläuft.
Du solltest nach der Berechnung der Zeitdifferenz also noch ein weiteres
Delay einbauen, damit die nächste Abtastung frühestens 1/50s nach der
vorherigen startet.
Als ersten Ansatz könnte man ja die Zeitdifferenz in ms umrechnen, und
dann ein weiteres Delay einfügen mit t_wait = 20ms - Zeitdifferenz(in
ms)
Vielleicht geht es technisch ja und die 50Hz sollten nicht überschritten
werden, damit das Ding nicht zu heiss wird?
Der Transducer haut unter Umständen ziemlich laute Pulse raus und möchte
dann ein wenig abkühlen.
Also hab gerade noch mal alles durchgerechnet: der Programmablauf
benötigt 72us. Die Messung für eine Entfernung von 10cm nimmt ca 600us
in Anspruch dann wäre ich bei einer Messfrequenz oberhalb von 1,5kHz
Achso, ne die 50Hz ergeben sich durch die max. zu erwartende Laufzeit.
Bei der Reichweite des Moduls von 3m sind das 17.5-18ms.
D.h. also, je näher dein Objekt ist, desto öfter kannst du abfragen.
Ergibt sich ja dann auch automatisch dadurch, dass complete_hc früher
auf 1 geht.
Ich würde es trotzdem nicht übertreiben, und auch bei nahen Objekten
eine vernünftige Zeit warten. Du hast ja auch Echos im Raum, die erstmal
abklingen sollten.
Ich hatte das mit den 50 Hz Messfrequenz auch schonmal gelesen aber hab
mir gerade das Datasheed mal angesehen. Da steht kein Limit der
Messungen drinne
Also wenn man kein Signal empfängt geht er sogar 200ms auf High damit
wären nur 5 Messungen pro sekunde möglich passt auch wenn man den
Trigger mal beim messen zuhält.
Ja, wie gesagt, das ist glaube ich eher ein theoretisches Limit, dass du
auch bis 3m mit 50Hz abtasten kannst.
Aber es könnte ein Grund für deine Ausreisser sein.
Wenn dein Hauptobjekt sagen wir mal 20cm entfernt ist, und in 30cm
Entfernung ein weiteres Objekt steht, dann misst du das 1. Echo bei
20cm.
Dann startest du direkt die nächste Messung, und der Sensor empfäng das
2. Echo der vorherigen Messung.
Das sieht dann so aus, als ob das Objekt plötzlich nur 10cm entfernt
ist.
ok das ist richtig dann müsste ich aber von der Frequenz noch weiter
runter gehen, da er zwar nur eindeutig bis 4m die echos aber keine
grenze haben. Bzw die grenze durch ihre Wellenlänge. Aber ich behalte es
mal im hinter kopf.
Vermutlich sind deswegen die 50Hz empfohlen.
Ich glaube ich muss mir mal so ein Modul bestellen. Hab grad selber Bock
damit rumzuspielen.
So richtig geil wäre ja, man würde das Modul so modifizieren, dass man
den Empfänger für eine definierte Zeit "taub" stellen kann.
Dann könnte man das 1. Echo messen, wüsste die Entfernung zum ersten
Objekt, und würde bei der 2. Messung den Empfänger so lange disablen,
bis das erste Echo vorbei ist. Dann müsste man das nächste Echo "sehen "
können, usw... Verstehste?
Eine Frage hätte ich noch: Wofür brauchst Du eigentlich die
Interrupt-Routine?
Du schaltest doch vermutlich einen Sender mit
> PORTB |= (1<<HC_TRIGGER);
oder
> PORTB &= ~(1<<HC_TRIGGER)
ein und wartest dann auf die Antwort. Warum nicht einfach plain code?
Sebi schrieb:
1
while(i<20)
2
{
3
/* einschalten (?) */
4
PORTB|=(1<<HC_TRIGGER);
5
/* Zeit Messen */
6
Timestart=timer0;
7
delay(40);
8
/* abschalten */
9
PORTB&=~(1<<HC_TRIGGER);
10
/* warten bis empfang */
11
while(...);
12
/* Ende der Zeitmessung */
13
Timestop=timer0;
14
/* wie gewohnt ... */
15
if((Timedifferenz<2)||(Timedifferenz>4000))
16
{
17
...
18
}
19
...
20
}
Wenn der Empfang schon im Delay sein darf ... na, auch das wäre einfach.
Eventuell macht es sogar Sinn, den Timer neu zu starten für jede
Messung, dann entfällt die Subtraktion. Oder Du startest die Messung
beim 0-Durchgang des Timers, dann hast Du die Verzögerung.
Ich war gerade am überlegen wie viele Messwerte ich Prozentual für die
Mittelwertbildung nutzen sollte. Dachte da an Gauß mit knapp 2/3 der
Messergebnisse, da sollten die groben aussreisser ja raus sein oder ?
Jap versteh was du meinst Joe.
Zum Timer mit den zurücksetzten hatte ich auch schonmal überlegt wurde
mir aber von abgeraten, da ich im schlimmsten fall eine Zeiteinheit
verlieren kann, wenn während des zurücksetztens gerde der Timer um 1
hochzählt.
Zu dem Interrupt ich habe es per Interrupt gemacht, weil es schneller
ging und ich noch 3 andere Interrupts am laufen habe welche gesperrt
werden während der Interrupt des HC ausgeführt wird, und somit
gewährleistet ist das kein Interrupt die Messungstört.
Sebi schrieb:> weil es schneller ging und ich noch 3 andere Interrupts am laufen habe> welche gesperrt werden während der Interrupt des HC ausgeführt wird,
Verstehe ich nicht. Was sind das für Interrupts und ist sicher, dass der
Interrupt der Messung die anderen unterbricht?
Sebi schrieb:> Ja ist weiter oben eingestellt, das keine Interrupts während eines> Interrupts statt findet.
hast Du oben was dazu geschrieben? Naja, wenigstens weisst Du nun, warum
Du manchmal ausreißer hast. Wenn die anderen Interrupts während der
Messung wichtig sind, brauchst du um ein input capture timer.