Drehzahlregelung Verbrennungsmotor

Einen wunderschönen guten morgen liebes Forum :slight_smile:

Ich habe mal wieder ein Projektchen, und bräuchte mal einen Denkanstoß, vielleicht habt ihr einen Gedanken für mich!

Konkret gehts um meinen Rasenmäher. Momentan hat der Motor eine Fliehkraftgesteuerte Drehzahlregelung. Das bedeutet: Mit dem Gaszug spanne ich nur eine Feder, die dann mit einer gewissen Kraft am Hebel der Drosselklappe zieht und diese somit ganz öffnet (vollgas). An die Kurbelwelle ist nun ein Fliehkraftregler gekoppelt, der mit steigender Drehzahl einen Hebel bewegt. Dieser Hebel drückt nun die Drosselklappe zurück richtung geschlossen. Wenn das alles gut justiert ist, pendelt sich die Drehzahl sauber ein auf einen Wert den ich am Gaszug einstellen kann, und reagiert somit auf Belastungen.
Und hier ist auch die Crux, das ganze ist dermaßen schlecht zu justieren, fehleranfällig und hakelig, ganz besonders weil der Motor mit der Regelung doch schon in die Jahre gekommen ist, und sich dadurch natürlich auch die Charakteristik ändert.

Nun hab ich mir in den Kopf gesetzt, den ganzen Klapperatismus durch einen Arduino, einen Hallgeber und einen Servo zu ersetzen.
Man könnte sich natürlich die Arbeit sparen und einfach einen neuen Rasenmäher kaufen, aber das wäre langweilig ^^

Nun zum eigentlichen Projekt:
Kernstück ist ein Arduino Nano mit einem Mega328p.
Die Drehzahl wird mit einem Hallgeber direkt an der Schwungscheibe abgenommen, in der ja schon ein Magnet integriert ist (für die Zündspule), es ergibt sich ein Impuls pro Umdrehung.
Es wird 2 Killswiches geben, einer der das ganze System ausschaltet, und einer der über ein einfaches Relais die Motorzündung abschaltet (bei Spannungsabfall lässt das Relais los -> Zündung unterbrochen -> Motor aus).
Mit 2 Tastern wird die Solldrehzahl in Schritten von 100 oder 200 upm eingestellt (Hier wäre auch ein Poti denkbar).
Als Display ist eine 7-Segmentanzeige vorgesehen, die mit einem MAX7219 angesteuert wird. Davon sollen 4 Digits die exakte Ist-Drehzahl anzeigen, 2 Digits zeigen die Eingestellte Soll-Drehzahl an, und die restlichen 2 Digits werden ausgelötet, dafür kommt ein Bargraph als Lastanzeige dran (der letzten Endes nur die Drosselklappenstellung widerspiegelt). Die Digits auf dem Display möchte ich alle 500ms aktualisieren, die Lastanzeige alle 100ms, mit dem Durchschnittswert aus der jeweiligen Zeitspanne.
Die Drosselklappe wird dann einfach direkt über ein kleines Servo angesteuert.

Folgendes ist schon realisiert:
Der Arduino liest den Hallgeber aus und zeigt die exakte Drehzahl auf dem Display an. Funktioniert bis 1000upm problemlos, mehr Drehzahl gibt mein Akkuschrauber leider nicht her, also werde ich das ganze bald in den Rasenmäher einbauen müssen :wink:

Die einzelnen Elemente an sich stellen kein Problem für mich dar, Errechnen der Drehzahl, Ansteuerung des Displays, sind gar kein Problem, und auch ein Servo steuern sollte unproblematisch sein (auch wenn ich das noch nie gemacht hab).

Meine Gedankenblockade liegt nun eher im Regelkreis, so ein Motor reagiert ja auch etwas verzögert, und nicht so exakt (wobei es ja auf 50 Umdrehungen hin oder her nicht ankommt)
Ich bin für jeden Gedankeninput dankbar, und wenn er noch so abwegig oder unausgegoren scheint! :slight_smile:

