Guten Tag liebe Profis. gleich werde ich wieder Schläge kriegen :D ... Nachdem ich mich mit dem C bzw. C++ des Arduino nun etwas angefreundet habe, eine Frage zum Timer. Aus welchem Grund ist in ISR delay() gesperrt? Gibts dafür einen technischen Grund? Oder wurde das getan, um die Leute von "Dummheiten" abzuhalten? Also mit millis() und while() kann man 1 Sekunde Wartezeit z.B. ja auch realisieren, wenn man das will. Da millis() in der Warteloop auch weitergezählt wird, frage ich mich, wieso delay() den diesnst versagt. Ist ja nur eine Frage zur Theorie.
:
Gesperrt durch Moderator
Wenn du nur einen Code hast, der stur Zeile für Zeile abgearbeitet wird, dann kann ich nichts gegen ein delay() einwenden. Sobald du jedoch eine (mehrere) ISR hast wird es problematisch. Der Sinn hinter der Verwendung von einer ISR ist, dass das Hauptprogramm seine Arbeit verrichten kann und nur kurz durch z.B. das Empfangen von neuen Daten, unterbrochen wird. Verwendest du nun aber ein delay(1000) in deiner ISR, so wird das Hauptprogramm gestoppt und der uC macht 1s lang gar nichts. Wenn dich das nicht stört kannst du es schon machen (wenn auch nicht schön/gern gesehen).. Schlimm wird es bei einer zweiten (niedriger oder gleich priorisierten) ISR. Bevor diese ausgeführt wird, muss zuerst die ISR1 abgearbeitet werden. Dadurch kann es zu sehr langen Verzögerungen führen. Wenn ISR2 zeitlich kritisch ist..
Moin Roth,
> gleich werde ich wieder Schläge kriegen :D ...
Naja, immerhin weist Du es ja schon :-) Denn Dein Ansinnen ruft
mindestens mildes Kopfschütteln aus.
Delay in einer ISR ist an sich schonmal seltsam. Kurz gesagt willst Du
ISRs ausnahmslos (komplett ausnahmslos!) zeiteffizient abarbeiten. In
einer Timer-ISR wird das ganze noch viel widersinniger. Wozu warten,
wenn Du einfach aus der ISR raus und später wieder rein kannst?
Gruß, jois3
jois3 schrieb: > Kurz gesagt willst Du > ISRs ausnahmslos (komplett ausnahmslos!) zeiteffizient abarbeiten Wenn man Controller mit verschachtelbaren Interrupts hat (Cortex-M z.B.) kann man unter bestimmten Umständen durchaus auch in ISRs längere Dinge tun. Ob das in Arduino so geht weiß ich aber nicht.
jois3 schrieb: > Moin Roth, > >> gleich werde ich wieder Schläge kriegen :D ... > Naja, immerhin weist Du es ja schon :-) Denn Dein Ansinnen ruft > mindestens mildes Kopfschütteln aus. ja. Ich kenn euch doch :) So ein paar Sonderfälle kamen mir schon vor die Finger. z.B. Taster 5Sek gedrückt => Reboot. Vor dem Reboot sollte eine LED 1 Sek. leuchten, als Taster-Feedback, also Rückmeldung für den User. Taster-Feedback muss zwar nicht sein, ist aber eine schöne Abrundung für eine Platine, die nur ein paar LEDs, aber kein Display hat. Und wen juckt es schon, wenn vor einem Reboot der ISR nicht kann wie er will. Ich habe mehrere Kanäle im ISR. Wenn ich einen blockiere (nur mal zum testen habe ich das probiert), habe ich festgestellt, dass die anderen noch weiter versorgt werden. Ohne sei() auszuführen () Hat mich zwar gewundert, ist aber so. Ja, was soll ich sagen? Wer sich nicht mit Interrupts auskennt, sollte kein delay(1000) in Routinen verwenden, die 100x pro Sekunde aufgerufen werden. Wer es doch tut, und keine Regulatorik hat, der muss vor dem Lernen eben leiden. Ich wollte aber eigentlich , wieso delay() technisch deaktiviert ist. Das könnte meines Erachtens auch im ISR ohne weiteres funktionieren.
"Ich wollte aber eigentlich wissen" ... wollte ich eigentlich schreiben.
Roth schrieb: > Aus welchem Grund ist in ISR delay() > gesperrt? Weil delay selber den Timerinterrupt benutzt, aber in einem Interrupthandler sind alle Interrupts gesperrt -> Deadlock. Der AVR kennt keine Interruptlevel (bzw. nur einige neuere). Man kann aber das Delay-Macro des GCC benutzen _delay_ms().
Roth schrieb: > Ich wollte aber eigentlich , wieso delay() technisch deaktiviert ist. Vermutlich ist delay() unter Arduino über einen Timer-Interrupt realisiert. Da standardmäßig bei AVRs geschachtelte Interrupts nicht möglich sind (außer man trickst ziemlich herum), kommt der zu delay() gehörende Timer-Interrupt nicht zum Zuge. Daher wird delay() nicht mehr zurückkommen und Dein Programm hängt an dieser Stelle. Beschreibe besser, was Du eigentlich machen möchtest. Meist kann man das vollkommen anders (und besser!) lösen.
1 | //C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring.c
|
2 | unsigned long micros() { |
3 | unsigned long m; |
4 | uint8_t oldSREG = SREG, t; |
5 | |
6 | cli(); |
7 | m = timer0_overflow_count; |
8 | #if defined(TCNT0)
|
9 | t = TCNT0; |
10 | #elif defined(TCNT0L)
|
11 | t = TCNT0L; |
12 | #else
|
13 | #error TIMER 0 not defined
|
14 | #endif
|
15 | |
16 | #ifdef TIFR0
|
17 | if ((TIFR0 & _BV(TOV0)) && (t < 255)) |
18 | m++; |
19 | #else
|
20 | if ((TIFR & _BV(TOV0)) && (t < 255)) |
21 | m++; |
22 | #endif
|
23 | |
24 | SREG = oldSREG; |
25 | |
26 | return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); |
27 | }
|
28 | |
29 | void delay(unsigned long ms) |
30 | {
|
31 | uint32_t start = micros(); |
32 | |
33 | while (ms > 0) { |
34 | yield(); |
35 | while ( ms > 0 && (micros() - start) >= 1000) { |
36 | ms--; |
37 | start += 1000; |
38 | }
|
39 | }
|
40 | }
|
Weil delay() die Funktion micros() verwendet, diese wiederum dem Timer0. Dessen Interrupt (wie alle anderen auch) ist aber gesperrt, wenn Du dich mit der Abarbeitung einer ISR beschäftigts. des I-Flag wird erst nach Rückkehr aus dieser durch die Hardware neu gesetzt. -- Andererseit: ( ich bin da auch nicht soo der Experte... )
1 | if ((TIFR0 & _BV(TOV0)) |
sollte doch, unabhängig vom globalen Freigabebit (I-Flag, TOIE0) trotzdem im TIFR0 das TOV0 Bit gesetzt werden wenn der Timer0 überläuft, oder?
Roth schrieb: > Ich habe mehrere Kanäle im ISR. Wenn ich einen blockiere (nur mal zum > testen habe ich das probiert), habe ich festgestellt, dass die anderen > noch weiter versorgt werden. Ohne sei() auszuführen () Hat mich zwar > gewundert, ist aber so. Unfug!
Frank M. schrieb: > Beschreibe besser, was Du eigentlich machen möchtest. Meist kann man das > vollkommen anders (und besser!) lösen. Habs ja schon umgesetzt. Wollte nur den Grund wissen, also reine Theorie. Ich habe wie gesagt eine LED softwaremäßig an ein paar Taster gebunden. Feedbacks für Tastendruck, ergebnisabhängig, verschiedenes Blinken oder Leuchten. Alles timergesteuert. Das klappt zwar alles ohne Verzögerung, aber eine Blinksequenz sollte zu Ende laufen und nicht von einem anderen Event überschrieben werden, bevor z.B. die 1 Sekunde um ist. Und dass der Timer gestoppt ist, wenn in einem ISR gewartet wird, konnte ich im Labor nicht feststellen. Bin in eine while(1){} Schleife gesprungen und -etwas verwundert- festgestellt, dass die LED (timergesteuert) immer noch blinkt. Das hieße ja eigentlich, dass nur 1 Takt des Timers "hängt", und neue Takte noch ausgeführt werden. Code, der länger als 1 ISR-Takt dauert, ist natürlich mit static zu sperren , damit kein neuer Takt dem aktuellen in den Rücken fällt,.
Arduino Fanboy D. schrieb: > Unfug! Und schon ist die Ruhe vorbei. Bitte gehe doch wieder weg und pöbel in anderen Themen. danke.
ÄXl schrieb: > Weil delay() die Funktion micros() verwendet, diese wiederum dem Timer0. ÄXl ich habe Timer2 in Verwendung. Ich weiß nicht, wie die Timer priorisiert sind. Les mich da mal demnächst besser ein. Im Moment bin ich noch am tüfteln + probieren, reine Spielwiese
Roth schrieb: > , wieso delay() technisch deaktiviert ist. Since delay() requires interrupts to work, it will not work if called inside an ISR. delayMicroseconds() does not use any counter, so it will work as normal. Generally, an ISR should be as short and fast as possible. https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
> Roth schrieb: >> Ich habe mehrere Kanäle im ISR. Wenn ich einen blockiere (nur mal zum >> testen habe ich das probiert), habe ich festgestellt, dass die anderen >> noch weiter versorgt werden. Ohne sei() auszuführen () Hat mich zwar >> gewundert, ist aber so. Eine ISR mit while(1); blockiert? Wenn eine andere ISR dann noch aufgerufen wird, dann muss diese höher priorisiert sein.
Roth schrieb: > Arduino Fanboy D. schrieb: >> Unfug! > > Und schon ist die Ruhe vorbei. Bitte gehe doch wieder weg und pöbel in > anderen Themen. danke. Meister! Schaue in die Doku deines AVR und deiner Lieblingssprache. Und du wirst erfahren, das beim/vorm Eintritt in die ISR Interrupts gesperrt werden. Diese Sperre wird per Default erst beim Austritt wieder aufgehoben. Somit ist deine Geschichte ein Märchen. Was du da in der Realität veranstaltet hast, ist geheim. Zumindest sehe ich es nicht. Zeige ein einfaches Beispiel, von dem, was du da tust. Und ich sage dir dann, ob und wenn, dann warum, da weiter ISRs aufgerufen werden, obwohl angeblich Interrupts abgeschaltet sind. Du hast da ganz offensichtlich irgendein Verhalten deines µC fehlinterpretiert. Das ist ok, passiert jedem mal. Aber an dieser Stelle ist das nachprüfbar zu widerlegen. Du erzählst Märchen. Unwahrheiten. Und ab jetzt, bei Wiederholungen, nach dem ich dir gesagt habe, dass das Unsinn ist, wird aus dem Märchen eine Lügengeschichte. Märchen enthalten wenigstens einen Kern Wahrheit, oder eine Empfehlung. Deine Geschichte nicht. OK, du magst es so wahrgenommen haben. Aber mit der Realität, was wirklich passiert ist, hat das wenig/nichts zu tun. Roth schrieb: > Und dass der Timer gestoppt ist, wenn in einem ISR gewartet wird, konnte > ich im Labor nicht feststellen. Bin in eine while(1){} Schleife > gesprungen und -etwas verwundert- festgestellt, dass die LED > (timergesteuert) immer noch blinkt. Der Timer wird nicht gestoppt! Der läuft unbeirrt weiter. Roth schrieb: > Das hieße ja eigentlich, dass nur 1 Takt des Timers "hängt", und neue > Takte noch ausgeführt werden. Code, der länger als 1 ISR-Takt dauert, > ist natürlich mit static zu sperren , damit kein neuer Takt dem > aktuellen in den Rücken fällt Auch eine lustige Geschichte! Dieses mal sogar mit der Empfehlung, mit static zu sperren. Würdest du bitte den Absatz nochmal überdenken...
sei() wird ja auch schon vom Framework aufgerufen. Damit hast Du ja nix zu tun. (main.cpp ruft init auf, darin: sei()) gleich über der og. delay() Routine inder wiring.cpp zu finden. danach erst kommt "setup", dann das "loop".
1 | "C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\main.cpp" |
Du hattest doch den Quelltext nun schon offen. Sieh doch einfach nach, was passiert! Stell' mal deinem while(1) ein cli() voran. weshalb sollte eine While(1) deine Ints sperren?
Arduino Fanboy D. schrieb: > Meister! ja, danke :) > Schaue in die Doku deines AVR und deiner Lieblingssprache. Piano. Ich habe nach deiner Anregung 100 Bücher gekauft, aber erst 58 gelesen. Bitte vergib mir, o Herr MiMa schrieb: > Eine ISR mit while(1); blockiert? > Wenn eine andere ISR dann noch aufgerufen wird, dann muss diese höher > priorisiert sein. Ja. Ich habe das aber selbst nie richtig glauben können, und noch mal alles durchforstet. Bisher ging ich davon aus, dass cli()...sei() zwingend symetrisch organisiert sind (wie z.B. push und pop in Asm). Wenn ISR gesperrt ist (also sozusagen "Status cli()" vorliegt), und im weiteren Code die Folge {cli(); blablabla; sei()} vorkommt, ging ich davon aus, dass nach dem sei() "Status cli()" immer noch vorliegt ( 2xcli() und nur 1x sei() ). Es ist aber wohl so, dass die letzte Order gewinnt. Da ich bei atomaren Operationen cli() und sei() verwende (zwar nicht im ISR aber in Serviceroutinen, die vom ISR gelegentlich verwendet werden), war es also im Endeffekt so, dass ISR durch das abschließende sei() einer Serviceroutine freigeschaltet war, obwohl dort noch Code ausgeführt worden ist. Habe ich gar nicht gemerkt :) Und daher ging auch while(1); problemlos. Es war ja nur der eine Kanal blockiert, die anderen wurden noch vom Taktgeber versorgt. Weil ich es aus Assembler gewohnt bin, im Timerinterrupt "ohne Netz" zu arbeiten (also Taktgeber rattert weiter, auch wenn gerade ein Event bearbeitet wird), ist mir das nicht aufgefallen, dass ISRs beim Arduino standardmäßig gesperrt sind, wenn "drinnen" gerade was ausgeführt wird. Wie oben geschrieben, war ich zwar verwundert, dass sich while(1); nicht aufhängt, fand das aber eher positiv. Wenn der Kanal nicht gesperrt gewesen wäre, hätte es vermutlich im nullkommanix eine Stack Overflow gegeben ;)
Roth schrieb: > Aus welchem Grund ist in ISR delay() > gesperrt? Gibts dafür einen technischen Grund? Nichtmal millis() wird dann weiter laufen, d.h. Zeitsteuerungen funktionieren nicht mehr.
Bin mal so frei, meine Spielwiese offen zu stellen. Die ISR ohne das (im PDF rot markierte) Testzeugs läuft einwandfrei. Vielleicht nützt es dem einen oder anderen ja mal. > Was du da in der Realität veranstaltet hast, ist geheim. > Zumindest sehe ich es nicht. So so. Du siehst es also nicht. Und jetzt, kannst du es sehen?
1 | // Ein kleines ISR Programm, um LEDs mit konfigurierbarer Sequenz blinken zu lassen.
|
2 | // Das rote (nur im PDF ist es rot) ist zum testen eingefügt, um zu sehen, wie der
|
3 | // Timer Interrupt sich verhält, wenn ein LED-Kanal behindert wird.
|
4 | |
5 | /*************************** D E F I N E S ***************************************************/
|
6 | |
7 | // besser lesbar
|
8 | #define byte uint8_t
|
9 | #define word uint16_t
|
10 | #define dword uint32_t
|
11 | |
12 | // Allgemein
|
13 | #define NC 255 // Default für "unbenutzt" (z.B. Pin)
|
14 | |
15 | // Timer 2 Interrupt: Haupttakt konfigurieren
|
16 | #define MAIN_CLK 160 // Interrupts pro Sekunde (Timer-Takt)
|
17 | #define OCR2A_KOR 2 // Manueller OCR2A Korrekturfaktor
|
18 | |
19 | /**********************/
|
20 | /* LM: LED-Management */
|
21 | /**********************/
|
22 | |
23 | // LM: Allgemeine Einstellungen
|
24 | #define LM_COUNT 4 // Anzahl Kanäle
|
25 | #define LM_CLOCK 20 // Timer-Prescaler Default
|
26 | |
27 | // LM_01: Kanal 1 konfigurieren (LED rot)
|
28 | #define LM_01_IDX 0 // Index im Arbeitsbereich
|
29 | #define LM_01_PIN 37 // Pin-Nr.
|
30 | |
31 | // LM_02: Kanal 2 konfigurieren (LED gelb)
|
32 | #define LM_02_IDX 1 // Index im Arbeitsbereich
|
33 | #define LM_02_PIN 39 // Pin-Nr.
|
34 | |
35 | // LM_03: Kanal 3 konfigurieren (LED grün)
|
36 | #define LM_03_IDX 2 // Index im Arbeitsbereich
|
37 | #define LM_03_PIN 41 // Pin-Nr.
|
38 | |
39 | // LM_04: Kanal 4 konfigurieren
|
40 | #define LM_04_IDX 3 // Index im Arbeitsbereich
|
41 | #define LM_04_PIN NC // Pin-Nr.
|
42 | |
43 | // LM: Verwendete Kanäle (Sprechender Tabellenindex)
|
44 | #define LED_ROT LM_01_IDX // LED rot
|
45 | #define LED_GELB LM_02_IDX // LED gelb
|
46 | #define LED_GRUEN LM_03_IDX // LED grün
|
47 | |
48 | /*************************** T Y P E S *******************************************************/
|
49 | |
50 | // LM: Struktur des Arbeitsbereichs
|
51 | struct tLM { |
52 | byte Pin; // Pin-Nr. (NC=ungenutzt) |
53 | word TPrescaler; // Timer-Prescaler (0=Kanal deaktiviert) |
54 | word TCounter; // Prescaler-Counter |
55 | byte InUse; // ISR-Sperrflag (1=Kanal wird gerade verwendet) |
56 | byte Pattern; // LED-Blinkmuster |
57 | byte BitPointer; // Bit-Zeiger |
58 | };
|
59 | |
60 | /*************************** G L O B A L E V A R I A B L E N ********************************/
|
61 | |
62 | // LM: LED-Arbeitsbereich anlegen
|
63 | volatile tLM LM[LM_COUNT]; |
64 | |
65 | /*************************** F O R W A R D S ************************************************/
|
66 | |
67 | void mySetup(); |
68 | |
69 | /*************************** A D M I N I S T R A T I O N S T O O L S *************************/
|
70 | |
71 | /***************************************************************************/
|
72 | /* Zeigt die Millisekunden mit Nachkommastellen seit dem letzten Aufruf an */
|
73 | /* */
|
74 | /* fNoPrint : 1=initialisiert nur den Zeitstempel (kein Ausgabe) */
|
75 | /***************************************************************************/
|
76 | void PrintMillisDelta(byte iKanal=0, byte fNoPrint=0) { |
77 | static dword Timestamp[10]; |
78 | if (!fNoPrint) |
79 | {Serial.println( (micros() - Timestamp[iKanal]) / 1000.0);} |
80 | Timestamp[iKanal] = micros(); |
81 | }
|
82 | |
83 | /***************************************/
|
84 | /* Byte als Binärzahl seriell ausgeben */
|
85 | /***************************************/
|
86 | void PrintBinaer(byte i, byte fMitBitNr=0, byte fNoLN=0) { |
87 | if (fMitBitNr) |
88 | {Serial.println("76543210");} |
89 | for (byte n=0; n<8; n++) |
90 | {Serial.print(i & (128 >> n) ? 1 : 0);} |
91 | if (!fNoLN) |
92 | {Serial.println("");} |
93 | }
|
94 | |
95 | /*************************** I N I T I A L I S I E R U N G ***********************************/
|
96 | |
97 | void setup() { |
98 | |
99 | /****************************************/
|
100 | /* Serielle Schnittstelle und Admintool */
|
101 | /****************************************/
|
102 | PrintMillisDelta(0, 1); // Zeitmesser 0 initialisieren |
103 | Serial.begin(9600); // Geschwindigkeit der Schnittstelle zum PC |
104 | delay(250); // kurz warten |
105 | Serial.println("(0) Hallo Meister"); |
106 | |
107 | /*************************************/
|
108 | /* LM: LED-Management initialisieren */
|
109 | /*************************************/
|
110 | for (byte ix=0; ix<LM_COUNT; ix++) { |
111 | tLM *p; // Hilfspointer |
112 | p = &LM[ix]; // Zeiger auf Arbeitsbereich |
113 | |
114 | // LM: Allgemeine Einstellungen
|
115 | p->TPrescaler = 0; // Timer-Prescaler |
116 | p->InUse = 0; // ISR-Sperrflag |
117 | |
118 | // LM: Spezifische Einstellungen
|
119 | switch (ix) { |
120 | case LM_01_IDX: // Kanal 1 |
121 | p->Pin = LM_01_PIN; // Pin-Nr. |
122 | break; |
123 | case LM_02_IDX: // Kanal 2 |
124 | p->Pin = LM_02_PIN; // Pin-Nr. |
125 | break; |
126 | case LM_03_IDX: // Kanal 3 |
127 | p->Pin = LM_03_PIN; // Pin-Nr. |
128 | break; |
129 | case LM_04_IDX: // Kanal 4 |
130 | p->Pin = LM_04_PIN; // Pin-Nr. |
131 | break; |
132 | default:
|
133 | p->Pin = NC; // Ungültiger Index, keine Pin-Nr. |
134 | } // Ende Spezifische Einstellungen |
135 | |
136 | // LM: Pin als Ausgang definieren
|
137 | if (p->Pin != NC) { // Nur wenn eine Pin definiert ist |
138 | pinMode(p->Pin, OUTPUT); // Pin auf OUTPUT schalten |
139 | digitalWrite(p->Pin, LOW); // LED ausschalten |
140 | } // Ende Pin als Ausgang definieren |
141 | |
142 | } // Ende LED-Management initialisieren |
143 | |
144 | /**************************************************/
|
145 | /* SM: Interrrupt konfigurieren und Timer starten */
|
146 | /**************************************************/
|
147 | cli(); // Interrupts sperren |
148 | TCNT2 = 0; // Timer Counter 2 |
149 | TCCR2A = 0; // Timer Counter Controll Register A löschen |
150 | TCCR2B = 0; // Timer Counter Controll Register B löschen |
151 | OCR2A = (16000000.0/(1024.0*MAIN_CLK))+OCR2A_KOR; // Vergleichswert in Output Compare Reg. A |
152 | TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20); // Prescaler 1024 |
153 | TCCR2A |= (1<<WGM21); // CTC-Mode ein |
154 | TIMSK2 |= (1<<OCIE2A); // Output Compare A Match Interrupt Enable |
155 | sei(); // Interrupts erlauben |
156 | |
157 | /**************************************/
|
158 | /* Vordergrundprogramm initialisieren */
|
159 | /**************************************/
|
160 | Serial.print("(0) HG-Setup beendet. Dauer: "); |
161 | PrintMillisDelta(0); |
162 | mySetup(); // VG-Setup |
163 | Serial.print("(0) VG-Setup beendet. Dauer: "); |
164 | PrintMillisDelta(0); |
165 | |
166 | } // Ende setup() |
167 | |
168 | /*************************** T I M E R E V E N T ********************************************/
|
169 | |
170 | /***************************************/
|
171 | /* Timer 2 Interrrupt 160x pro Sekunde */
|
172 | /***************************************/
|
173 | ISR(TIMER2_COMPA_vect) { |
174 | |
175 | /****************/
|
176 | /* Nur zum Test */
|
177 | /****************/
|
178 | sei(); // Das ist eine Männer-ISR! |
179 | |
180 | /**********************/
|
181 | /* LM: LEDs versorgen */
|
182 | /**********************/
|
183 | for (byte ix=0; ix<LM_COUNT; ix++) { |
184 | tLM *p; // Hilfspointer |
185 | p = &LM[ix]; // Zeiger auf Arbeitsbereich |
186 | |
187 | // LM: Kanal aktiviert?
|
188 | if (p->TPrescaler == 0) {/*schon fertig*/} // Prescaler=0 sperrt die Ausführung |
189 | |
190 | // LM: Kanal gesperrt?
|
191 | else if (p->InUse) {/*besetzt*/} // ISR-Sperrflag: Kanal ist in Bearbeitung |
192 | |
193 | // LM: Prescaler abgelaufen?
|
194 | else if (++p->TCounter >= p->TPrescaler) { // Der Timerevent verwendet einen Prescaler |
195 | p->TCounter = 0; // Auslösewert erreicht: Counter löschen |
196 | |
197 | // LM: Kanal sperren
|
198 | p->InUse = 1; // Nicht stören |
199 | |
200 | // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
201 | // Eingefügt zum Testen des Timers
|
202 | if (ix == LED_GELB) { // Kanal der gelben LED |
203 | PrintMillisDelta(2, 1); // blockieren, um zu sehen, |
204 | Serial.println("(2) Gelbe LED 5 Sek blockiert"); // ob die anderen LEDs noch |
205 | word iTS = millis() + 5000; // blinken. Sie blinken nur |
206 | while(iTS > millis()); // dann, wenn zu ISR-Begin |
207 | Serial.print("(2) Gelbe LED wieder frei. Dauer: "); // ein sei() eingefügt wurde. |
208 | PrintMillisDelta(2); |
209 | }
|
210 | // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
211 | |
212 | // LM: 8 Bits ausgegeben?
|
213 | if (++p->BitPointer > 8) // Wenn 8 Bits ausgegeben sind |
214 | {p->BitPointer = 0;} // Bitzeiger wieder auf 0 |
215 | |
216 | // LM: LED ansteuern
|
217 | byte f = p->Pattern & (1 << p->BitPointer); // Bit auslesen |
218 | digitalWrite(p->Pin, f); // LED umschalten |
219 | |
220 | // LM: Kanalsperre aufheben
|
221 | p->InUse = 0; // Kanal wieder freigeben |
222 | |
223 | } // Ende Prescaler abgelaufen? |
224 | } // Ende LEDs versorgen |
225 | } // Ende ISR |
226 | |
227 | /*************************** B A S I S F U N K T I O N E N ***********************************/
|
228 | |
229 | /******************************************************************/
|
230 | /* LM: Konfiguriert einen LED-Kanal */
|
231 | /* */
|
232 | /* iKanal : Nummer der LED (Tabellenindex, beginnend ab 0) */
|
233 | /* iPattern : Bitmuster */
|
234 | /* iPrescaler : Blinkgeschwindigkeit Standard: 8 Bit pro Sekunde) */
|
235 | /******************************************************************/
|
236 | void LM_SetLED(byte iKanal, |
237 | byte iPattern, |
238 | word iPrescaler = LM_CLOCK) { |
239 | |
240 | tLM *p; // Hilfspointer |
241 | p = &LM[iKanal]; // Zeiger auf Arbeitsbereich |
242 | |
243 | // LM: Kanal konfigurieren
|
244 | cli(); // Interrupts verbieten |
245 | p->Pattern = iPattern; // LED-Bitmuster |
246 | p->BitPointer = 0; // Bit-Zeiger auf 0 |
247 | p->TCounter = 0; // Prescaler-Counter löschen |
248 | p->TPrescaler = iPrescaler; // Prescaler übergeben |
249 | sei(); // Interrupts erlauben |
250 | }
|
251 | |
252 | /*************************** V O R D E R G R U N D R O G R A M M *****************************/
|
253 | |
254 | void mySetup() { |
255 | LM_SetLED(LED_ROT, 0b11110000); |
256 | LM_SetLED(LED_GELB, 0b11001100); |
257 | LM_SetLED(LED_GRUEN, 0b10101010); |
258 | |
259 | Serial.println("(1) Start delay(1000)"); |
260 | PrintMillisDelta(1, 1); |
261 | delay(1000); |
262 | Serial.print("(1) Ende delay(1000). Dauer: "); |
263 | PrintMillisDelta(1); |
264 | |
265 | LM_SetLED(LED_GRUEN, 0b00001111); |
266 | }
|
267 | |
268 | void loop() { |
269 | }
|
4 LEDs anschließen und die Portnummern in DEFINES eintragen. Dann einfach laufen lassen und auch den Monitor beobachten.
Arduino Fanboy D. schrieb: > Roth schrieb: >> Das hieße ja eigentlich, dass nur 1 Takt des Timers "hängt", und neue >> Takte noch ausgeführt werden. Code, der länger als 1 ISR-Takt dauert, >> ist natürlich mit static zu sperren , damit kein neuer Takt dem >> aktuellen in den Rücken fällt > Auch eine lustige Geschichte! > Dieses mal sogar mit der Empfehlung, mit static zu sperren. > > Würdest du bitte den Absatz nochmal überdenken... Der Arduino Fanboy, wenn er nicht so frech wäre, würde vielleicht sogar positiv glänzen in der Welt. Aber so freut sich nur der Gilb. Immerhin hat der Fanboy ja rausgefunden, dass es ohne sei() nicht geht. Und das habe ich in der Tat übersehen bzw. die cli()...sei() Systematik als verschachtelbares Konstrukt eingeschätzt - was es aber nicht ist-.
Roth schrieb: > Immerhin hat der Fanboy ja rausgefunden, dass es ohne sei() nicht geht. Das brauche ich nicht herauszufinden! Sowas weiß ich! Denn meine Kompetenz in Sachen AVR beruht auf Wissen und Erfahrung. Deine Kompetenz liegt offensichtlich eher im Verbohrt sein und in einer lebhaften Einbildungskraft, gepaart mit einer beachtenswerten Überheblichkeit und Arroganz. Roth schrieb: > Der Arduino Fanboy, wenn er nicht so frech wäre, Erinnere dich an unsere ersten Begegnungen.... Wie du mich da herabgewürdigt hast, nur weil du zu blöd/borniert/beschränkt warst meine Antworten zu kapieren? Ich bin ein Spiegel! Du hast Verachtung gesät, und du wirst Verachtung ernten. Roth schrieb: > Und schon ist die Ruhe vorbei. Bitte gehe doch wieder weg und pöbel in > anderen Themen. danke. Ist das freundlich? Nee, oder? Wie kannst du dich dann wundern, darüber mokieren, dass ich dir einen Tick härter komme, als ich es bei anderen tue?
Roth schrieb: > Weil ich es aus Assembler gewohnt bin, im Timerinterrupt "ohne Netz" zu > arbeiten (also Taktgeber rattert weiter, auch wenn gerade ein Event > bearbeitet wird), ist mir das nicht aufgefallen, dass ISRs beim Arduino > standardmäßig gesperrt sind, wenn "drinnen" gerade was ausgeführt wird. 1) Auch, wenn man in Asm programmiert, sind beim AVR8 in einer ISR natürlich standardmäßig die Interrupts gesperrt, denn das ist eine Eigenschaft der Maschine und nicht der Sprache. Dementsprechend kann man auch in allen Sprachen das Verhalten ändern, indem man irgendwo in der ISR SREG_I setzt, sei es durch eine sei-Instruktion oder auch durch irgendein anderes Konstrukt. Dann kann nachfolgender Code der ISR durch einen Interrupt unterbrochen werden. Das Problem dabei ist nur: es kann auch der eigene sein, was entweder einen Mechanismus erfordert, genau nur diesen zu sperren oder ein genau durchdachtes (und korrekt umgesetztes) Timing aller ISRs des Systems. Ansonsten droht Stackunterlauf. 2) Ob die Timer laufen oder nicht, hat mit Interrupts überhaupt nix zu schaffen. Die laufen, wenn einmal gestartet, immer lustig weiter, ganz egal, ob die Interrupts gesperrt sind oder nicht. Auch wieder: Eigenschaft der Maschine, nicht der Sprache. Interrupts braucht man nur, um auf Timerereignisse mit eigenem Code reagieren zu können. Für die reine Ausgabe über die OC-Anschlüsse braucht man sie nicht, da ist die MCU überhaupt nicht involviert. Das hast du offensichtlich niemals kapiert.
Arduino Fanboy D. schrieb: > Ich bin ein Spiegel! ja genau. https://newstopaktuell.files.wordpress.com/2014/02/fluoride-und-so-lc3bcgt-der-spiegel.jpg
Delays sind in Arduino innerhalb von ISRs gesperrt? Oh je noch ein Grund das nicht zu benutzen. Ja ja man darf einem Interrupt nicht unnötig verzögern, bla bla, weiß wirklich jeder. Mir fallen trzd auf Anhieb eine handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt sinnvoll u okay ist. Was bringt eine Entwicklungsumgebung die mir Sachen verbietet nur weil einige damit nicht umgehen können?!
Max M. schrieb: > Was bringt eine Entwicklungsumgebung die mir Sachen verbietet > nur weil einige damit nicht umgehen können?! Arduino ist keine Entwicklungsumgebung sondern eine Krücke für sonst nicht Gehfähige.
Max M. schrieb: > Delays sind in Arduino innerhalb von ISRs gesperrt? Oh je noch ein > Grund das nicht zu benutzen. Ja ja man darf einem Interrupt nicht > unnötig verzögern, bla bla, weiß wirklich jeder. Mir fallen trzd auf > Anhieb eine handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt > sinnvoll u okay ist. Was bringt eine Entwicklungsumgebung die mir Sachen > verbietet nur weil einige damit nicht umgehen können?! Viel verstehst du auch nicht.... Und wenn, dann auch gerne das falsche.
Beitrag #5628192 wurde von einem Moderator gelöscht.
Hallo, Max M. schrieb: > Mir fallen trzd auf Anhieb eine > handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt sinnvoll u > okay ist. dann mach es doch einfach. µs wird nicht per Timer realisiert, geht also auch in einer ISR in der ArduinoIDE. Du kannst auch gern __asm__("nop\n\t"); benutzen, niemand hindert Dich daran Gruß aus Berlin Michael
:
Bearbeitet durch User
Passduuff schrieb im Beitrag #5628192: > Diese langweilige Laberei von "Krücke" ist selbst eine Krücke. > Und zwar eione für nicht GehWILLIGE bezieht sich wohl eher auf die ide denn auf die hardware. lässt sich aber aus dem kontext erschliessen...
Max M. schrieb: > Mir fallen trzd auf Anhieb eine > handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt sinnvoll u > okay ist. Mir nicht. Wer im Interrupt Zeit hat zu warten, für den ist der Interrupt wahrscheinlich nicht die richtige Lösung sondern bestenfalls ein Notbehelf. Uff Passe schrieb: > Arduino ist keine Entwicklungsumgebung sondern eine Krücke > für sonst nicht Gehfähige. Der Erfolg des Arduino zeigt wohl offensichtlich, dass es sehr viele, nach deine Definition, nicht Gehfähige gibt ;) Ich hab mich auch nicht wirklich mit der Arduino IDE anfreunden können, finde aber das Konzept einfach großartig und gelungen. Als Krücke würde ich Arduino nicht bezeichnen.
:
Bearbeitet durch User
Ich frage mich nachdem das Programm gesehen habe wofür man zum LED blinken überhaupt zusätzliche Timer Interrupts benötigt. Das kann man alles mit millis und Merkern erschlagen.
Veit D. schrieb: > Ich frage mich nachdem das Programm gesehen habe wofür man zum LED > blinken überhaupt zusätzliche Timer Interrupts benötigt. Das kann man > alles mit millis und Merkern erschlagen. Vielleicht weil man beginnt sich mit Interrupts zu beschäftigen. So hab ich auch den Einstieg in Interrupts gemacht bei mir: Die LED nicht mehr via delay blinken lassen sondern via ISR ;)
Ich hoffe nur zum lernen, nicht das es Gewohnheit wird für jeden Mist einen Interrupt zu verwenden.
Veit D. schrieb: > Ich hoffe nur zum lernen, nicht das es Gewohnheit wird für jeden Mist > einen Interrupt zu verwenden. Naja, muss ja nicht unbedingt schlecht sein. Ich hab fast nur noch Interrupt gesteuerte Programmabläufe.
Passduuff schrieb im Beitrag #5628192: > Uff Passe schrieb: >> Arduino ist keine Entwicklungsumgebung sondern eine Krücke >> für sonst nicht Gehfähige. > > Sagt wer? > Arduino ist eine großartige Einstiegshilfe für Menschen, die keinen > Lötkolben haben oder keine Lust oder keinen Sinn darin sehen, sich erst > ein Board zu bauen, bevor sie ein paar Zeilen Programmcode laufen lassen > können. Diese langweilige Laberei von "Krücke" ist selbst eine Krücke. > Und zwar eione für nicht GehWILLIGE Dafür gibt es Evaluation-Boards. Arduino ist eher für Leute die von µCs nicht die geringste Ahnung haben und einfach irgendwie irgendwas zum laufen kriegen wollen, ohne so richtig zu verstehen was da eigentlich los ist. Wer zu Arduino greift weil er einfach nicht löten will hat definitiv iwas falsch verstanden.
Michael U. schrieb: > Hallo, > > Max M. schrieb: >> Mir fallen trzd auf Anhieb eine >> handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt sinnvoll u >> okay ist. > > dann mach es doch einfach. µs wird nicht per Timer realisiert, geht also > auch in einer ISR in der ArduinoIDE. > Du kannst auch gern __asm__("nop\n\t"); benutzen, niemand hindert Dich > daran > > Gruß aus Berlin > Michael Also soll ich in meinem mit 20 MHz getakteten Atmega 40x die Anweisung _NOP(); schreiben anstatt _delay_us(2);? Na glückwunsch, da hat aber jmd. Ahnung wie man sich unübersichtliche Quelltexte bastelt..
M. K. schrieb: > Max M. schrieb: >> Mir fallen trzd auf Anhieb eine >> handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt sinnvoll u >> okay ist. > > Mir nicht. Wer im Interrupt Zeit hat zu warten, für den ist der > Interrupt wahrscheinlich nicht die richtige Lösung sondern bestenfalls > ein Notbehelf. Mir schon.
Hannes J. schrieb: > M. K. schrieb: >> Max M. schrieb: >>> Mir fallen trzd auf Anhieb eine >>> handvoll Fälle ein, wo ein Delay von wenigen µs im Interrupt sinnvoll u >>> okay ist. >> >> Mir nicht. Wer im Interrupt Zeit hat zu warten, für den ist der >> Interrupt wahrscheinlich nicht die richtige Lösung sondern bestenfalls >> ein Notbehelf. > > Mir schon. Damit wollte ich lediglich ausdrücken: Wer im Interrupt mit delay_us oder delay_ms warten will, für den gibt es höchstwahrscheinlich eine bessere Lösung als in der ISR zu warten. Natürlich kann ich mir auch vorstellen mithilfe von delay in einer ISR zu warten, aber idR ist das eine denkbar schlechte Lösung.
M. K. schrieb: > Damit wollte ich lediglich ausdrücken: Wer im Interrupt mit delay_us > oder delay_ms warten will, für den gibt es höchstwahrscheinlich eine > bessere Lösung als in der ISR zu warten. Oft ist das so, wahrscheinlich sogar meistens, aber nicht immer. > Natürlich kann ich mir auch vorstellen mithilfe von delay in einer ISR > zu warten, aber idR ist das eine denkbar schlechte Lösung. Manchmal ist es sogar die einzig mögliche, um ein bestimmtes Ziel zu erreichen. Nehmen wir z.B. mal an, du wolltest auf einem AVR8 (ohne dedizierte USB-Hardware) einen USB-Host umsetzen, es soll aber in gewissem Maße möglich bleiben, konkurrierende Interrupts zu betreiben. Oder, Variante praktisch der gleichen Aufgabe: Ausgabe an einen VGA-Monitor, ebenfalls mit der Möglichkeit, konkurrierende Interrupts zu betreiben. In beiden Fällen führen die Anforderungen des zu erzeugenden Signals fast zwingend dazu, dass du in der ISR warten musst. OK, ist dann kein dummes Delay, sondern ein komplizierteres Konstrukt mit dem Ziel, die variable Latenz der Konkurrenz aufzuessen, wenn diese sie gerade nicht benötigt hat, aber es ist und bleibt Warten in der ISR durch Verbrennung von Rechenzeit. Ja, man könnte in beiden Fällen sicherlich mit geeigneter Hardware (insbesondere USART im SPI-Mode) dasselbe Ergebnis auch ohne dieses Warten erzielen, dabei entstehen aber zwei Probleme: 1) nicht jeder AVR8 verfügt überhaupt über derartige Hardware und 2) schränkt das typischerweise die Auswahl der Pins ganz erheblich ein.
Hannes J. schrieb: > Dafür gibt es Evaluation-Boards. Arduino ist eher für Leute die von µCs > nicht die geringste Ahnung haben und einfach irgendwie irgendwas zum > laufen kriegen wollen, ohne so richtig zu verstehen was da eigentlich > los ist. Das sehe ich anders. Ich nutze "Arduino" auf 2erlei Arten: 1. Die Hardware, prima Steckbrett-geeignet (Nano, Micro) 2. Die Entwicklungsumgebung mit div. Librarys, mit welcher neue Sensoren etc. sich schnell einbinden und testen lassen Für Q&D - und durchaus auch für ernstere Anwendungen ohne zeitkritische Teile reicht es aus meiner Sicht vollauf aus. Es zwingt mich niemand, millis() etc. zu nutzen. Wenn ich die volle Kontrolle über Interrupts, Timer etc. haben will nutze ich Variante 1 bzw. andere, auch steckbrettfähige (für die Entwicklung), MC's. Um irgendeinen Sensor etc. auf die Schnelle auszuprobieren (auch auf dem Steckbrett) nutze ich oft die Entwicklungsumgebung / Librarys. Warum auch nicht - geht schnell und man kann das Verhalten recht gut einschätzen. Zeitkritische Anwendungen entwickle ich in C (im Atmel Studio - ich weiß, ist verpönt bei manchen) ggf. mit Inline-Assembler. Reinen Assembler habe ich sei Jahren nicht mehr genutzt (@ C-Hater - ich bin auch kein professioneller MC-Entwickler). Wenn ich es brauche skaliere ich halt die Hardware/den MC hoch - es ist nur für mich (keine Serienfertigung) - und der Weg ist das Ziel :-) Ein wenig Ahnung habe ich schon - daher distanziere ich mich von Hannes Aussage.
Hannes J. schrieb: > Also soll ich in meinem mit 20 MHz getakteten Atmega 40x die Anweisung > _NOP(); schreiben anstatt _delay_us(2);? Wer sagt das? Das kannst du tun! Aber von "sollen" war keine Rede. Auf Arduino steht die AVR C-Lib vollumfänglich zur Verfügung. Die gleichen delay Funktionen, wie im Atmel Studio. Zusätzlich noch die Arduino eigenen Delay Funktionen. Und diese, nur diese, benötigen selber Timer Interrupts. Darum funktionieren sie nicht in ISR. Das ist logisch nachvollziehbar. Das ist zwangsläufig so. Das ist dokumentiert. Max M. schrieb: > Was bringt eine Entwicklungsumgebung die mir Sachen verbietet > nur weil einige damit nicht umgehen können?! Das ist Unsinn! Da ist nichts verboten. -- Es gibt allerdings noch einen Grund, warum man kein Arduino delay() in ISR nutzen sollte, selbst wenn man die Interrupts händisch aktiviert. delay() ruft intern yield() auf. Auch bei AVRs. Einfach um eine Möglichkeit zu haben, die in delay() zu verplempernde Zeit noch anders nutzen zu können. Hat man zufällig ein Multitasking System unter den Fingern (ja, manche Arduino Dinger haben das, sind so) stehen die Chancen sehr gut, dass man dabei auf die Fresse fällt. Mit Karracho.
Veit D. schrieb: > Ich hoffe nur zum lernen, nicht das es Gewohnheit wird für jeden Mist > einen Interrupt zu verwenden. Veit D. schrieb: > Ich frage mich nachdem das Programm gesehen habe wofür man zum LED > blinken überhaupt zusätzliche Timer Interrupts benötigt. Das kann man > alles mit millis und Merkern erschlagen. Kannst du den Code "mit millis und Merkern" bitte mal veröffentlichen? Das sind ja bestimmt nur ein paar Zeilen. Danke.
Hannes J. schrieb: > Passduuff schrieb im Beitrag #5628192: >> Uff Passe schrieb: >>> Arduino ist keine Entwicklungsumgebung sondern eine Krücke >>> für sonst nicht Gehfähige. >> >> Sagt wer? >> Arduino ist eine großartige Einstiegshilfe für Menschen, die keinen >> Lötkolben haben oder keine Lust oder keinen Sinn darin sehen, sich erst >> ein Board zu bauen, bevor sie ein paar Zeilen Programmcode laufen lassen >> können. Diese langweilige Laberei von "Krücke" ist selbst eine Krücke. >> Und zwar eione für nicht GehWILLIGE > > Dafür gibt es Evaluation-Boards. Arduino ist eher für Leute die von µCs > nicht die geringste Ahnung haben und einfach irgendwie irgendwas zum > laufen kriegen wollen, ohne so richtig zu verstehen was da eigentlich > los ist. Wer zu Arduino greift weil er einfach nicht löten will hat > definitiv iwas falsch verstanden. Mir ging es so mit dem VW New Beetle. Er mag sein wie er will, aber niemals ein "neuer Käufer". Er hat nicht mal danebengestanden. Kult wo er hingehört. New Beetle fahren ist kein Kult, sondern eine alternative Lebenseinstellung, die zu spät kommt. Daher fahren das Ding auch oft alte Frauen mit gefärbten Haaren. KLISCHEE /OFF Trotzdem muss man den Arduino nicht anspucken. Ich verwende das Teil auch, um billig und schnell ein paar "Gehversuche" mit einem C-programierbaren µC zu machen. Obwohl ich mit anderen Typen zu tun hatte (MCS51, PIC, Z80) und die Platinen auch gebaut habe. Aber das ist Jahrzehnte her und ich brauchte es dann einfach (beruflich) nicht mehr. Aktuell will ich "nur" ein (privates) Projekt verwirklichen und muss mir nicht mehr beweisen, dass ich Platinen herstellen und einenn µC zum Laufen bringen kann. Ich kann es, und das weiß ich. Also hört auf (gähn), alle Arduino-Verwender als Dilettanten oder Deppen hinzustellen. Das stimmt vlt hier und da, aber jeder hat auch das recht, nur spielen zu wollen. Man kann den Spieß ja auch umdrehen. Ein Tiefseetaucher, der im Schwimmbad mit seinem Meckern allen auf den Geist geht, dass das Dreimeterbecken "nicht tief genug" wäre, ist irgendwie dasselbe in Grün....
Roth schrieb: > Man kann den Spieß ja auch umdrehen. Ein Tiefseetaucher, der > im Schwimmbad mit seinem Meckern allen auf den Geist geht, dass das > Dreimeterbecken "nicht tief genug" wäre, ist irgendwie dasselbe in > Grün.... Du bist eindeutig kein Taucher.
Der Spiegel schrub im Beitrag #5628706: > Hat man zufällig ein Multitasking System unter den Fingern (ja, manche > Arduino Dinger haben das, sind so) stehen die Chancen sehr gut, dass man > dabei auf die Fresse fällt. > Mit Karracho. Du scheinst dich mit diesem "Karracho" ja bestens auszukennen. Bevor du in deiner eingefleischten Funktion als Schreibschläger wieder in Hormonwallungen und Schweißschüben triggerst, überlege erst. Wenn du das überhaupt kannst. Übertrage deine schlimmen Erfahrungen der Vergangenheit, die wohl mehr dem Gefrickel denn einem Lernen geschuldet sind, nicht auf alle anderen. Nur weil du (ggf. unbewusst) Mitleider suchst. Das interessiert hier niemanden. Ich z.B. bin Einsteiger in C. Und ich schreibe auch (bei jeder Gelegenheit), dass ich C-Einsteiger bin. Ich stelle Fragen, weil ich etwas nicht weiß. Und dann kommt "der Spiegel" und haut mir die Fragen um die Ohren und dass ich "zu dumm bin", weil ich Fragen stellen ... dazu fällt mir wirklich nichts mehr ein außer Kopfschütteln (und ein gewissen Mitleid).
Dieter F. schrieb: > Roth schrieb: >> Man kann den Spieß ja auch umdrehen. Ein Tiefseetaucher, der >> im Schwimmbad mit seinem Meckern allen auf den Geist geht, dass das >> Dreimeterbecken "nicht tief genug" wäre, ist irgendwie dasselbe in >> Grün.... > > Du bist eindeutig kein Taucher. Richtig. Ich bin der, der zum Schwimmen ins Schwimmbad geht. Und nun suche die Taucher.
Roth schrieb: > Und nun > suche die Taucher. Brauche ich nicht - ich tauche selbst. Aber nicht im Schwimmbad - das ist nur für Anfänger (ist das etwa eine Analogie ?).
Beitrag #5628958 wurde von einem Moderator gelöscht.
Könnte es sein, dass Verachtung die höchste Form der Anerkennung ist, zu der du fähig bist? Denn, was mich wundert: Anstatt dankbar zu sein, dass ich dich auf einen Irrtum in deinen Überlegungen hingewiesen habe, mühst du dich damit ab den Boten schlecht aussehen zu lassen.
Roth schrieb: > Kannst du den Code "mit millis und Merkern" bitte mal veröffentlichen? > Das sind ja bestimmt nur ein paar Zeilen. Danke. Wenn ich den Thread verfolge und du jeden niedermachst der dir über den Weg läuft, der dir die Sache über Interrupts richtig erklären möchte, dann sehe ich mich nicht gezwungen die nur irgendeinen Codeschnipsel zu zeigen.
Arduino Fanboy D. schrieb: > Anstatt dankbar zu sein, dass ich dich auf einen Irrtum in deinen > Überlegungen hingewiesen habe, mühst du dich damit ab den Boten schlecht > aussehen zu lassen. Du kleiner Schreibschläger hast mich auf was hingewiesen? Aha. Deine kindlichen Fantastereien in Ehren, mit der Keule in der Hand (du bist Conan oder?), aber werde bald mal erwachsen.
Veit D. schrieb: > Roth schrieb: >> Kannst du den Code "mit millis und Merkern" bitte mal veröffentlichen? >> Das sind ja bestimmt nur ein paar Zeilen. Danke. > > Wenn ich den Thread verfolge und du jeden niedermachst der dir über den > Weg läuft, der dir die Sache über Interrupts richtig erklären möchte, > dann sehe ich mich nicht gezwungen die nur irgendeinen Codeschnipsel zu > zeigen. Auch das ist nicht wahr. Der Arduino Fanboy und sein Gefolge (bzw. Handpuppen) sind nicht "jeder". Oder gehörst du auch zu dem Kreis der Online Basher? Schade dass solche Schreibschläger sich hier tummeln und die Mods dagegen offenbar nichts unternehmen können. Denn die absolut überwiegende Mehrheit der Mitglieder sind angenehm und hilfsbereit. Was ihr wenigen durch eure Nachstellungen kaputt macht. Stört übrigens nicht nur mich und die meisten gehen dann weg. Ich antworte eben, weil ihr das am wenigsten ertragen könnt. Feiges, anonymes Schreibschlägerpack!
Hallo, mal ganz langsam, komme mal wieder runter. Wenn du dich irgendwann beruhigt hast wirst du feststellen das wir hier nicht anonym unterwegs sind. Zumindestens nicht so anonym wie du. Und wenn du alles mal sacken lassen und nicht immer mit der Keule losgehen würdest, dann würdest du alle Hilfestellungen hoffentlich anders wahrnehmen und verstehen. Und wegen "Online Basher". Wenn du so fragst und eine ehrliche Antwort erwartest, dann muss ich dir sagen ich sehe nur einen. Und das sind nicht die anderen und ich auch nicht.
Roth schrieb im Beitrag #5628958:
> Du bist völlig neben der Kappe und merkst es nicht.
Genug jetzt!