IR-Signal wird ausgewertet obwohl unerwünscht

Hallo Leute,

dieses Mal geht es um das Laser-Gewehr. Ich habe folgendes Problem. Während der Neustart-Phase (Countdown von 5 bis 0) soll das Gewehr nicht empfangsbereit sein. Tatsächlich wertet das Gewehr Beschüsse während des Countdowns nicht aus, obwohl es Zeit dazu hätte. Aber sobald das Spiel beginnt wertet er den Beschuss aus, als hätte er sich diesen gemerkt und zwischengespeichert.

Während des Countdowns wird die Variable menuStatus=1 gesetzt, dass das if-Statement für die Trefferauswertung false ist. Das klappt ja auch - der Schuss bleib unbeachtet. Aber nach dem Countdown wird menuStatus=0 gesetzt, das Spiel beginnt. Und nun ist das Gewehr auch empfangsbereit. Dummerweise wertet es nun den Beschuss, der vor mehreren Sekunden kam, aus.

https://youtu.be/udXonE5IxF0

Gibt es dafür eine (hoffentlich einfache) Erklärung, die mir hilft, den Bug in meinem Sketch zu tilgen?

Es geht vornehmlich um die Abschnitte TREFFER und RESTART.


#include <IRremote.h>
#include <Arduino.h>
#include <Wire.h>
#include <LCD_I2C.h>




//AMOUNTS
int magazin = 16;
int health = 100;

//PINS
int receiver = 9;
int sender = 4;
int trigger = 6;
char triggerState = LOW;

int recoil = 2;
int empty = 3;
int feedback = 5;
int reload = 7;
int menu = 8;


int menuStatus = 0;


// Für Trefferanzeige auf LCD
long unsigned int startHitLCD;
long unsigned int intervall = 2000;



int nametag = 0;


unsigned long time;
bool reset = false;

LCD_I2C lcd(0x27, 16, 2);

IRsend irsend(sender);
IRrecv irrecv(receiver);
decode_results results;




byte bullet[] = {
  B01100,
  B11110,
  B11110,
  B11010,
  B11010,
  B11010,
  B11010,
  B11110
};


void updateDisplay() {
  lcd.clear();
  lcd.setCursor(0, 0);

  Serial.print("aktueller Nametag: ");
  Serial.println(nametag);

  if(nametag == 0) {openMenu();}
  else
  {
    clearLCDLine(0);
    databaseOfNametags(nametag);
    
    lcd.setCursor(13, 0);
    if (health == 0){
      lcd.print("KIA");
      Serial.println("KIA");
    }
    else {
      if(health != 100){lcd.print(" ");}
      
      lcd.print(health);
      
    }
  
    lcd.setCursor(0, 1);
    if (magazin == 0) {
      lcd.print("[RELOAD]");
    }
    else {
      for (int i = 0; i < magazin; i++) {
        lcd.write(byte(0));
      }
    }
    Serial.println("Display refreshed");
  }
}



void clearLCDLine(int line)
{               
        lcd.setCursor(0,line);
        for(int n = 0; n < 16; n++)
        {
          lcd.print(" ");
        }
        lcd.setCursor(0,line);
}

void openMenu() {
    menuStatus = 1;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Select your name!");
    lcd.setCursor(0, 1);
    lcd.print("[FIRE] or [MENU]");
    


    Serial.println("Menu opened");
}

void databaseOfNametags(int nametagID){

  switch (nametagID) {
        case 1: lcd.print("Recognite"); break;
        case 2: lcd.print("Tyrannforce"); break;
        case 3: lcd.print("Haselnuss"); break;
        case 4: lcd.print("John"); break;
        case 5: lcd.print("Schmith"); break;
        case 6: lcd.print("Ronald"); break;
        case 7: lcd.print("Miller"); break;
        case 8: lcd.print("Tudor"); break;
        case 9: lcd.print("Clarkson"); break;
        case 10: lcd.print("Goldtooth"); break;
        case 11: lcd.print("GRENADE"); break;
        case 12: lcd.print("PROX BOMB"); break;
        case 13: lcd.print("AIM BOT"); break;
        case 14: lcd.print("TEST SHOT"); break;
        case 15: lcd.print("MEDIC"); break;
        case 30: lcd.print("RESET"); break;
        default: break;
      }
}