Ein weiteres Problem befürchte ich im Timing: bei 4000upm (soviel muss auf jeden Fall messbar sein, das ist so die obere Grenze im normalen Mähbetrieb, allerdings kann der Motor auch locker mehr, was nach Möglichkeit auch noch gemessen werden sollte) dauert jede Umdrehung gerademal 15ms, wenn jetzt der Arduino recht beschäftigt ist und ständig Umdrehungen übersieht wäre das ungünstig... Vielleicht könnt ihr ja meine Sorgen diesbezüglich ein bisschen zerstreuen, oder habt auch Tipps um die Sache möglichst sicher zu gestalten.

So, das war jetzt viel Text, für so ein mickriges und vollkommen unnötiges Projekt, aber vielleicht ist noch Jemand bis hierhin gekommen und hat einen Denkanstoß für mich...!

Zum Abschluss hänge ich noch meinen bisherigen Code an, aber achtung: Das ist bisher nur ein ganz schnell zusammengesteckter Code zum testen der Funktionen, es ist viel copy&paste und miese variablennamen drin, das wird noch komplett neu geschrieben :wink:

#include "LedControl.h"

LedControl lc=LedControl(12,11,10,1); 
unsigned long previousMillis = 0;
const long interval = 1000;
int i = 9;
int r = 0;
int c = 0;
boolean hall_state_changed = 0;
unsigned long millis_rev = 0;
unsigned long millis_last = 0;
unsigned long upm = 0;
int upm_0 = 0;
int upm_1 = 0;
int upm_2 = 0;
int upm_3 = 0;

const byte interruptPin = 2;

void isr()
  {
  hall_state_changed = 1;
  }

void setup()
  {
  
  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), isr, FALLING);

  lc.shutdown(0,false);
  lc.setIntensity(0,8);  // (0-15)
  lc.clearDisplay(0);

  lc.setRow(0,3,B01011011);
  lc.setRow(0,2,B01000110);
  lc.setRow(0,1,B01111110);
  lc.setRow(0,0,B11100111);

  }

void loop()
  {
  if(hall_state_changed == 1)
    {
    hall_state_changed = 0;
    millis_rev = millis() - millis_last;
    millis_last = millis();
    upm = 60000/millis_rev;
    upm_3=(upm%10000)/1000;
    upm_2=(upm%1000)/100;
    upm_1=(upm%100)/10;
    upm_0=upm%10; 
    lc.setDigit(0,3,upm_3,true);
    lc.setDigit(0,2,upm_2,false);
    lc.setDigit(0,1,upm_1,false);
    lc.setDigit(0,0,upm_0,false);
    }
  if(millis() - millis_last >= 1000)
    {
    lc.setRow(0,3,B01011011);
    lc.setRow(0,2,B01000110);
    lc.setRow(0,1,B01111110);
    lc.setRow(0,0,B11100111);
    upm = 0;
    }
  
  if(millis() - previousMillis >= interval)
    {
    previousMillis = millis();
    // Platz für alles mögliche
    }

  }

Spontane Ideen:

Zeitsklave:
... mehr Drehzahl gibt mein Akkuschrauber leider nicht her ...

Mit sechs Magneten kannst Du die sechsfache Geschwindigkeit simulieren. :slight_smile:

Zeitsklave:
dauert jede Umdrehung gerademal 15ms, wenn jetzt der Arduino recht beschäftigt ist und ständig Umdrehungen übersieht wäre das ungünstig...

Wenn Du in der ISR Impulse zählst, kannst Du in loop diese durch die Zeitspanne dividieren. Bei größerer Zeitspanne wird dies durch mehr Impulse ausgeglichen. Außerdem liefert die Formel upm = 60000/millis_rev; nie den Wert Null, sonst müßte millis_rev Unendlich werden. Aber Impulse/feste_Zeitspanne birgt dieses Risiko nicht.

Zeitsklave:
Die Digits auf dem Display möchte ich alle 500ms aktualisieren, die Lastanzeige alle 100ms, mit dem Durchschnittswert aus der jeweiligen Zeitspanne.

Das kann ich dem Sketch nicht entnehmen:

