[gelöst] Status einer bool-Variablen unverständlich

Guten Morgen,
ich stehe hier bei vermutlich sehr simplen Dingen auf dem Schlauch. Die folgenden Codezeilen stammen aus einem Projekt, das so gekürzt wurde, dass nur noch die für die Frage relevanten Zeilen vorhanden sind.

Geplant ist folgendes: (butt_cent usw. beziehen sich auf einen “Joystick-Taster” mit 5 Bedienungsmöglichkeiten. butt_cent meint den Taster drücken, butt_d bzw. butt_u die runter bzw. rauf-Bewegung).
Bei Druck auf den Zentraltaster soll das Programm auf eine Eingabe (Taster runter oder rauf, d oder u) warten und entspechend der Tastbewegung mw auf LOW oder HIGH setzen.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

bool mw = 1; // Anzeige der Werte in mW, 0 wäre in nE

const byte butt_d = 3; // Taster-Anschlüsse
const byte butt_r = 4;
const byte butt_u = 5;
const byte butt_l = 6;
const byte interruptPin = 2;
bool butt_cent = 0; // Status des Zentral-Tasters
volatile unsigned long time0 = 0;
volatile unsigned long deb_time = 20; // Entprellzeit 20 ms

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);
  // initialize both serial ports:
  Serial.begin(9600);
   // Lege den Interruptpin als Inputpin mit Pullupwiderstand fest: Pin 2
  pinMode(interruptPin, INPUT_PULLUP);
  pinMode(butt_cent, INPUT_PULLUP);
  pinMode(butt_d, INPUT_PULLUP);
  pinMode(butt_u, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), unit, 0);


}

void loop() {
   if (mw == 1) {

    display.setTextSize(1); display.setRotation(0);
    display.clearDisplay(); display.setCursor(10, 0); display.print("mW/m2");
  }
  else {
    display.setRotation(0); display.setTextSize(1);
    display.clearDisplay();     display.setCursor(10, 0); display.print("nE");
  }
  display.display();

  Serial.println(digitalRead(butt_cent));


  if (butt_cent == 1) {
    Serial.print("C: "); Serial.println(digitalRead(butt_cent));
    while (digitalRead(butt_cent == 1)) {
      display.clearDisplay(); display.setRotation(0); display.setCursor(30, 30); display.print("Einstellungen"); display.display();                            // Auswahl der Einheit: mW oder nE      digitalRead(butt_u); digitalRead(butt_d);
    }
    if (digitalRead(butt_u) == 0) {
      mw = 0;
      butt_cent = 0;
    }
    if (digitalRead(butt_d) == 0) {
      mw = 1;
      butt_cent = 0;
    }
  }
}
//--------------------------------------------------
void unit() {                                  //Interruptroutine prüft, ob Zentraltaste gedrückt
  if ((millis() - time0) > deb_time) {                 // Entprellung
    time0 = millis();
    butt_cent = !butt_cent;
  }
}

Am Anfang wird in der Variablendeklaration butt_cent als LOW deklariert. Trotzdem gibt die Kontrolle über die serielle Konsole “1” als Status aus.

Sobald der Taster gedrückt wird, zeigt die Konsole “C: 0” und der Text “Einstellungen” erscheint auf dem Display, obwohl das ja bei butt_cent = HIGH der Fall sein sollte. Die folgenden Tastendrücke nach unten oder oben bewirken nichts mehr. Das Programm läuft auch nicht mehr weiter.

Ich hoffe, das Problem ist deutlich. Wo ist der Knick im Schlauch?
Ich würde mich sehr über einen Tipp freuen.

-richard

Du bringst Pin und Zustand durcheinander.

 pinMode(butt_cent, INPUT_PULLUP);

Das hast Du besrimmt nicht so gewollt, zumindest wenn butt_cent bool ist - Pin 0?.

Gruß Tommy

Da hast Du natürlich recht. Aber auch wenn ich entsprechend korrigiere, bleiben die Boolschen Werte für mich immer noch unverständlich:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

bool mw = 1; // Anzeige der Werte in mW, 0 wäre in nE