void toggleNametags() {
    lcd.setCursor(1, 1);
       
    if(nametag >= 10) {nametag = 1;} else {nametag++;}    
    delay(200);

    clearLCDLine(1); 
    lcd.print(nametag); 
    lcd.print(" "); 
    databaseOfNametags(nametag);

   
    Serial.print("NAMETAG CHOSEN: ");
    Serial.println(nametag);
}



void closeMenu() {
    menuStatus = 0;
    updateDisplay();

    magazin = 16;
    health = 100;

    updateDisplay();

    restart();
    
    Serial.println("Menu closed");
}

void restart() 
{
  menuStatus = 1;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("New Round in");
  lcd.setCursor(6, 1);

  for(int i=5; i>-1; i--)
  {
    lcd.print(i);
    lcd.setCursor(6, 1);
    delay(500);
  }

  health = 100;
  magazin = 16;
  updateDisplay();
  
  Serial.println("Restart");
  delay(500);

  menuStatus = 0;
}





// SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP

void setup() {

  Serial.begin(9600);

  
  lcd.begin();
  lcd.createChar(0, bullet);
  lcd.backlight();
  
  
  pinMode(receiver, INPUT);
  pinMode(trigger, INPUT_PULLUP);
  pinMode(feedback, OUTPUT);
  pinMode(empty, OUTPUT);
  pinMode(reload, INPUT_PULLUP);
  pinMode(recoil, OUTPUT);
  pinMode(menu, INPUT_PULLUP);
  pinMode(sender, OUTPUT);
  
  
  
  irsend.enableIROut(38);
  irrecv.enableIRIn();

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Customs Lasertag");
  lcd.setCursor(4, 1);
  delay(1000);
  lcd.print("by RECO");
  delay(1500);

  Serial.println("Customs Lasertag by RECO");
  
  updateDisplay();
  
}




// LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    

