Forum: Mikrocontroller und Digitale Elektronik delay() in Timer-Event ISR (Arduino)


von Roth (Gast)


Lesenswert?

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
von MiMa (Gast)


Lesenswert?

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..

von jois3 (Gast)


Lesenswert?

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

von Dr. Sommer (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

"Ich wollte aber eigentlich wissen"  ... wollte ich eigentlich 
schreiben.

von Peter D. (peda)


Lesenswert?

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().

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von ÄXl (Gast)


Lesenswert?

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?

von Einer K. (Gast)


Lesenswert?

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!

von Roth (Gast)


Lesenswert?

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,.

von Roth (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Unfug!

Und schon ist die Ruhe vorbei. Bitte gehe doch wieder weg und pöbel in 
anderen Themen. danke.

von Roth (Gast)


Lesenswert?

Ä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

von Georg M. (g_m)


Lesenswert?

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/

von MiMa (Gast)


Lesenswert?

> 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.

von Einer K. (Gast)


Lesenswert?

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...

von ÄXl (Gast)


Lesenswert?

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?

von Roth (Gast)


Lesenswert?

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 ;)

von Wolfgang (Gast)


Lesenswert?

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.

von Roth (Gast)


Angehängte Dateien:

Lesenswert?

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
}

von Roth (Gast)


Lesenswert?

4 LEDs anschließen und die Portnummern in DEFINES eintragen. Dann 
einfach laufen lassen und auch den Monitor beobachten.

von Roth (Gast)


Lesenswert?

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-.

von Einer K. (Gast)


Lesenswert?

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?

von c-hater (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?


von Max M. (max_m250)


Lesenswert?

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?!

von Uff Passe (Gast)


Lesenswert?

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.

von Ich (Gast)


Lesenswert?

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.
von Michael U. (amiga)


Lesenswert?

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
von Sven K. (quotschmacher)


Lesenswert?

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...

von M. K. (sylaina)


Lesenswert?

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
von Veit D. (devil-elec)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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 ;)

von Veit D. (devil-elec)


Lesenswert?

Ich hoffe nur zum lernen, nicht das es Gewohnheit wird für jeden Mist 
einen Interrupt zu verwenden.

von M. K. (sylaina)


Lesenswert?

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.

von Hannes J. (hannes_j)


Lesenswert?

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.

von Hannes J. (hannes_j)


Lesenswert?

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..

von Hannes J. (hannes_j)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

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.

von Dieter F. (Gast)


Lesenswert?

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.

von Einer K. (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

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....

von Dieter F. (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

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).

von Roth (Gast)


Lesenswert?

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.

von Dieter F. (Gast)


Lesenswert?

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 ?).

von Einer K. (Gast)


Lesenswert?

Roth schrieb:
> Du scheinst ...
Offensichtlich hast du den Text noch nicht mal im Ansatz erfasst.

Beitrag #5628958 wurde von einem Moderator gelöscht.
von Einer K. (Gast)


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

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.

von Roth (Gast)


Lesenswert?

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!

von Veit D. (devil-elec)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Roth schrieb im Beitrag #5628958:
> Du bist völlig neben der Kappe und merkst es nicht.
Genug jetzt!

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.