Guten Morgen und einen schönen Feiertag. Ich finde irgendwie verschiedene Schreibweisen, wie der Capture und Overflow Interrupt vom Timer1 des Nano geschrieben wird. Vom PIC her bin ich das bitweise setzen anders gewöhnt. Ich möchte diese gern auch am Arduino Bitweise setzen oder deaktivieren. Laut Datenblatt wären diese Bits wie folgt: TCCR1B ICES1: Input Capture Edge Select TIMSK1 ICIE1: Timer/Counter1, Input Capture Interrupt Enable TOIE1: Timer/Counter1, Overflow Interrupt Enable Sind diese Schreibweisen so korrekt ? TCCR1B &= ~(1<<ICES1) -> Bit setzen für fallende flanke TCCR1B |= (1<<ICES1) -> Bit setzen für steigende flanke TIMSK1 &= ~(1<<TOIE1) -> Bit setzen für Deaktivierung overflow Interrupt TIMSK1 &= ~(1<<ICIE1) -> Bit setzen für Deaktivierung Capture Interrupt TIMSK1 |= (1<<TOIE1) -> Bit setzen für Aktivierung overflow Interrupt TIMSK1 |= (1<<ICIE1) -> Bit setzen für Aktivierung Capture Interrupt Vielen Dank vorab.
Daniel E. schrieb: > Arduino Dann setzt man am besten TCCR1A und TCCR1B beide auf 0, da Arduino die Timer für PWM vorbereitet
> Dann setzt man am besten > TCCR1A und TCCR1B beide auf 0, da Arduino die Timer für PWM vorbereitet Jup so... TCCR1A = 0; // Reset Timer 1 Control Register A TCCR1B = 0; // Reset Timer 1 Control Register B leider ist meine Frage damit nicht beantwortet... Danke.
Daniel E. schrieb: > TIMSK1 &= ~(1<<TOIE1) -> Bit setzen für Deaktivierung overflow Interrupt > TIMSK1 &= ~(1<<ICIE1) -> Bit setzen für Deaktivierung Capture Interrupt Du setzt damit allerdings kein Bit, sondern löscht es. Der Kommentar stimmt also nicht, die Schreibweise zum Löschen ist aber richtig. Auch die anderen Zeilen sehen richtig aus.
:
Bearbeitet durch User
Daniel E. schrieb: > leider ist meine Frage damit nicht beantwortet... Deine Schreibweisen sind allesamt unnötig/unsinnig in der Situation
Daniel E. schrieb: > Sind diese Schreibweisen so korrekt ? Die Frage riecht nach: "Ich habe keine Lust mich mit den Operatoren der Sprache C bekannt zu machen bzw. die Bedeutung dieser Operatoren zu lernen".
Arduino F. schrieb: > Daniel E. schrieb: >> leider ist meine Frage damit nicht beantwortet... > > Deine Schreibweisen sind allesamt unnötig/unsinnig in der Situation Das mag evtl. so erscheinen, ich wollte damit sichergehen, dass der Code wenigstens richtig ist, bevor ich ein Problem hier schildere/ draus mache. Ich komme später drauf zurück. Danke.
Daniel E. schrieb: > Das mag evtl. so erscheinen, Deine Erscheinungen..... Daniel E. schrieb: > ich wollte damit sichergehen, dass der Code > wenigstens richtig ist, bevor ich ein Problem hier schildere/ draus > mache. Alles klar, keine Fragen.
Ich kommen malm zum eigentlichen Problem mit dem ich kämpfe. Ich habe eine ISR mit Timer 2, welche aller 1 ms eine Zahl erhöht und bei 200 ms dann den Capture freigeben soll.
1 | ISR(TIMER2_COMPA_vect) // 1 khz (1 ms Timer) |
2 | {
|
3 | |
4 | Display_counter ++; |
5 | |
6 | if(Display_counter >= 200) // aller 200 ms Display refresh |
7 | {
|
8 | DisplayUpdate = 1; |
9 | Display_counter = 0; |
10 | |
11 | if(Wait_RPM_Trigger == 0) |
12 | {
|
13 | Serial.println(TCNT1); |
14 | TIMSK1 = (1 << TOIE1); // Enable Timer1 overflow interrupt |
15 | TIMSK1 |= (1 << ICIE1); // Enable Timer1 Input Capture Interrupt |
16 | TCNT1 = 0; // Schreibe Timer mit Wert 0 |
17 | First_Capture = 0; |
18 | Overflow = 0; |
19 | Serial.println("Timer setzen"); |
20 | Serial.println(TCNT1); |
21 | Wait_RPM_Trigger = 1; |
22 | }
|
23 | }
|
Daniel E. schrieb: > Ich kommen malm zum eigentlichen Problem mit dem ich kämpfe. Mehrere serielle Ausgaben inklusive Konvertierung innerhalb einer ISR. Du kämpfst noch mit ganz anderen Problemen. ;-)
Beitrag #7566837 wurde vom Autor gelöscht.
Ich kommen malm zum eigentlichen Problem mit dem ich kämpfe. Ich habe eine ISR mit Timer 2, welche aller 1 ms eine Zahl erhöht und bei 200 ms dann den Capture freigeben soll.
1 | ISR(TIMER2_COMPA_vect) // 1 khz (1 ms Timer) |
2 | {
|
3 | |
4 | Display_counter ++; |
5 | |
6 | if(Display_counter >= 200) // aller 200 ms Display refresh |
7 | {
|
8 | DisplayUpdate = 1; |
9 | Display_counter = 0; |
10 | |
11 | if(Wait_RPM_Trigger == 0) |
12 | {
|
13 | Serial.println(TCNT1); |
14 | TIMSK1 = (1 << TOIE1); // Enable Timer1 overflow interrupt |
15 | TIMSK1 |= (1 << ICIE1); // Enable Timer1 Input Capture Interrupt |
16 | TCNT1 = 0; // Schreibe Timer mit Wert 0 |
17 | First_Capture = 0; |
18 | Overflow = 0; |
19 | Serial.println("Timer setzen"); |
20 | Serial.println(TCNT1); |
21 | Wait_RPM_Trigger = 1; |
22 | }
|
23 | }
|
in der ISR vom Capture steht
1 | ISR(TIMER1_CAPT_vect) //Capture Interrupt Drehzahlmessung |
2 | {
|
3 | Serial.println("ich capture trotzdem"); |
4 | if (First_Capture == 1) |
5 | {
|
6 | ZeitT2 = ICR1; |
7 | NewRPMValue = 1; |
8 | First_Capture = 3; //Modus gib es nicht |
9 | Serial.println("2. Capture routine"); |
10 | Serial.println(TCNT1); |
11 | }
|
12 | |
13 | if (First_Capture == 0) |
14 | {
|
15 | TCNT1 = 0; // Schreibe Timer mit Wert |
16 | Serial.println("1. Capture routine"); |
17 | Serial.println(TCNT1); |
18 | First_Capture = 1; //Capture 2nd value |
19 | }
|
20 | }
|
das sieht dann wie folgt aus auf dem Serial monitor: 37 ich capture trotzdem 2. Capture routine 12537 ich capture trotzdem ich capture trotzdem 43979 Timer setzen 26 ich capture trotzdem 1. Capture routine 38 ich capture trotzdem 2. Capture routine 12538 ich capture trotzdem ich capture trotzdem 43978 Timer setzen 26 Das zweite Capture Ergebnis ist immer 12538 +/-1. Füge ich in die
1 | |
2 | if (First_Capture == 1) |
3 | {
|
4 | TIMSK1 &= ~(1<<ICIE1); // -> Bit setzen für Deaktivierung Capture Interrupt |
5 | }
|
zusätzlich ein, weil ich den Capture deaktivieren will kommt bei gleicher Frequenz am Eingang folgendes raus: ich capture trotzdem 1. Capture routine 39 ich capture trotzdem 2. Capture routine 12175 49837 Timer setzen 27 ich capture trotzdem 1. Capture routine 39 ich capture trotzdem 2. Capture routine 12176 49837 Timer setzen 27 ich capture trotzdem 2. Capture routine 12178 49837 Timer setzen 27 ich capture trotzdem 1. Capture routine 39 ich capture trotzdem 2. Capture routine 12179 49837 Timer setzen 27 ich capture trotzdem 1. Capture routine 39 ich capture trotzdem 2. Capture routine 12181 Man sieht, dass alle weiteren Capture nach dem 2ten gesperrt sind, soweit so gut. Leider ist der zweite Capture Wert völlig daneben und wird sogar mit jeder Routine hochgezählt, bei gleicher Eingangsfrequenz.. Was will ich eigentlich? Ich möchte aller 200 ms eine Freigabe der Capture und Overflow ISR im Timer 2 ISR machen. Gibt es zwei Flanken, werden beide ISR (Capture+ Overflow) gesperrt und es wird auf die nächste Freigabe nach 200 ms gewartet. Gibt es nur einen Impuls oder garkeinen, dann läuft der Timer über und im Overflow soll dann der capture und overflow deaktiviert werden, bis er zur nächsten Freigabe in der Timer 2 ISR wieder aktiviert wird. Alles in allem läuft das mit dem deaktivieren und aktivieren der zuvor angefragten Befehle bei mir überhaupt nicht und ich weiß leider nicht warum.. Danke für den Support
Norbert schrieb: > Du kämpfst noch mit ganz anderen Problemen. ;-) Wie man hier schon sehen konnte: Beitrag "Arduino Auslastung Tacho und Drehzahl messen" Er versteht weder die gestellten Rückfragen noch die Antworten dazu.
Naja, ich weis selber das die ISR damit sehr lange abgearbeitet wird und eigentlich sehr kurz gehalten werden soll. Um das Problem einzugrenzen, bietet sich halt der serial Port an, um zu sehen was wo los ist… Meint ihr etwa, wenn ich das serial rausnehme, dass es dann geht, so wie ich die Freigaben und Blockierungen machen will ? Gegenfrage, warum funktioniert es ohne TIMSK1 &= ~(1<<ICIE1); // -> Bit setzen für Deaktivierung Capture Interrupt und mit dem Code wird Blödsinn, falsche Werte angezeigt. Wird eigentlich ja nur der ISR gesperrt. Danke.
Mi N. schrieb: > Norbert schrieb: >> Du kämpfst noch mit ganz anderen Problemen. ;-) > > Wie man hier schon sehen konnte: > Beitrag "Arduino Auslastung Tacho und Drehzahl messen" > Er versteht weder die gestellten Rückfragen noch die Antworten dazu. Das 15 V Signal geht auf einen Komparator Eingang und der bereitet es für den uc auf, der dann ein 5 V Signal bekommt. Ist mir schon klar, dass der uC keine 15 V verträgt.
Daniel E. schrieb: > Naja, ich weis selber das die ISR damit sehr lange abgearbeitet wird und > eigentlich sehr kurz gehalten werden soll. Das stimmt so nicht. Richtig ist, daß alle Interrupts gesperrt sind, während die ISR abgearbeitet wird. Die ISR muß also fertig sein, bevor der nächste Interrupt kommt. Wie lange du dazu Zeit hast, hängt von der Konfiguration deines uC ab.
Ja, ist klar, dass der Interrupt erst abgearbeitet wird. Passiert nebenbei noch einer, wird ins Hauptprogramm gesprungen, nur ein Befehl abgearbeitet und dann in den nächsten ISR gesprungen nach deren Vektoradresse, nicht deren Reihenfolge
Arduino F. schrieb: > Daniel E. schrieb: >> Passiert >> nebenbei noch einer, wird ins Hauptprogramm gesprungen > > Nein. Na ja, man könnte schon erahnen, das damit „Passiert nebenbei noch einer, wird nach Ende der ISR ins Hauptprogramm gesprungen…“ gemeint war. Oliver
Oliver S. schrieb: > gemeint war. Nein! Serial basiert auf Interrupts. Das ist nicht wirklich schlimm. Aber in ISR sind Interrupts erstmal verboten. Damit ist die Blockade "vorprogrammiert" wenn man in ISR Serial nutzt. Und das ist schlimm.
Das normale Verhalten beim Abarbeiten einer ISR ist, das global erstmal alle IRQs per I-Flag gesperrt werden. Wenn man weiss, was man tut, kann man die ISR als NO_BLOCK deklarieren, damit das nicht passiert. Aber serielle Ausgaben haben in jeglicher ISR nichts zu suchen. Man kann doch in der Hauptschleife ausgeben.
Schade, dass hier am Problem, einer Erklärung oder den möglichen Ursachen vorbei diskutiert wird …
Daniel E. schrieb: > Schade, dass hier am Problem, einer Erklärung oder den möglichen > Ursachen vorbei diskutiert wird … 1. Deine Erklärungen sind für Außenstehende nicht/kaum/nur mit extrem hohem Zeitaufwand nachvollziehbar (das tut sich keiner an) 2. Kommentare in Deinem Code verwirren eher, als daß sie nutzbare Informationen enthalten ("Bit setzen für deaktivieren" obwohl in der Realität das Bit gelöscht wird); auch das tut sich keiner über längere Zeit an; ein entsprechender Hinweis kam sehr zeitig im Thread 3. in Deinem Code sind jede Menge nicht kontrollierbare/erkennbare/nachvollziehbare Seiteneffekte (Variablen werden gesetzt mit nicht erkennbaren Ausirkungen, nutzen der in ISRs hochgradig problematischen println-Funktion innerhalb einer ISR, ...); Hierzu auch sehr früh im Thread der entsprechende Hinweis. Zusammengefaßt alles Dinge, durch die potentielle Leser dieses Threads von ihrem Willen zu Helfen abschreckt werden. Daniel E. schrieb: > Gegenfrage, warum funktioniert es ohne > > TIMSK1 &= ~(1<<ICIE1); // -> Bit setzen für Deaktivierung Capture > Interrupt > > ... Wird eigentlich ja nur der ISR gesperrt. Es wird nicht nur einfach der Interrupt gesperrt. Ab diesem Zeitpunkt wird auch die ISR nicht mehr aufgerufen und sämtliche mit dieser ISR verbundenen Seiteneffekte (setzen von Variablen, reagieren auf diese Variablen, verändern dieser und anderer Werte in Deinem Programm, Aufruf weiterer Funktionen mit weiteren Auswirkungen auf den Programmablauf usw.) treten nicht oder anders auf. Dein gesamter Programmablauf ändert sich. ich bin damit auch raus ....
Daniel E. schrieb: > Schade, dass hier am Problem, einer Erklärung oder den möglichen > Ursachen vorbei diskutiert wird Beratungsresistenz ist eine Zier, doch weiter kommt man ohne ihr. Sinnvoller wäre es, erst einmal zu erklären was du überhaupt erreichen willst bevor du wild mit zwei Timern gleichzeitig das Programmieren anfängst.
Daniel E. schrieb: > Was will ich eigentlich? Ich möchte aller 200 ms eine Freigabe der > Capture und Overflow ISR im Timer 2 ISR machen. Warum ständig sperren und wieder freigeben? Ich halte dieses Konzept für eher untauglich. Lass doch den Timer mit seinen Funktionen einfach ständig weiterlaufen und beachte ihn einfach nicht. Kostet doch keine Rechenzeit. Der Capture-INT schreibt im Hintergrund immer brav seine Werte in irgendeine Variable. Und wenn dann alle 200ms der Wert benötigt wird so holt man diesen einfach aus der Variable. So mache ich das seit Jahren und funktioniert problemlos.
Daniel E. schrieb: > Ich habe eine ISR mit Timer 2, welche aller 1 ms eine Zahl erhöht Rechne doch bitte erstmal nach, wieviel Zeichen Du innerhalb 1ms über die UART ausgeben kannst bei Deiner gewählten Baudrate. Z.B bei 9600 Baud nichtmal eins.
Hallo und die Runde und danke für das Feedback. Ich habe den Ratschlag angenommen, ständig zu Capturen und in der Routine mir Variablen zu setzen, je nachdem wo ich gerade stehe. Der Code läuft nun, kleiner 4 Hz gibt es den Overflow und es wird 0 RPM angezeigt und ab 240 UPM/ min bis 348 Hz = 20800 UPM/min keine Probleme. Alle 200 ms wird eine neue Messung frei gegeben. Wahrscheinlich muss ich meine Denkweise -lasse den µC nur das tun was WIRKLICH notwendig ist, ablegen lernen. Eigentlich muss es auch, wenn es richtig angestellt ist mit freigeben und sperren gehen, wenn alle Variablen richtig deklariert sind. Schade, dass ich nun nicht weiß, woran es gelegen hat. Für die, die es interessiert stell ich den Codeteile mal hier ein. Wer noch Bemerkungen hat, gerne her damit. Ansonsten vielen Dank für den Beistand.
1 | void loop() { |
2 | |
3 | //RPM Motor berechnen_________________________________________________________________________________//
|
4 | |
5 | if (Capture_State ==3 ) // Messung gültig |
6 | {
|
7 | RPM_Motor = (1000000/ ZeitT2)*15 ; |
8 | Capture_State = 0; //Freigabe neue Messung |
9 | }
|
10 | |
11 | if (Overflow == 1 ) |
12 | {
|
13 | RPM_Motor = 0; |
14 | }
|
15 | |
16 | ISR(TIMER1_CAPT_vect) //Capture Interrupt Drehzahlmessung |
17 | {
|
18 | |
19 | if (Capture_State == 2) |
20 | {
|
21 | ZeitT2 = ICR1; |
22 | Capture_State = 3; //Habe Messwert |
23 | }
|
24 | |
25 | if (Capture_State == 1) |
26 | {
|
27 | TCNT1 = 0; // Schreibe Timer mit Wert |
28 | Capture_State = 2; //Capture |
29 | }
|
30 | }
|
31 | |
32 | |
33 | |
34 | ISR(TIMER1_OVF_vect) // overflow |
35 | {
|
36 | digitalWrite(LED, !digitalRead(LED)); |
37 | if(Capture_State == 0 || Capture_State == 3) |
38 | {
|
39 | Overflow = 0; |
40 | }
|
41 | else
|
42 | {
|
43 | Overflow = 1; |
44 | }
|
45 | |
46 | }
|
47 | |
48 | |
49 | |
50 | |
51 | |
52 | ISR(TIMER2_COMPA_vect) // 1 khz (1 ms Timer) |
53 | {
|
54 | |
55 | Display_counter ++; |
56 | if(Display_counter >= 200) // aller 200 ms Display refresh |
57 | {
|
58 | DisplayUpdate = 1; |
59 | Display_counter = 0; |
60 | |
61 | if(Capture_State == 0) |
62 | {
|
63 | TCNT1 = 0; // Schreibe Timer mit Wert 0 |
64 | Overflow = 0; |
65 | Capture_State = 1; //Starte Messung |
66 | }
|
67 | }
|
68 | }
|
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.