void loop() {


  if(health < 0) {health = 0; updateDisplay();}
  else if(health > 100) {health = 100; updateDisplay();}
  triggerState = digitalRead(trigger);



  if (digitalRead(menu) == LOW && !reset){
      time = millis();
      reset = true;
  }
  if(digitalRead(menu) == HIGH && reset){
      reset = false;
  }
 

  
//  MENÜ ÖFFNEN
  if (digitalRead(menu) == LOW && health != 0 && menuStatus == 0 && (millis() - time > 1000)){
      openMenu(); delay(500);

  }

  //NAMEN DURCHGEHEN
  if (menuStatus == 1 && digitalRead(trigger) == LOW) {
    toggleNametags();
  }


//  MENÜ SCHLIESSEN
  if (digitalRead(menu) == LOW && menuStatus == 1 && (millis() - time > 1000)){
      closeMenu(); 
      delay(500);
  }  

// RESET
  if (irrecv.decode(&results) && results.value == 30  ) 
    {
      health = 100;
      magazin = 16;
      menuStatus = 0;
      Serial.println("Reset");
      updateDisplay();
    }


  // KIA
  if (digitalRead(menu) == LOW && health == 0)
  {

      digitalWrite(feedback,HIGH);
      delay(300);
      digitalWrite(feedback, LOW);
      delay(300);
 
  }


  //RESTART
  if (digitalRead(menu) == LOW && health == 0)
  {
     restart();
  }



  //NACHLADEN
  if (digitalRead(reload) == LOW && health != 0 && menuStatus == 0)
  {
    magazin = 16;

    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("reloading ...");
    lcd.setCursor(0,1);
    
    for (int i = 0; i < magazin; i++)
      {
        delay(170);
        lcd.write(byte(0));
        digitalWrite(empty, HIGH);
        delay (15);
        digitalWrite(empty, LOW);
        delay (65);
    }

    Serial.println("Reload");

    updateDisplay();
  }

 

  //SCHUSSABGABE
  if (triggerState == LOW  && magazin != 0 && health != 0 && menuStatus == 0) 
  {
    Serial.println("Shoot");
    magazin --;
    updateDisplay();
    digitalWrite(recoil, HIGH);
    delay(100); 
    digitalWrite(recoil, LOW);
         
       for(int i= 0; i<2; i++)
       {

        irsend.sendSony(nametag, 32);
        delay(40); 
    
       }
  }

  //SCHUSSVERSUCH LEER
  if (triggerState == LOW  && magazin == 0 && health != 0 && menuStatus == 0) 
  {
    Serial.println("Leer");
    digitalWrite(empty, HIGH);
    delay(15); 
    digitalWrite(empty, LOW);
    delay(500); 
  }
  


  //TREFFER
  if (irrecv.decode(&results) && health != 0 && menuStatus == 0) {


      Serial.print("compare: ");
      Serial.print(results.value);
      Serial.print(" and ");
      Serial.println(nametag);
      
    if(results.value != nametag && results.value > 0 && results.value < 30)
    {

      Serial.print("Hit by ");
      Serial.println(results.value);

      digitalWrite(feedback, HIGH);

      if(results.value <= 10)       {health -= 10;}      //Schuss Schaden
      else if (results.value == 11) {health -= 25;}       //Granaten Schaden
      else if (results.value == 12) {health -= 50;}       //Bomben Schaden
      else if (results.value == 13) {health -= 20;}       //Aim Bot Schaden
      else if (results.value == 14) {health -= 15;}       //Test Shot
      else if (results.value == 15) {health += 33;}       //Health


      lcd.clear();
      lcd.print("Hit by ");
      lcd.setCursor(0,1);
      databaseOfNametags(results.value);
      delay(1000);
      updateDisplay();
      digitalWrite(feedback, LOW);
      
    }
  }
  irrecv.resume();
  delay(10);
}

Sorry, aber für mich sind das zu viele if!
Für dich offenbar auch.

Ich rate dir zu endlichen Automaten.

Eine Vermutung hätte ich: IRremote arbeitet mit Interrupts, die auch während delay() aktiv sind und Impulse auswerten.

Du könntest irrecv.stop(); und irrecv.start(); probieren.

1 Like

Ich danke dir vielmals. Das wusste ich noch nicht.

Zugegebenermaßen konnte ich bisher mit "endlichen Automaten" nichts anfangen und habe erst einmal gegoogelt, dann ein paar Videos angesehen und viel gelesen. Ich finde diesen Vorschlag eigentlich ziemlich gut, denn mir ist schon bewusst, dass mein Code ziemlich unübersichtlich ist.

Wenn ich das jetzt angehen möchte und den Code des Gewehrs als endlichen Automaten entwerfen möchte, kommen mir aber ein paar Fragen. Zunächst einmal, was ich verstanden habe:

Q = {menu, ready, empty, dead}
∑ = {open, close, restart, reload, fire, be hit}
δ = {menu x close --> ready; ready x be hit --> dead ..... usw}
Qo = {menu}
E = {dead}

Was ich noch nicht nachvollziehen kann ist, dass es zwar endlicher Automat heißt, ich aber aus meinem Ende ja auch wieder herauskomme:
dead x restart --> ready

Ist es dann also kein endlicher Automat? restart ist auch nur eine Funktion wie fire oder reload.

Außerdem führt die ausgeführte Funktion be hit nicht wirklich zu dead, sondern erst ein fünfmaliges be hit. Heißt das nun, dass es fünf Zustände zwischen ready und dead geben muss? Genau das gleiche zwischen ready und empty, da das Magazin ja 16 Schuss fasst.