const byte butt_dPin = 3; // Taster-Anschlüsse
const byte butt_rPin = 4;
const byte butt_uPin = 5;
const byte butt_lPin = 6;
const byte interruptPin = 2; // Der Zentraltaster löst den Interrupt aus
bool butt_cent = 0; // Status des Zentral-Tasters
bool butt_u;
bool butt_d;
volatile unsigned long time0 = 0;
volatile unsigned long deb_time = 20; // Entprellzeit 20 ms

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);
  // initialize both serial ports:
  Serial.begin(9600);
  pinMode(interruptPin, INPUT_PULLUP);
  pinMode(butt_dPin, INPUT_PULLUP);
  pinMode(butt_uPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), unit, 0);


}

void loop() {
   if (mw == 1) {

    display.setTextSize(1); display.setRotation(0);
    display.clearDisplay(); display.setCursor(10, 0); display.print("mW/m2");
  }
  else {
    display.setRotation(0); display.setTextSize(1);
    display.clearDisplay();     display.setCursor(10, 0); display.print("nE");
  }
  display.display();

  Serial.println(digitalRead(butt_cent));


  if (butt_cent == 1) {
    Serial.print("C: "); Serial.println(digitalRead(butt_cent));
    while (digitalRead(butt_cent == 1)) {
      display.clearDisplay(); display.setRotation(0); display.setCursor(30, 30); display.print("Einstellungen"); display.display();                            // Auswahl der Einheit: mW oder nE      digitalRead(butt_u); digitalRead(butt_d);
    }
    if (digitalRead(butt_u) == 0) {
      mw = 0;
      butt_cent = 0;
    }
    if (digitalRead(butt_d) == 0) {
      mw = 1;
      butt_cent = 0;
    }
  }
}
//--------------------------------------------------
void unit() {                                  //Interruptroutine prüft, ob Zentraltaste gedrückt
  if ((millis() - time0) > deb_time) {                 // Entprellung
    time0 = millis();
    butt_cent = !butt_cent;
  }
}

r_a_mueller:
Da hast Du natürlich recht. Aber auch wenn ich entsprechend korrigiere, bleiben die Boolschen Werte für mich immer noch unverständlich:

bool butt_cent = 0; // Status des Zentral-Tasters

if (butt_cent == 1) {
   Serial.print("C: "); Serial.println(digitalRead(butt_cent));
   while (digitalRead(butt_cent == 1)) {
     display.clearDisplay(); display.setRotation(0); display.setCursor(30, 30); display.print("Einstellungen"); display.display();

Ich versteh nicht, was Du hier machen willst.
butt_cent ist eine Variable und kein PIN - da macht digitalRead irgendwie keinen Sinn.
Und alles, was hinter while (butt_cent == 1) steckt, wird solange ausgeführt, bis Du den Stecker ziehst.
Du kommst da nie wieder raus, weil sich die Bedingung nicht mehr ändert.

r_a_mueller:
Ich würde mich sehr über einen Tipp freuen.

Wenn Tommy sagt, dass er in einer bestimmten Zeile eine Ungereimtheit sieht, dann solltest Du Dir auch den Rest Deines Programms daraufhin ansehen. Da stimmt einiges nicht.

Mach Dein Programm zunächst mal hübsch.

Gruß

Gregor

Verstehe. Ich hatte keinen Unterschied gemacht zwischen dem Abfragen des Status des Pins und dem Abfragen des Status der zugehörigen Variablen.

Habe jetzt alle Taster auf Interrupts gelegt, da werde ich aber demnächst in Bedrängnis kommen, da die Interrupt-Pins auch noch für serielle Kommunikation und I2C zuständig sind - da wird es eng werden. Jetzt funktioniert es. Den Zentraltaster habe ich hierbei nicht mehr verwendet, den braucht es im Moment eigentlich nicht. Und je weniger, desto besser. Einige Routinen für diesen Taster stehen (momentan unnötig) für spätere Zwecke jedoch noch drin.

Und bezüglich “hübsch”: Völlig richtig. Nur so häßlich fand ich den Code eigentlich nicht (nun, ein bisschen vielleicht doch :wink:

Jedenfalls schon mal schönen Dank für das Mitdenken und Posten! Den funktionierenden (bis jetzt kompletten - wird noch dran gearbeitet) Code habe ich hier unten angehängt, falls es jemanden interessiert.

-richard

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

bool mw = 1; // Anzeige der Werte in mW, 0 wäre in nE

const byte interruptPinD = 3; // Taster-Anschlüsse
//const byte interruptPinR = 18;
const byte interruptPinU = 18;
const byte interruptPinL = 21;
const byte interruptPinCent = 2; // Der Zentraltaster löst den Interrupt aus
bool butt_cent = 0; // Status des Zentral-Tasters
bool butt_u = 0;
bool butt_d = 0;
volatile unsigned long time0 = 0;
volatile unsigned long deb_time = 20; // Entprellzeit 20 ms

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);
  // initialize both serial ports:
  Serial.begin(9600);
  pinMode(interruptPinCent, INPUT_PULLUP);
  pinMode(interruptPinD, INPUT_PULLUP);
  pinMode(interruptPinU, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinCent), unit, LOW);
  attachInterrupt(digitalPinToInterrupt(interruptPinU), oben, LOW);
  attachInterrupt(digitalPinToInterrupt(interruptPinD), unten, LOW);


}