if(hall_state_changed == 1)
    {
...
    lc.setDigit(0,3,upm_3,true);
    lc.setDigit(0,2,upm_2,false);
    lc.setDigit(0,1,upm_1,false);
    lc.setDigit(0,0,upm_0,false);
    }

Bei einem Drehzahl-Signal von 66Hz sehe ich keine nennenswerten Probleme mit der Erfassung. Das Signal kann auch auf einen Input-Capture Timer-Interrupt gelegt werden, dann geht sicher nichts mehr verloren.

Ein PI-Regler sollte ausreichen, um die (vermutlich) krumme Kennlinie der Motorsteuerung auszugleichen.

Was die Anzeige betrifft, wie nützlich ist eine digitale Drehzahlanzeige bei einem Rasenmäher wirklich, die noch dazu bei jeder einzelnen Umdrehung aufdatiert wird - also bis zu 4000 mal pro Minute? Da erscheint mir eine Glättung unverzichtbar, die gleichzeitig zum Aussortieren eventueller Ausreißer verwendet werden könnte.

Deshalb würde ich die Impulse zählen (in isr), und das Display nur etwa jede Sekunde aktualisieren. Der Regler könnte davon unabhängig auch in kürzeren Intervallen aufdatiert werden.

DrDiettrich:
Das Signal kann auch auf einen Input-Capture Timer-Interrupt gelegt werden, dann geht sicher nichts mehr verloren.

Ein PI-Regler sollte ausreichen, um die (vermutlich) krumme Kennlinie der Motorsteuerung auszugleichen.

Oh je, zwei Schlagworte, zu denen ich mich wohl gründlich einlesen muss ^^ gerade mal ein paar Seiten zum Thema Regler (bzw PI-Regler) aufgemacht, das ist wohl eine Wissenschaft für sich...

DrDiettrich:
Was die Anzeige betrifft, wie nützlich ist eine digitale Drehzahlanzeige bei einem Rasenmäher wirklich, die noch dazu bei jeder einzelnen Umdrehung aufdatiert wird - also bis zu 4000 mal pro Minute? Da erscheint mir eine Glättung unverzichtbar, die gleichzeitig zum Aussortieren eventueller Ausreißer verwendet werden könnte.

Deshalb würde ich die Impulse zählen (in isr), und das Display nur etwa jede Sekunde aktualisieren. Der Regler könnte davon unabhängig auch in kürzeren Intervallen aufdatiert werden.

So ist das auch gedacht, wie oben geschrieben möchte ich das Display ca. alle 500ms aktualisieren.
Über die Nützlichkeit an sich könnte man sich natürlich streiten, aber wenn ich schon sowas mache, will ich auch was sehen :wink:

agmue:
Das kann ich dem Sketch nicht entnehmen:

Ertappt :wink: Ich habs der faulheit halber einfach so reingeschrieben, wie gesagt, das script ist nur mal zum Testen und Probieren der grundlegenden Dinge.

agmue:
Mit sechs Magneten kannst Du die sechsfache Geschwindigkeit simulieren. :slight_smile:

So einfach kanns sein :smiley: Manchmal hat man halt ein Brett vorm Kopf...

agmue:
Wenn Du in der ISR Impulse zählst, kannst Du in loop diese durch die Zeitspanne dividieren. Bei größerer Zeitspanne wird dies durch mehr Impulse ausgeglichen. Außerdem liefert die Formel upm = 60000/millis_rev; nie den Wert Null, sonst müßte millis_rev Unendlich werden. Aber Impulse/feste_Zeitspanne birgt dieses Risiko nicht.

Naja, wenn upm=0 wird, kommt bei millis_rev sowieso nichts mehr an, weil ja die Schleife gar nicht mehr aufgerufen wird wenn kein Impuls kommt. Deswegen habe ich noch die if(millis() - millis_last >= 1000) eingebaut, um bei fehlendem Signal die 0 zu bekommen (oder in dem Fall "STOP" uf dem Display).
Aber dein Vorschlag mit dem Impulse Zählen dürfte mir einiges an Rechenzeit einsparen, und auch deutlich mehr Sicherheit bringen, falls mal irgendeine Aufgabe mehr Zeit braucht, weil mir dann keine Impulse verloren gehen, sehe ich das richtig?
Dann müsste man halt beispielsweise mit 100ms Intervallen rechnen, das sollte ja für die Regelung eigentlich auch schon reichen. Der Motor braucht eh geschätzt mehrere hundert ms um auf eine Änderung der Drosselklappenstellung zu reagieren.