Vielleicht kann mir jemand einen Hinweis geben, wie man das betrachten muss.

Eine endlicher Automat hat eine endliche Menge an Zuständen.
Wiederholungen/Kreisläufe sind durchaus möglich/erwünscht.

Dann kannst Du „im“ Status be hit mitzählen, bis so oft getroffen wurde, dass sich der Status auf dead ändern kann. Das Gleiche für ready und empty.

Im Prinzip:

case  behit:
  // mach irgendwas
  hitCounter++
  if (hitCounter==5) {state = dead;}
  break;
case ready:
   // blah
  readyCounter++
  if (readyCounter== 16) {state = empty;}
  break;
// usw.

Musst dann aber aufpassen, dass die Counter in einem andern Status zurückgesetzt werden.

Ja, gut. So in etwa hatte ich es ja bisher auch. Gut.
"Endlich" habe ich dann wohl falsch verstanden. Nun ist es mir klar.

Dann werde ich es mal versuchen umzusetzen. Danke für die Hinweise.

So, ich habe mich jetzt mal rangesetzt und alles neu geschrieben. Es gefällt mir jetzt schon deutlich besser und das Hinzufügen oder Verändern von Funktionalitäten ist deutlich einfacher. Also schon einmal vorab danke für den Hinweis mit den endlichen Automaten.

Ohne jetzt alle Codezeilen zu prüfen: Ist das so in etwa gemeint? Vor dem SetUp habe ich alle möglichen Methoden als Funktionen vordefiniert und die verfügbaren Status festgelegt. In der Loop werden dann die Status mit Methoden kombiniert.

Dass das verbesserbar ist, ist mir klar - hab nicht Informatik studiert :wink: Es geht um's Grundprinzip. Das Gewehr funktioniert besser als zuvor :smiley:

#include <IRremote.h>
#include <Arduino.h>
#include <LCD_I2C.h>

// BUTTONS
#define PIN_BTN_FIRE 6
#define PIN_BTN_RELOAD 7
#define PIN_BTN_MENU 8

// MECHANICS
#define PIN_RECOIL 2
#define PIN_EMPTY 3
#define PIN_FEEDBACK 5

// INFRARED
#define PIN_SENDER 4
#define PIN_RECEIVER 9

// GAME PARAMETERS
int magazin = 16;
int health = 100;
int nametag = 0;
int state;

// STATES
const int READY = 1;
const int MENU = 2;
const int EMPTY = 3;
const int LOADING = 4;
const int HIT = 5;
const int DYING = 6;
const int DEAD = 7;

// MILLIS
const unsigned long INTERVAL = 1000;
unsigned long BTN_MENU_HOLD;

unsigned long previousMillis = 0; 


LCD_I2C lcd(0x27, 16, 2);

IRsend irsend(PIN_SENDER);
IRrecv irrecv(PIN_RECEIVER);
decode_results results;

// GRAFIK PATRONE
byte bullet[] = {B01100, B11110, B11110, B11010, B11010, B11010, B11010, B11110};
byte heart[] = {B00000, B01010, B11011, B11111, B01110, B00100, B00000, B00000};


// GENERAL FUNCTIONS
void databaseOfNametags(int nametagID)
{
    switch (nametagID) 
    {
        case 1: lcd.print("Recognite"); break;
        case 2: lcd.print("Tyrannforce"); break;
        case 3: lcd.print("Haselnuss"); break;
        case 4: lcd.print("Miekchen"); break;
        case 5: lcd.print("Schmith"); break;
        case 6: lcd.print("Ronald"); break;
        case 7: lcd.print("Miller"); break;
        case 8: lcd.print("Tudor"); break;
        case 9: lcd.print("Clarkson"); break;
        case 10: lcd.print("John"); break;
        case 11: lcd.print("GRENADE"); break;
        case 12: lcd.print("PROX BOMB"); break;
        case 13: lcd.print("AIM BOT"); break;
        case 14: lcd.print("TEST SHOT"); break;
        case 15: lcd.print("MEDIC"); break;
        case 30: lcd.print("RESET"); break;
        default: break;
    }
}