void loop() {
  if (mw == 1) {

    display.setTextSize(1); display.setRotation(0);
    display.clearDisplay(); display.setCursor(10, 0); display.print("mW/m2");
  }
  else {
    display.setRotation(0); display.setTextSize(1);
    display.clearDisplay();     display.setCursor(10, 0); display.print("nE");
  }
  display.display();


  if (butt_u == 1) {
    mw = 0; butt_u = 0; Serial.println("mW");
  }
  if (butt_d == 1) {
    mw = 1; butt_d = 0; Serial.println("nE");
  }

}
//--------------------------------------------------
void unit() {                                //Interruptroutine prüft, ob Zentraltaste gedrückt
  if ((millis() - time0) > deb_time) {                 // Entprellung
    time0 = millis();
    butt_cent = !butt_cent;
  }
}
//--------------------------------------------------
void oben() {                                 //Interruptroutine prüft, ob Up-Taste gedrückt
  if ((millis() - time0) > deb_time) {                 // Entprellung
    time0 = millis();
    butt_u = 1;
  }
}
//--------------------------------------------------
void unten() {                                 //Interruptroutine prüft, ob Down-Taste gedrückt
  if ((millis() - time0) > deb_time) {                 // Entprellung
    time0 = millis();
    butt_d = 1;
  }
}

r_a_mueller:
Und bezüglich "hübsch": Völlig richtig. Nur so häßlich fand ich den Code eigentlich nicht (nun, ein bisschen vielleicht doch :wink:

Ich gebe zu, dass die Zahl hässlicherer Codes sehr groß ist :slight_smile:

Die Lesbarkeit ist halt sehr wichtig für die Verständlichkeit. Und wer „nicht im Code steckt“, hat es nochmal schwerer.

Was Deine Taster angeht: Ich habe mir den Code und die Aufgabe nicht so richtig angeguckt und wundere mich nur darüber, dass Du die Abfrage per Interrrupt machst. Meiner Erfahrung nach ist bei ordentlicher Programmierung die Abfrage „zu Fuß“ (in loop() per digitalRead()) in 99,9 % aller Fälle vollkommen ausreichend.

Aber wenn Du es verstehst und es funktioniert, dann lass es so. Das kam mir nur so in den Sinn (isja Wochenende, gell).

Gruß

Gregor

Echt jetzt, du hast dein Problem gelöst ?

Taster per interrupt abzufragen ist mal die schlechteste Lösung.
Tasterzustände ändern sich so langsam, dass man das problemlos in der loop machen kann.

da werde ich aber demnächst in Bedrängnis kommen, da die Interrupt-Pins auch noch für serielle Kommunikation und I2C zuständig sind - da wird es eng werden.

Ah, ja ....
Wenn du meinst ...