So, ich war mal fleißig...

void isr()
  {
  if(impulse == 0)
    {
    timerOld = timer;
    timer = micros();
    }
  if(micros()-timer>=100000)
    {
    count_upm = 1;
    }
  
  impulse++;
  }

.
.
.

void loop()
  {
  if(count_upm == 1)
    {
    upm = (impulse*60000000)/(timer - timerOld);
    count_upm = 0;
    impulse = 0;
    millis_last = millis();
    upm_3=(upm%10000)/1000;
    upm_2=(upm%1000)/100;
    upm_1=(upm%100)/10;
    upm_0=upm%10;
    lc.setDigit(0,3,upm_3,false);
    lc.setDigit(0,2,upm_2,false);
    lc.setDigit(0,1,upm_1,false);
    lc.setDigit(0,0,upm_0,false);
    }

  if(millis() - millis_last >= 1000)
    {
    lc.setRow(0,3,B01011011);
    lc.setRow(0,2,B01000110);
    lc.setRow(0,1,B01111110);
    lc.setRow(0,0,B11100111);
    upm = 0;
    }
  }

OK, nicht die feine Art mit micros() in der isr, aber es funktioniert. So muss ich mich wenigstens nicht mit Timern rumschlagen (Hab ich mich noch nie damit beschäftigt :wink: ), und ich bekomme später keine Konflikte mit der servo-lib.

Mit 6 Magneten am Akkuschrauber bekomme ich auch problemlos gut 6000 upm zusammen, es läuft wunderbar flüssig. Im unteren drehzahlbereich sind halt ordentliche schwankungen drin, die weniger werden, je mehr die drehzahl steigt, aber das liegt schlicht dran dass ich natürlich die magnete auf dem Bohrfutter nicht 100%ig auf ihre 60° ausrichten kann, und zusätzlich das Bohrfutter auch noch ein bisschen eiert.
Aber ich denke ich kann damit soweit zufrieden sein, wenn das später auch noch so glatt funktioniert wenn ich die berechnungen für die drehzahlregelung und das servo drin hab...

Lieben dank erstmal für die hilfreichen Tipps! :slight_smile: Jetzt werd ich mich wohl mal intensiver mit dem PI-Regler bzw Regelkreisen allgemein beschäftigen müssen...

Zeitsklave:
Ertappt :wink: Ich habs der faulheit halber einfach so reingeschrieben, ...

Wenn es Dir bewußt ist, ist es gut.

Zeitsklave:
das ist wohl eine Wissenschaft für sich...

Wohl war!

Wenn Du den Stellwert schlagartig veränderst, kannst Du aus der Sprungantwort Kennwerte ermitteln, die Dich rechnerisch zu den nötigen Regelgrößen für P, I und D führen.

Experimentell kannst Du zunächst mit einem P-Regler anfangen. Der hat eine bleibende Regelabweichung, die dann vom I-Anteil eleminiert wird. Der D-Anteil sorgt für eine schnellere Reaktion, führt aber auch zu Schwingungen. Da ich einen elektrischen Rasenmäher nutze, fehlt mir aber praktische Erfahrung.

PID Library

Hallo,

warum soll er 6 Magneten anbringen wenn einer reicht? Was soll das bringen? Damit verkürzt man sich nur künstlich seine Erfassungszeit. Muß doch nicht sein. 15ms für eine Umdrehung sind erstmal eine Ewigkeit. Ist aber noch nicht die relevante Angabe. Die Frage ist, wie lang liegt denn das Signal an wenn der Magnet vorbei saust? Denn das ist die eigentliche Zeit in der der µC das Signal mitbekommen muß. Das kann man verlängern in dem man mehrere Magneten hintereinander befestigt. Sodass das Magnetfeld gestreckt wird. Oder ein anderer µC wird zur Erfassung abgestellt oder man muß doch mit Interrupts arbeiten oder im festen Zeitfenster pollen und nicht nur in der loop einfach pollen lassen.