void openMenu() 
{
    Serial.println("MENU OPENED");
    BTN_MENU_HOLD = millis();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Select your name!");
    lcd.setCursor(0, 1);
    lcd.print("[FIRE] or [MENU]");
    state = MENU;
}


void restart() 
{
    Serial.println("RESTART");
    
    //irrecv.stop();
    
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("New Round in");
    lcd.setCursor(6, 1);
    
    for(int i=5; i>-1; i--)
    {
        lcd.print(i);
        lcd.setCursor(6, 1);
        delay(500);
    }
    
    health = 100;
    magazin = 16;
    
                                                                                
    //irrecv.start();
    BTN_MENU_HOLD = millis();   // delay of restart influences counter of BTN_MENU_HOLD, refresh neccessary

    
    state = READY;
    updateDisplay();
}


void toggleNametags() 
{
    lcd.setCursor(1, 1);
     
    if(nametag >= 10) {nametag = 1;} else {nametag++;}    
    delay(200);
    
    clearLCDLine(1); 
    lcd.print(nametag); 
    lcd.print(" "); 
    databaseOfNametags(nametag);
    
    Serial.print("NAMETAG: ");
    Serial.println(nametag);
}


void fire()
{
    state = READY;
    Serial.println("SHOOT");
    magazin --;
    updateDisplay();
    digitalWrite(PIN_RECOIL, HIGH);
    delay(100); 
    digitalWrite(PIN_RECOIL, LOW);
    
    for(int i= 0; i<2; i++)
    {
        irsend.sendSony(nametag, 32);
        delay(10); 
    }
}

int hit(int enemy)
{
        Serial.print("Hit by ");
        Serial.println(enemy);
        
        digitalWrite(PIN_FEEDBACK, HIGH);
        
        if(enemy <= 10)       {health -= 10;}       //Schuss Schaden
        else if (enemy == 11) {health -= 25;}       //Granaten Schaden
        else if (enemy == 12) {health -= 50;}       //Bomben Schaden
        else if (enemy == 13) {health -= 20;}       //Aim Bot Schaden
        else if (enemy == 14) {health -= 55;}       //Test Shot
        else if (enemy == 15) {health += 33;}       //Health
        
        
        lcd.clear();
        lcd.print("Hit by ");
        lcd.setCursor(0,1);
        databaseOfNametags(enemy);
        delay(750);
        digitalWrite(PIN_FEEDBACK, LOW);

        updateDisplay();
        state = READY;
}



void reload()
{

    if(state == READY) {magazin = 0;}
    state = LOADING;

    unsigned long currentMillis = millis();

    Serial.print("CURR: ");Serial.println(currentMillis);
    Serial.print("PREV: ");Serial.println(previousMillis);
    
    if(magazin < 16 && currentMillis - previousMillis >= 220)
    {
        lcd.setCursor(0,0);
        lcd.print("reloading...");
        
        magazin++;
        lcd.setCursor(0,1);
        digitalWrite(PIN_EMPTY, HIGH);
        delay (15);
        digitalWrite(PIN_EMPTY, LOW);
        previousMillis = currentMillis;
        updateDisplay();
    }
    else if (magazin == 16)
    {
        state = READY;
        updateDisplay();
    }

    Serial.println("RELOAD");
    Serial.println(state);
    Serial.print("magazin: ");Serial.println(magazin);

    
    BTN_MENU_HOLD = millis();   // delay of reload influences counter of BTN_MENU_HOLD, refresh neccessary

}

