Frage zum Programmierstil

Hallo

Ich hab mal ne vielleicht doofe Frage zum guten Programmierstil. Wenn ich den trivialen Fall "Wenn Pin 3 High ist dann schalte Pin 4 auch auf High" betrachte. Ist es besser einen Wert immer blind zu schreiben oder stattdessen zu lesen und zu schauen ob er überhaupt geschrieben werden muss?

Im einfachsten Fall schreibe ich in meine loop sowas wie:

if (digitalRead(pin3) == HIGH) digitalWrite(pin4,HIGH); else digitalWrite(pin4,LOW;)

oder sogar digitalWrite(pin4,(digitalRead(pin3)) falls das geht

Jetzt wird aber in jedem Durchlauf der Pin beschrieben. Ist das Aufwändig für den Prozessor? langsam? Ist das vermeidenswert? Bspw. so?

static boolean pin4state = false
if ((digitalRead(pin3) == HIGH) && !pin4state) {
  digitalWrite(pin4,HIGH);
  pin4value = true;
}
else if (pinvalue) {
   digitalWrite(pin4,LOW);
   pin4value = false;
}

Der Code wird ja dadurch nicht einfacher. :~

des nächtens noch grübelnd
Kurt

Ich hätte es jetzt so geschrieben wie in deinem Beispiel

if(digitalRead(pin3) == true) digitalWrite(pin4, true);
else digitalWrite(pin4, false);

Die Kurzform sollte natürlich ausgehen. Serenfly hatte gestern etwas bzgl. der Dauer geschrieben, was es benötigt, einen Pin zu schalten. Wenn ich das nun nicht aus den Zusammenhang gerissen habe, beträgt die Zeit dafür 4 µS (habe das Thema nur kurz überflogen).

Das hier könntest du machen, spielt aber erst einmal weniger eine Rolle, interessant wird sowas in Verbindung mit einem LC Display, wenn der Textinhalt immer gelöscht werden soll.

ungetestet, sollte aber gehen.

static boolean lastStatePin3;
if (digitalRead(pin3) != lastStatePin3) {
  lastStatePin3 = digitalRead(pin3);
  digitalWrite(pin4, lastStatePin3);
}

Achtung nicht bei allen Arduinomodelen kannst Du den zustand eines Pins auslesen. Jetzt weiß ich nicht welche ses sind die nicht funktionieren ich glaube der DUE.
Grüße Uwe

Denke, bei dem Beispiel handelt es sich um einen Taster Pin3 und einer Led Pin 4. Alternativ macht es ja sonst keinen Sinn, wenn Pin 4 immer in Abhängigkeit zu Pin 3 geschaltet wird. Dann hätte man auch einen Pin rausmachen können :wink: Zum Lasten verteilen soll das aber hoffentlich nicht genutzt werden.

komischerschwabe:
Der Code wird ja dadurch nicht einfacher. :~

Bravo, Du hast gerade eines der Grundprinzipien bei der Programmoptimierung gefunden!

digitalRead und digitalWrite sind relativ "langsame" Funktionen, jede braucht so ca. (hab die Zahl nicht im Kopf) 60 bis 70 Taktzyklen zur Ausführung.

Mit digitalWrite(pin4,(digitalRead(pin3)) werden nun jedesmal sowohl digitalRead als auch digitalWrite aufgerufen, obwohl digitalWrite fast nie ausgeführt werden muß, wenn der Pinstatus schon vorher korrekt gesetzt ist. Durch die Vermeidung der meisten Aufrufe von digitalWrite kannst Du durch einen einfachen Vergleich mit einer Variablen (schnell) die meisten Aufrufe von digitalWrite (langsam) vermeiden. Das Programm wird dadurch schneller, aber dadurch wird der Code des Programms größer.

Für die Optimierung von Programmen gilt (in vielen Fällen) entweder:

  • kleine Programmgröße, langsame Ausführung
    oder
  • schnelle Ausführung, große Programmgröße

Das kann man durch den Code beeinflussen, den man schreibt.
Meist ist es so, dass man für besonders schnell arbeitenden compilierten Programmcode auch viel mehr Quellcode schreiben muss.

Das eigentliche Verändern eines Bits an einem Port ( oder Überschreiben mit dem gleichen Wert ) ist eine der ganz schnellen Operationen ( 1 Taktzyklus )
if - Abfragen, die erstmal prüfen ob etwas zu tun ist, kosten auch ein paar Zyklen.

Wenn dir digitalWrite() zu langsam ist, gibt es auch Alternativen, die mit weniger Takten auskommen.

Aber wenn du Arduino Software verwendest, weil es so schön einfach ist mit digitalWrite und so,
und du ja eine "Frage zum Programmierstil" stellst, ist meine Antwort:
Mach dir um "unnötige" digitalWrite Aufrufe keine Sorgen,
Was klarer aussieht für dich, ist der bessere Code.

Nachtrag:

digitalWrite(LED, digitalRead(TASTER) );  // Tasterzustand an Led anzeigen

gefällt mir persönlich gut, ausser man will mit dem Tasterzustand noch was anderes machen :wink:

Es gilt aber auch, dass man nicht immer vorauseilend optimierend sollte :slight_smile:
Bei so primitiven Programmen ist es egal ob das lange braucht oder nicht.

Es gibt natürlich Anwendung wo man auf digitalRead() verzichten sollte, z.B. in Interrupts die wirklich schnell sein müssen, eventuell LED Matrizen oder generell wenn es sehr oft in kurzer Zeit erfolgen muss. Dann macht man aber gleich direkte Port Adressierung und verzichtet auf die Arduino Funktionen komplett.

Der Grund weshalb diese relativ langsam sind ist die Arduino Pin Nummern auf die Prozessor Pins umgesetzt werden müssen und glaube ich Abfragen auf die Gültigkeit der Eingaben gemacht werden.

Vielen Dank für eure Anmerkungen dazu. Hat mich weitergebracht.
Ich machs über Vergleiche von Klartextvariablen. Das ist schön übersichtlich und passt auch zum Bauchgefühl.

komischerschwabe:
Vielen Dank für eure Anmerkungen dazu. Hat mich weitergebracht.
Ich machs über Vergleiche von Klartextvariablen. Das ist schön übersichtlich und passt auch zum Bauchgefühl.

Was sind "Klartextvariable" ?

ich nehme an, sowas wie "statusPIN3"

ja, das ist wesentlich besser als

boolean x; // status von Pin 3
    • auf jeden Fall, wenns eine globale Variable ist :wink:

Ja genau: Selbstsprechende Variablennamen: Also so irgendwie.
Und es hat mir dahingehend geholfen für mich zu verstehen, dass mir oft nicht nur der Ist-Zustand von Bedeutung ist sondern auch das EInschalten an sich. Also die Flanke. Und da lässt sich klartextcode einfach super lesen. Ohne die Umsetzung auf Variable hätte ich mir einen Knoten in den Kopf gemacht. Also noch nicht hier aber im restlichen Code.

const int Kesselpumpe_PIN = 3;
const int Lambdasondenheizung_PIN = 4;
boolean Kesselpumpe = false; 
boolean Lambdasondenheizung = false;
.....

void setup()
.....

void loop() {
 //Messwerte und Zustände auslesen
Kesselpumpe = digitalRead(Kesselpumpe_PIN);
Lambdasondenheizung = digitalRead(Lambdasondenheizung_PIN);
..........

// Sachen berechnen
...............

// Dinge tun
if (Kesselpumpe ==  true)  &&  (Lambdasondenheizung  ==  false)  {
    digitalWrite(Lambdasondenheizung_pin,HIGH);
   serialprint(millis()/1000);serialprintln(": Heizung startet, gültige Messwerte in 60 Sekunden"); 
}
else if (Kesselpumpe  ==  false)  && (Lambdasondenheizung  ==  true){
    digitalWrite(Lambdasondenheizung_pin,LOW);
   serialprint(millis()/1000);serialprintln(": Heizung stoppt"); 
}
......

}

Gruß Kurt

Guter Programmierstil kommt nicht von einzeln optimierten Statements. Wenn wirklich was lernen willst ist "Code Complete" von McConnel ein guter Startpunkt.

Uff. Großer dicker Schinken. Ich guck ihn mir trotzem mal an. 8)