Regelung wurde schon angesprochen. Ist ein komplexeres Thema, aber machbar.

Doc_Arduino:
warum soll er 6 Magneten anbringen wenn einer reicht?

Weil der Akkuschrauber zu langsam ist.

Doc_Arduino:
Die Frage ist, wie lang liegt denn das Signal an wenn der Magnet vorbei saust? Denn das ist die eigentliche Zeit in der der µC das Signal mitbekommen muß.

Wohl war und hier gibt es gegenüber der Simulation mit sechs Magneten eine Abweichung, da die Bahngeschwindigkeit größer wird. Mittels attachInterrupt(digitalPinToInterrupt(interruptPin), isr, FALLING); sollte es aber funktionieren.

Eben. Die 6 Magnete sind ja nur Mogelei, um zum ausprobieren mehr Drehzahl zu simulieren.
An der Schwungscheibe vom Rasenmäher ist nur 1 Magnet. Dessen Größe kann ich natürlich nicht beeinflussen, aber wie agmue sagt, mit dem Interrupt auf FALLING sollte es kein Problem sein :wink:
Klappt auch bisher wunderbar...
Habe jetzt im laufe des Nachmittags den Code neu geschrieben, und ein bisschen besser gemacht.

Mit der Regelung werd ich halt noch ein bisschen ins schwitzen kommen, der Rest ist aber lösbar :slight_smile:

Hallo,

achso, wegen Simulation mit Akkuschrauber zum testen. Das hatte ich nicht mehr auf dem Schirm. Sorry.

Nochmal zu meinem Gedankenspiel. Für ein normales Polling sollte das Signal mindestens so lange anliegen wie die maximale loop Durchlaufzeit ist. Man könnte es noch künstlich verlängern. Aber wenn der Motor mal sehr langsam dreht, hast das umgekehrte Problem das die Pause dazwischen zu kurz ist. Ich denke auch das du einen Interrupt nehmen solltest. Aber darin keine großes Aktionen starten. Nur einen Counter inkrementieren oder ein "Flag" setzen oder ähnlich kleine Dinge womit dann in der loop zügig weiter gearbeitet wird.

Du wirst dann auch zwangsläufig mit volatile und atomic konfrontiert bei Interrupt Nutzung.
Kleiner Abriss ... Probleme mit Timer bei Arduino Uno - Deutsch - Arduino Forum

Doc_Arduino:
Du wirst dann auch zwangsläufig mit volatile und atomic konfrontiert bei Interrupt Nutzung.

Immer gut, wenn mehrere drauf schauen :slight_smile:

Siehe attachInterrupt(): "Typically global variables are used to pass data between an ISR and the main program. To make sure variables shared between an ISR and the main program are updated correctly, declare them as volatile." Das hast Du zumindest in #0 nicht gemacht:

boolean hall_state_changed = 0;

Ob und wann das zu einem Fehler führt, weiß ich aber nicht.

Bei byte und boolean Variablen braucht man kein volatile, die werden mit atomaren Operationen gelesen und geschrieben.

Volatile wird interessant bei Zählern und Variablen mit mehr Bytes, und dann müssen auch noch die Interrupts bei den Zugriffen außerhalb der ISR abgeschaltet werden.

Bei byte und boolean Variablen braucht man kein volatile, die werden mit atomaren Operationen gelesen und geschrieben.

Das ist nicht ganz richtig....
Manchmal besteht ein Intormationspaket aus mehreren Bool, oder Byte Values.
Dann muss man das ganze Paket atomar abhandeln.

Also nicht nur der Datentype, sondern auch der Kontext.

Bei byte und boolean Variablen braucht man kein volatile, die werden mit atomaren Operationen gelesen und geschrieben.

Volatile wird interessant bei Zählern und Variablen mit mehr Bytes, und dann müssen auch noch die Interrupts bei den Zugriffen außerhalb der ISR abgeschaltet werden