void empty()
{
    Serial.println("EMPTY MAG");
    digitalWrite(PIN_EMPTY, HIGH);
    delay(15); 
    digitalWrite(PIN_EMPTY, LOW);
    delay(500); 
    
    updateDisplay();
}

void updateDisplay() 
{
    if(state != LOADING)
    {
        // PRINT NAME
        lcd.clear();
        lcd.setCursor(0, 0);
        databaseOfNametags(nametag);
    
        // PRINT HEALTH
        lcd.setCursor(12, 0);
        if (state == DYING)
        {
            lcd.print("KIA");
            Serial.println("KIA");
            state = DEAD;
        }
        else 
        {
            if       (health == 100) {lcd.write(byte(1));}
            else if  (health < 100)  {lcd.write(byte(1)); lcd.print("0");}
            else if  (health < 10)   {lcd.write(byte(1)); lcd.print("00");}
            lcd.print(health);
        }
    }
    // PRINT MAGAZIN
    clearLCDLine(1); 
    lcd.setCursor(0, 1);
    if (state == EMPTY) 
    {
        lcd.print("[RELOAD]");
    }
    else 
    {
        for (int i = 0; i < magazin; i++) 
        {
            lcd.write(byte(0));
        }
    }
    Serial.println("UPDATE DISPLAY");
}

void clearLCDLine(int line)
{               
    lcd.setCursor(0,line);
    for(int n = 0; n < 16; n++)
    {
      lcd.print(" ");
    }
    lcd.setCursor(0,line);
}



// SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP
void setup() 
{
    Serial.begin(9600);
    //unsigned long previousMillis = millis();
    
  
    lcd.begin();
    lcd.createChar(0, bullet);
    lcd.createChar(1, heart);
    lcd.backlight();
    
    pinMode(PIN_BTN_FIRE, INPUT_PULLUP);
    pinMode(PIN_BTN_RELOAD, INPUT_PULLUP);
    pinMode(PIN_BTN_MENU, INPUT_PULLUP);
    
    pinMode(PIN_RECOIL, OUTPUT);
    pinMode(PIN_EMPTY, OUTPUT);
    pinMode(PIN_FEEDBACK, OUTPUT);
    
    pinMode(PIN_SENDER, OUTPUT);
    pinMode(PIN_RECEIVER, INPUT);
    
    irsend.enableIROut(38);
    irrecv.enableIRIn();
  
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Customs Lasertag");
    lcd.setCursor(4, 1);
    delay(500);
    lcd.print("by RECO");
    delay(1000);
  
    Serial.println("START - - - - - - - - - - - - - - - - - - - - - - - -");
    updateDisplay();
}

// LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP    LOOP
void loop() 
{
    // BUTTEN PRESSED CHECK
    if (digitalRead(PIN_BTN_MENU) == HIGH) {BTN_MENU_HOLD = millis(); }

    // UPDATE STATES
    if (health <= 0 && state != DEAD) {state = DYING;}
    else if (magazin <= 0)            {state = EMPTY;}
    else if ((state == READY || state == LOADING) && irrecv.decode(&results) && results.value != nametag && results.value > 0 && results.value < 30) {state = HIT;}
    
    if (irrecv.decode(&results) && results.value == 30) {restart();}   // RESTART BY EXT RESET-MODULE

    
    if (state != MENU && nametag == 0) {openMenu();}
    if (state == MENU && (millis() - BTN_MENU_HOLD) >= INTERVAL) {restart();}
    if (state == MENU && digitalRead(PIN_BTN_FIRE) == LOW) {toggleNametags();}

    if (state == EMPTY && digitalRead(PIN_BTN_RELOAD) == LOW) {reload();}
    if (state == EMPTY && digitalRead(PIN_BTN_FIRE) == LOW) {empty();}

    if (state == LOADING && digitalRead(PIN_BTN_FIRE) == LOW) {fire();}
    if (state == LOADING) {reload();}
    

    if (state == DYING) {updateDisplay();}
    if (state == DEAD && digitalRead(PIN_BTN_MENU) == LOW) {restart();}

    if (state == READY && digitalRead(PIN_BTN_FIRE) == LOW) {fire();}
    if (state == READY && digitalRead(PIN_BTN_RELOAD) == LOW) {reload();}
    if (state == READY && (millis() - BTN_MENU_HOLD) >= INTERVAL) {openMenu();}

    if (state == HIT) {hit(results.value);}

    
    
//    Serial.println(state);
    
    irrecv.resume();
    delay(10);
}

Ich auch nicht.

Ja, ich sehe da einige Verbesserungsmöglichkeiten.

z.B. deinen Status, könnte gut und gerne ein enum Dingen werden. Wenn dann noch die if durch switch/case ersetzt werden, kann der Compiler dir melden wenn dort falsche/fehlende Zustände auftreten.
Es ist eigentlich immer eine gute, Idee dafür zu sorgen, dass der Compiler Irrtümer bemerken kann.
if schmeckt mir sowieso nicht so. In der Not ja, aber wenn Alternativen möglich....
Ebenso mit #define

Also, ja, das scheint mir alles jetzt deutlich übersichtlicher zu sein!
Eine Entwicklung in die richtige Richtung.

Wo siehst du denn den Unterschied, zwischen switch-case mit default und if/else if mit else? In beiden Fällen kann man doch einen fehlenden Zustand bzw. Fehler erkennbar machen. (Auch wenn ich das jetzt nicht so 100%ig umgesetzt habe).

Was stört dich an #define. Ich bin extra von der Deklaration mit int ab, weil ich gelesen habe, dass dadurch Speicher gespart werde.

Wenn ich dich mit deinem Kommentar "enum-Dingen" richtig verstehe, meinst du, dass die Status linear aufeinander aufbauen sollen? Nach dem Prinzip state++;? Ich denke, das bringt nicht wirklich viel, weil man doch viel hin- und herspringen kann. Sehr linear ist das nicht. Aber vielleicht meinst du auch etwas Anderes.

Ein Thema nach dem anderen... OK?

  1. Nur weil du das gelesen hast, muss das nicht stimmen. Ein Test würde Klarheit bringen. Und bei dem ist die Wahrscheinlichkeit hoch, dass er keinerlei Einsparung ans Licht fördert.
  2. #define stammt aus der C Vergangenheit. Hier bei dir, ist keine Verwendungsnotwendigkeit gegeben
  3. #define ist eine reine Textersetzung, bietet keinerlei Typesicherheit.

Zu 3:

//#define PIN_BTN_FIRE 6
#define PIN_BTN_FIRE 6.35

Das geht ohne jegliche Meldung durch, obwohl doch die Datentypen sehr unterschiedlich sind. Das kann, nicht hier bei dir, aber es kann zu sehr schwer zu findenden Fehlern führen.
Defines sind für ihre unangenehmen Nebenwirkungen bekannt, gar gefürchtet.

Zu 2:

//#define PIN_BTN_FIRE 6
constexpr byte pinBtnFire {6.35}; // Geschrei
// constexpr byte pinBtnFire {6}; // ok

Zu 1:
Wenn es dem Compiler irgendwie möglich ist, wird er const(read only) Ausdrücke zur Kompilezeit auflösen. Dann macht es keinen Unterschied im Speicherverbrauch. Bei constexpr Ausdrücken hat er keine Chance dafür Speicher bereit zu stellen, bzw. schreit er auf, wenn man das erzwingen will.

Meine Empfehlung lautet:
Wenn es irgend möglich ist, auf #define verzichten. Da hängen einfach viel zu viele Pferdefüße dran. In vielfacher Hinsicht.

Ahhh, ich habe eine hitzige Diskussion zu dem Thema zwischen dir und @DrDiettrich entdeckt. Hab mir alles durchgelesen und verstehe, worauf du hinauswillst. :+1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.