Verständnisfrage zu Variablen

Hallo,

ich versuche gerade meinen Arduino mittels IR-Fernbedienung zu steuern.
Prinzipiell klappt das sehr gut mit der IRremote-Library von http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html

Ich habe mir nun eine einfache Schaltung mit einer RGB-LED zusammengesteckt.
Wenn ich Taste 1 auf der FB drücke leuchtet die LED rot, bei 2 grün und bei 3 blau. Nach einer Wartezeit von 500ms geht die LED wieder aus. Soweit so gut.
Allerdings möchte ich nun mittels Taste 4 und 5 die Helligkeit der (roten) LED verändern. Ich habe gedacht, wenn ich die Variable redint einfach um 10 vergrößere oder verkleinere sollte die Helligkeit zu- bzw. abnehmen.

Aber scheinbar habe ich da was noch nicht richtig verstanden. Ich lasse mir den Wert von redint per SerialConsole ausgeben, aber der Wert ist nicht der, den ich erwarten würde.
Wenn ich Taste 4 drücke bekomme ich für redint immer 10, bei Taste 5 immer 2388.
Ich vermute nun, dass die Variablen redint, greenint und blueint bei jedem Durchlauf von loop() wieder auf null gesetzt werden. Ist diese Annahme richtig? Und wie kann ich das verhindern?

Hier noch mein Beispielcode:

#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
#define REDPIN 9
#define GREENPIN 10
#define BLUEPIN 8

void setup()
{
  pinMode(REDPIN, OUTPUT);
  pinMode(GREENPIN, OUTPUT);
  pinMode(BLUEPIN, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop() {
  int redint, greenint, blueint;
  if (irrecv.decode(&results)){
    Serial.println(results.value, HEX);
    if (results.value == 0x10){ //taste1
      analogWrite(REDPIN, 255);
      delay(500);
      analogWrite(REDPIN, 0);
    }
    if (results.value == 0x810){ //taste 2
      analogWrite(GREENPIN, 255);
      delay(500);
      analogWrite(GREENPIN, 0);
    }
    if (results.value == 0x410){ //taste 3
      analogWrite(BLUEPIN, 255);
      delay(500);
      analogWrite(BLUEPIN, 0);
    }
    if (results.value == 0xC10){ //taste 4
      redint = redint + 10;
            Serial.println(redint);
      analogWrite(REDPIN, redint);
    }
    if (results.value == 0x210){ //taste 5
      redint = redint - 10;
      Serial.println(redint);
      analogWrite(REDPIN, redint);
    }
    irrecv.resume();
  } 

}

fatzgenfatz:
Ich vermute nun, dass die Variablen redint, greenint und blueint bei jedem Durchlauf von loop() wieder auf null gesetzt werden. Ist diese Annahme richtig? Und wie kann ich das verhindern?

Ja, wenn eine Variablen ihren Wert innerhalb einer Schleife oder Funktion behalten soll muss sie außerhalb (also entweder global oder zumindest vor der Schleife) deklariert werden; also in Deinem Fall außerhalt der loop().

int redint, greenint, blueint;
void loop() {

Je nachdem wo Du in Deinem Code eine Variable definierst legt fest wie groß ihr Geltungsbereich ist.

Wenn Du eine Variable außerhalb einer Funktion deklarierst, ist diese im gesamten Programm bekannt, d.h. mit diesem Variablennamen wird immer der gleiche Speicherplatz bezeichnet, und wenn Du was hineingeschrieben hast kannst Du diesen Wert im gesamten Programm wieder auslesen.

Wenn Du eine Variable innerhalb einer Funktion (oder auch Schleife) deklarierst, also zwischen einer öffnenden und schließenden geschweiften Klammer, dann ist die Variable auch nur innerhalb dieses Bereichs bekannt.

Beispiel:

int a; // Global bekannt
void test1() {
  Serial.print(a++); // Gibt den Vert der Variablen "a" aus und zaehlt sie anschliessend um eins hoch
}
void test1() {
  int b; // Nur innerhalb der Funktion bekannt!!
  Serial.print(b++); // Gibt den Vert der Variablen "b" aus und zaehlt sie anschliessend um eins hoch
}
void loop() {
  test1(); // -> 0123456789
  test2(); // -> 0000000000
}

Siehs mal so: "int a;" ist IMMER automatisch wie "int a=0;". :wink:

Btw. lässt sich das mit der Sichtbarkeit und dem innerhalb von spitzen Klammern definieren auch beliebig verschachteln. XD

Hallo,

vielen Dank für die Aufklärung. Ich hab mir schon so was gedacht und hab die Variablen mal in setup() definiert, aber da waren sie auch falsch :slight_smile:

mfG,
f.

Hi,

in setup sind sie natürlich auch falsch... man unterscheidet lokale und globable Variablen.

Lokale Variablen werden in einer Funktion deklariert und die gelten nur solange, bis die Funktion zu Ende ist, danach sind sie weg. Und sie sind auch nur in der Funktion sichtbar, in der sie deklariert sind - daher kannst du keine lokalen Variablen in der Funktion setup() in loop() benutzen.

Globale Variablen hingegen sind im ganzen Sketch bekannt und man kann von überall darauf zugreifen. Das ist ihre Stärke, aber zugleich ihr Problem - wenn du an vielen verschiedenen Stellen darauf schreibend zugreifst, dann verlierst du den Überblick, wo eine Änderung stattgefunden hat. Besser ist des dann, die Veränderung in einer speziellen Funktion vorzunehmen (Setter-Methode) und dann diese Methode aufzurufen. Das hat dann den Vorteil, dass du im Fehlerfall z. B. eine Ausgabe über die Serial.println Methode protokollieren kannst und dadurch eher Fehler finden kannst.

Rudi

Vielen Dank für die Erklärung.

Ist schon lange her, dass ich aktiv programmiert habe :slight_smile:

mfG,
f.