Leider z.T. falsch oder missverständlich, fürchte ich :wink:

volatile sagt dem Compiler, dass die Variable veränderlich ist, sich also "von aussen" ändern kann. Verbietet also Optimierungen, z.B. in Registern.

Variable die größer als 1 byte sind, müssen "atomic" behandelt werden, man muss also in loop die Interrupts verbieten, damit man ungestört mit allen bytes der Variable arbeiten kann, bevor eine ISR dazwischen pfuschen kann. Dies ist übrigens sogar für 1 byte goße Variable zu empfehlen, wenn diese in loop nach dem Auswerten zurückgesetzt werden.

Ob und wann das zu einem Fehler führt, weiß ich aber nicht

Selten. Wie man falsche Optimierungen bei globalen Variablen provozieren kann, dazu müsste man sich in Assemblercode gut auskennen. Da ist es einfacher, einfach volatile hinzuschreiben, auch wenn der Code dadurch genau der gleiche bleibt. Und wann ein fehlendes noInterrupts() mal tatsächlich einen Fehler verursacht, sieht man in der Praxis nur bei einem speziellen Demo-Programm (gab's hier vor einiger Zeit). Oder wenn man nicht hinguckt, aber dann ist es eigentlich um so schlimmer.

Au weia, das scheint wieder einmal eine Grundsatzdebatte zu werden :wink:

Fangen wir mal beim Kontext an, den ich außer Acht gelassen hatte. Unter dem Kontext eines Code-Abschnitts sind alle globalen Variablen zu verstehen, auf die in diesem Abschnitt zugegriffen wird, und die sich während der Verarbeitung nicht (durch ISR) ändern dürfen.

Normalerweise optimiert der Compiler das genau passend, d.h. der Kontext wird bevorzugt in Registern (lokal) abgelegt. Nur werden dabei Interrupts nicht gesperrt, d.h. ohne noInterrupts() kann man inkonsistente Werte in den lokalen Variablen bekommen. Korrekterweise muß man dann also Interrupts ausschalten, den gesamten Kontext in lokale Variablen kopieren, dann Interrupts wieder einschalten.

Bei volatile Variablen darf der Compiler die Werte nicht lokal in Registern puffern. Klingt zunächst gut, ist es aber garnicht. Dann müssen nämlich zwischen dem ersten und letzten Zugriff auf eine volatile Variable die Interrupts ausgeschaltet bleiben, damit sich der Kontext zwischendrin nicht ändert. Schaltet man also die Interrupts brav aus, ist volatile völlig überflüssig, hindert allenfalls den Compiler am Optimieren, und die Interrupts kommen erst durch, wenn die Verarbeitung beendet ist.

Kommt noch das Zurückschreiben geänderter Werte in die globalen Variablen. Das funktioniert nur richtig, wenn der Kontext während der Berechnungen nicht geändert wird, also wieder alle Interrupts während der gesamten Verarbeitung abgeschaltet bleiben. Ich lehne mich jetzt mal aus dem Fenster und behaupte, daß man solche Änderungen gleich nach dem Kopieren des Kontext in die lokalen Variablen vornehmen kann, d.h. globale (volatile) Zähler und Flags auf konstante Werte zurücksetzen. Gleich danach darf man Interrupts getrost wieder erlauben, und Berechnungen mit dem kopierten Kontext durchführen. Berechnete Ergebnisse dürfen nicht von Interrupts geändert werden, gehören also nicht zum Kontext.

Damit hat volatile für mich nur noch rein dokumentarischen Nutzen, um zu kennzeichnen, welche Variablen von ISR geändert werden können. Als einzig richtige Benutzung solcher Variablen bleibt für mich dieses Schema übrig:

noInterrupts();
int localX = volatileX; ... //Kontext in lokale Variablen kopieren
X = 0; ... //Zähler und Flags zurücksetzen
interrupts(); //danach mit den lokalen Variablen weiterarbeiten

Aber vielleicht habe ich ja noch was übersehen?

Damit hat volatile für mich nur noch rein dokumentarischen Nutzen,

Alle Variablen und auch Register welche nicht nur vom Hauptprogrammfluss verändert werden, müssen als volatile gekennzeichnet werden!
Dazu gehören natürlich Variablen, welche von ISRs geändert werden.
Aber auch die Register für IO Operationen(Portregister), TimerRegister, die Register der ganzen seriellen Schnittstellen (I2C, UART, SPI), ADC Register, usw....
Die können sich durch äußere Einflüsse ändern. Auch ganz ohne ISR.

Einen "dokumentarischen Nutzen" hat es natürlich auch, aber auf den könnte man verzichten.
Auf den "praktischen Nutzen" kann man nicht verzichten.

Ohne volatile dürften die wenigsten Programme funktionieren.

combie:
Aber auch die Register für IO Operationen(Portregister), TimerRegister, die Register der ganzen seriellen Schnittstellen (I2C, UART, SPI), ADC Register, usw....
Die können sich durch äußere Einflüsse ändern. Auch ganz ohne ISR.

Die Deklarationen für die I/O Register sind vorgegeben, da sollte kein Programmierer dran rühren.

Einen "dokumentarischen Nutzen" hat es natürlich auch, aber auf den könnte man verzichten.
Auf den "praktischen Nutzen" kann man nicht verzichten.

Was soll denn dieser "unverzichtbare" praktische Nutzen sein?

Die Deklarationen für die I/O Register sind vorgegeben, da sollte kein Programmierer dran rühren.

"kein Programmierer"??
Und? Was ist mit Zeigern auf diese Register?
:smiling_imp: Da ich damit öfter mal mit rum mache, bin ich "kein Programmierer"! :smiling_imp:

Auch gerade daran, dass diese Register alle als volatile deklariert sind, zeigt sich doch schon die Unverzichtbarkeit. Spätestens, wenn man es ohne probiert, wird man elendig auf dem Bauch landen.

Was soll denn dieser "unverzichtbare" praktische Nutzen sein?

Wurde alles schon genannt....

Meine Glaskugel sagt: Auch du wirst deine Einstellung zu volatile noch ändern.
Und wenn es nur auf dem schmerzhaften Weg geht, dann muss das wohl so.
Frei nach dem Motto: Herdplatte, heiß, Finger, Aua, Einsicht.

Oder machst du dir gerade einen Spaß daraus, Anfänger in Fallen zu locken?

combie:
Was ist mit Zeigern auf diese Register?

Was soll damit sein?

Spätestens bei Zugriffen auf multi-byte Register muß man sich sowieso mit der Hardware auskennen, wenn man die richtig lesen oder schreiben möchte. Das nimmt der Compiler niemandem ab.

Auch gerade daran, dass diese Register alle als volatile deklariert sind, zeigt sich doch schon die Unverzichtbarkeit. Spätestens, wenn man es ohne probiert, wird man elendig auf dem Bauch landen.

Man kann mit Registern auf viele Arten auf den Bauch fallen. Wer da an den Voreinstellungen in den Basis-Bibliotheken rumfummelt, sollte schon sehr genau wissen, was er tut :-]

Wurde alles schon genannt....

Es wurde schon so viel Mist erzählt, deshalb hätte ich gerne eine Auflistung Deiner Argumente. Meine habe ich ja schon dargelegt, jetzt bist Du dran.

Oder machst du dir gerade einen Spaß daraus, Anfänger in Fallen zu locken?

Mit Deinen unbegründeten Behauptungen bist eher Du es, der Anfänger verunsichert. Gerade Anfänger sollte man nicht mit undurchdachten Ratschlägen und Halbwahrheiten auf falsche Gedanken bringen. Mir ist das schon lange klar, Dir anscheinend noch nicht :frowning:

Gerade Anfänger sollte man nicht mit undurchdachten Ratschlägen und Halbwahrheiten auf falsche Gedanken bringen.

Dem stimme ich zu!

Es wurde schon so viel Mist erzählt, deshalb hätte ich gerne eine Auflistung Deiner Argumente. Meine habe ich ja schon dargelegt, jetzt bist Du dran.

Erkläre mir bitte, was an diesem Text falsch ist: