Timer mit Button und zwei Phasen

Hallo zusammen,

ich bin blutige Anfängerin beim Thema Programmierung und Arduino und beiße mir beim Thema Timer mit verschiedenen Phasen gerade die Zähne aus. Ich habe mittlerweile so viele verschiedene Codes gelesen, die mit Timern arbeiten, aber andere Hardware verbaut haben als ich, und die Variablen verwirren mich so sehr, dass ich es nicht schaffe, es auf mein Projekt zu übertragen. Ich wäre euch wirklich sehr dankbar, wenn ihr mir bitte weiterhelfen könntet.

Die Hardware ist fertig und funktioniert. Ich verwendet einen Arduino Nano, einen Ultraschallsensor, einen Buzzer, einen Neopixel-Stick mit 8 Neopixels und einen Button.

Mein Grundkonzept kurz erklärt: Mein Gerät soll den Arbeiter am Bildschirm daran erinnern, dass er min. 50 cm Abstand zum Bildschirm haben sollte, und alle 20 Minuten für 2 Minuten in die Ferne schauen soll (Stichwort Augenstress mindern).

Das Gerät wird auf dem Bildschirm platziert. Betätigt man den Button, wird die "Bildschirmphase" gestartet und der 20-Minuten-Timer fängt an. Die Abstandsmessung zum Bildschirm soll nur in dieser Phase stattfinden (die funktioniert schon). Nach 20 Minuten wird die "PausePhase" gestartet. Die Neopixels sollen kurz aufleuchten und der Buzzer gibt einen Signalton ab. Nach Ablauf der 2-minütigen "Pausephase" soll das Ganze wieder von vorne beginnen.

Unterbrochen wird der Loop durch erneutes Drücken des Buttons, dann ist quasi alles wieder auf "Off" und es wird gewartet, bis der Button wieder auf "On" gestellt wird.

Ich hoffe es ist verständlich, was ich meine. Falls es hilft, poste ich hier noch eine der vielen Code-Varianten, die nicht funktionieren. xD Da funktioniert das mit der Bildschirmphase schon, aber wenn er dann in die Pausephase springt, bleibt er da und geht nicht wieder zurück. Dass der Button beim erneuten Drücken auf Off geht, ist da auch noch nicht integriert.

.
.
.
//Einrichten des Timer-Buttons
  #define buttonPin  12
  int buttonState = 0;
  boolean oldState = HIGH;
  bool buttonPressed = false;
  int switchVar;
  boolean newState;

//MILLIS
  int eyeTimer = 0;
  int eyeTimeout = 20000; //20 Sek    //1200000 = 20 Min
  int eyeBreak = 5000;      //5 Sek

//Andere Globale Werte
  #define Warte 400

/**************************************
//SETUP
**************************************/

void setup() {
  Serial.begin(9600);

  // Definieren der Eingabe-Pins
  pinMode(echoPin, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  
  // Definieren der Ausgabe-Pins
  pinMode(trigPin, OUTPUT);
  pinMode(buzzPin, OUTPUT);

  // Initialisieren des Neo-Pixel Strips
  strip.begin();
  strip.show();  // Initialisiert alle Pixels auf "Off" 
  
  switchVar = 0;
}

/**************************************
//Loop
**************************************/

void loop() {

  switch(switchVar){
    
    case 0:
      Serial.println("Button wird gelesen");
      newState = digitalRead(buttonPin);
      
      if ((newState == LOW) && (oldState == HIGH)) {
        // Short delay to debounce button.
        delay(20);
        buttonPressed = true;
      } else {
        buttonPressed = false;
      }

      if(buttonPressed == true){
        switchVar = 1;
      }
      
     break;
      
     case 1:
     bool raus = false;
     int timer;
     Serial.println("Case 1 entered");
     colorWipe(strip.Color(  255, 0,   0), 50);    // Grün leuchtet kurz auf
     eyeTimer = millis(); //Timer wird gestartet
     eyeBreak = eyeTimer + eyeTimeout;

     while(!raus){

        timer = millis();

        if(timer >= eyeBreak){
          raus = true;
          Serial.println("eyeBreak entered");
          }
        
        Serial.println("Zielzeit:");
        Serial.println(eyeBreak);
        Serial.println("Millisekunden");
        Serial.println(timer);
        Serial.println("In While-Loop");
        abstandMessen();
      }

      tone(buzzPin, G5);
      delay(Warte);
      noTone(buzzPin);
      rainbow(10);

      switchVar = 0;
      
     break;
  }

    Serial.println("Button:");
    Serial.println(buttonState);
}
.
.
.

Danke und viele Grüße,
Sandra

Dein Sketch ist fast nicht zu lesen. In einem Mobilgerät überhaupt nicht.
Setze den bitte in Code-Tags.

Verwende dazu die Schaltfläche </> oben links im Editorfenster.
Das kannst du auch nachträglich machen.
Dazu den Sketch markieren und die Schaltfläche klicken, oder [code] davor und [/code] dahinter ohne *.

Damit wird dieser für alle besser lesbar.
Das kannst du auch noch nachträglich machen.

Und da die Zeiten des Arduino nicht sehr genau sind, empfehle ich dir die Verwendung einer RTC, die DS3231 ist sehr genau.

HotSystems:
Dein Sketch ist fast nicht zu lesen. In einem Mobilgerät überhaupt nicht.
Setze den bitte in Code-Tags.

Verwende dazu die Schaltfläche </> oben links im Editorfenster.
Das kannst du auch nachträglich machen.
Dazu den Sketch markieren und die Schaltfläche klicken, oder [code] davor und [/code] dahinter ohne *.

Damit wird dieser für alle besser lesbar.
Das kannst du auch noch nachträglich machen.

Und da die Zeiten des Arduino nicht sehr genau sind, empfehle ich dir die Verwendung einer RTC, die DS3231 ist sehr genau.

Danke für den Hinweis, da merkt man, dass ich ganz neu in diesem Forum bin. Habe ich gleich geändert und hoffe, es ist jetzt besser lesbar. :slight_smile:

Die Empfehlung mit der RTC werde ich mir merken, danke. Ich würde es so zum Testen aber erstmal mit der integrierten Uhr probieren wollen.

Ein paar Anmerkungen:

  • Strg+t in der IDE formatiert Dein Programm.
  • Die Variablen- und Konstantentypen sind teils unglücklich, teils falsch.
  • strip.Color( 255, 0, 0) sollte entsprechend RGB Rot ergeben. Initialisierungsfehler im geheimen Teil Deines Programms.
  • Du verwendest eine Schrittkette und millis(), aber leider auch ein blockierndes while. Bleibe bei der Schrittkette, das ist einfacher.

Ausbaufähiger Ansatz:

#include <Adafruit_NeoPixel.h> // include the Neopixel Library in this Sketch
#define PIN 11 // This is the Arduino Pin controlling the LEDstrip.
#define NUMPIXELS 8
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

//Einrichten des Timer-Buttons
const byte buttonPin = 2;
const byte buzzPin = 13;
enum {WARTEN, BILDSCHIRMPHASE, BUZZEIN, INDIEFERNESCHAUEN};
byte schritt = WARTEN;

//MILLIS
uint32_t eyeTimer;
const uint32_t ARBEITSZEIT = 20000; //20 Sek    //1200000 = 20 Min
const uint32_t PAUSENZEIT = 5000;      //5 Sek
const uint32_t BUZZZEIT = 200;

/**************************************
  //SETUP
**************************************/

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buzzPin, OUTPUT);
  strip.begin();
  strip.fill(strip.Color(0 , 0 , 255), 0, strip.numPixels());
  strip.show();  // Initialisiert alle Pixels auf "Off"
}

/**************************************
  //Loop
**************************************/

void loop() {
  switch (schritt) {
    case WARTEN:
      if (!digitalRead(buttonPin)) { // gedrückt = LOW
        strip.fill(strip.Color(0 , 255 , 0), 0, strip.numPixels());
        strip.show();  // Initialisiert alle Pixels auf "Off"
        eyeTimer = millis();
        schritt = BILDSCHIRMPHASE;
      }
      break;

    case BILDSCHIRMPHASE:
      if (millis() - eyeTimer >= ARBEITSZEIT) {
        strip.fill(strip.Color(255 , 0 , 0), 0, strip.numPixels());
        strip.show();  // Initialisiert alle Pixels auf "Off"
        digitalWrite(buzzPin, HIGH);
        eyeTimer = millis();
        schritt = BUZZEIN;
      }
      break;
    case BUZZEIN:
      if (millis() - eyeTimer >= BUZZZEIT) {
        digitalWrite(buzzPin, LOW);
        schritt = INDIEFERNESCHAUEN;
      }
      break;

    case INDIEFERNESCHAUEN:
      if (millis() - eyeTimer >= PAUSENZEIT) {
        strip.fill(strip.Color(0 , 255 , 0), 0, strip.numPixels());
        strip.show();  // Initialisiert alle Pixels auf "Off"
        eyeTimer = millis();
        schritt = BILDSCHIRMPHASE;
      }
      break;
  }
}

Hallo,

Du solltest erst mal Deine Aufgabe in zeitliche Abschnitte gliedern , dann kommst Du schnell drauf das eine Ablaufsteuerung , Schrittkette, Endlicher Automat , Zustandsautomat gut geeignet ist. Das sind alles Begriffe für letztlich das gleiche. Es soll ein Ablauf in einer festgelegten Reihenfolge gesteuert werden. Beispiele dazu kannst Du hier im Forum finden.

Warten auf ein Schalter
Messen 20 min
Pause 2 min

Für die Zustände messen und pause erstellst Du Dir dann je eine eigene Funktion damit kannst Du das auch einzeln testen.

Zusätzich fragst Du den Schalter immer ab damit du jederzeit in den wartetzstand zurück kannst.

Das Thema millis() hast Du ja bereits angewendet.

Heinz

[/quote]

agmue:
Ein paar Anmerkungen:

  • Strg+t in der IDE formatiert Dein Programm.
  • Die Variablen- und Konstantentypen sind teils unglücklich, teils falsch.
  • strip.Color( 255, 0, 0) sollte entsprechend RGB Rot ergeben. Initialisierungsfehler im geheimen Teil Deines Programms.
  • Du verwendest eine Schrittkette und millis(), aber leider auch ein blockierndes while. Bleibe bei der Schrittkette, das ist einfacher.

Ausbaufähiger Ansatz:

#include <Adafruit_NeoPixel.h> // include the Neopixel Library in this Sketch

#define PIN 11 // This is the Arduino Pin controlling the LEDstrip.
#define NUMPIXELS 8
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

//Einrichten des Timer-Buttons
const byte buttonPin = 2;
const byte buzzPin = 13;
enum {WARTEN, BILDSCHIRMPHASE, BUZZEIN, INDIEFERNESCHAUEN};
byte schritt = WARTEN;

//MILLIS
uint32_t eyeTimer;
const uint32_t ARBEITSZEIT = 20000; //20 Sek    //1200000 = 20 Min
const uint32_t PAUSENZEIT = 5000;      //5 Sek
const uint32_t BUZZZEIT = 200;

/**************************************
 //SETUP
**************************************/

void setup() {
 pinMode(buttonPin, INPUT_PULLUP);
 pinMode(buzzPin, OUTPUT);
 strip.begin();
 strip.fill(strip.Color(0 , 0 , 255), 0, strip.numPixels());
 strip.show();  // Initialisiert alle Pixels auf "Off"
}

/**************************************
 //Loop
**************************************/

void loop() {
 switch (schritt) {
   case WARTEN:
     if (!digitalRead(buttonPin)) { // gedrückt = LOW
       strip.fill(strip.Color(0 , 255 , 0), 0, strip.numPixels());
       strip.show();  // Initialisiert alle Pixels auf "Off"
       eyeTimer = millis();
       schritt = BILDSCHIRMPHASE;
     }
     break;

case BILDSCHIRMPHASE:
     if (millis() - eyeTimer >= ARBEITSZEIT) {
       strip.fill(strip.Color(255 , 0 , 0), 0, strip.numPixels());
       strip.show();  // Initialisiert alle Pixels auf "Off"
       digitalWrite(buzzPin, HIGH);
       eyeTimer = millis();
       schritt = BUZZEIN;
     }
     break;
   case BUZZEIN:
     if (millis() - eyeTimer >= BUZZZEIT) {
       digitalWrite(buzzPin, LOW);
       schritt = INDIEFERNESCHAUEN;
     }
     break;

case INDIEFERNESCHAUEN:
     if (millis() - eyeTimer >= PAUSENZEIT) {
       strip.fill(strip.Color(0 , 255 , 0), 0, strip.numPixels());
       strip.show();  // Initialisiert alle Pixels auf "Off"
       eyeTimer = millis();
       schritt = BILDSCHIRMPHASE;
     }
     break;
 }
}

Großartig!! Das war mir eine riesige Hilfe und hat mir die benötigte "Erleuchtung" gebracht. :slight_smile: Vielen tausend Dank! Du hast Recht, das die Variablen ziemlich falsch/unglücklich formuliert waren, so habe ich jetzt wirklich besser durchgesehen. Ich habe mich heute Nachmittag nochmal mit einem Kommilitonen drangesetzt und wir haben jetzt noch integriert, dass ein weiterer ButtonPush wieder auf die Warteposition zurück wechselt. Somit funktioniert jetzt alles ungefähr so, wie ich es wollte. Danke nochmal.

Rentner:
Hallo,

Du solltest erst mal Deine Aufgabe in zeitliche Abschnitte gliedern , dann kommst Du schnell drauf das eine Ablaufsteuerung , Schrittkette, Endlicher Automat , Zustandsautomat gut geeignet ist. Das sind alles Begriffe für letztlich das gleiche. Es soll ein Ablauf in einer festgelegten Reihenfolge gesteuert werden. Beispiele dazu kannst Du hier im Forum finden.

Warten auf ein Schalter
Messen 20 min
Pause 2 min

Für die Zustände messen und pause erstellst Du Dir dann je eine eigene Funktion damit kannst Du das auch einzeln testen.

Zusätzich fragst Du den Schalter immer ab damit du jederzeit in den wartetzstand zurück kannst.

Das Thema millis() hast Du ja bereits angewendet.

Heinz

Vielen Dank für deinen Tipp, Heinz. Ich habe die Logik jetzt ungefähr so aufgebaut. :slight_smile: Ein paar Bugs sind noch drin, aber für einen ersten Test reicht es erstmal. Der Hinweis mit den eigenen Funktionen für jede Phase ist sehr gut, das werde ich mal ausprobieren. Ich werde meinen "finalen" Code hier dann nochmal posten, falls jemand mal ein ähnliches Problem haben sollte. Vielleicht hilft es ja jemandem weiter. ^^

sandra149:
Das war mir eine riesige Hilfe und hat mir die benötigte "Erleuchtung" gebracht. :slight_smile:

Bitte gerne :slight_smile:

Als ich durch dieses Forum die Schrittkette (=endlicher Automat =finite state machine) und die Verwendung von millis gelernt hatte, kam ich mir auch wie erleuchtet vor, weil Aufgaben viel leichter zu lösen waren.

sandra149:
Ich werde meinen "finalen" Code hier dann nochmal posten, falls jemand mal ein ähnliches Problem haben sollte. Vielleicht hilft es ja jemandem weiter. ^^

Ein Forum sollte aus Nehmen und Geben bestehen, daher ja bitte, ich würde mich freuen.

So, es ist noch nicht alles perfekt, aber das ist jetzt erstmal mein Ergebnis in diesem Projekt. :slight_smile:
Eine der LEDs ist kaputt, das liegt nicht am Code, nur daran, dass mir der Nano zuvor leider zwei Mal durchgebrannt ist. :cry:

Hier ein kurzes Video des Prototypen:

Und hier der Code:

/**************************************
  //Globale Variablen
**************************************/

//Einrichten des Ultraschallsensors
const int echoPin = 4;
const int trigPin = 6;
long Dauer;
int Abstand;
int minAbstand = 50;  //ab welchem Abstand in cm soll das Warnsignal ertönen

//Einrichten des Buzzer
const int buzzPin = 8;

//Notenfrequenz definieren
#define C4  262
#define D4  294
#define E4  330
#define F4  349
#define G4  392
#define A4  440
#define B4  494
#define C5  523
#define D5  587
#define E5  659
#define F5  698
#define G5  784
#define A5  880
#define B5  988

//Einrichten des NeoPixel Sticks
#include <Adafruit_NeoPixel.h>
#define neoPin     10
#define Pixelzahl  8
Adafruit_NeoPixel strip(Pixelzahl, neoPin, NEO_RGB + NEO_KHZ800);

//Einrichten des Timer-Buttons
const byte buttonPin = 12;
enum { WARTEN = 1, BILDSCHIRMPHASE = 2, PAUSENPHASE = 3 };
byte phase = WARTEN; //Programm startet immer in der WARTEN Phase

//MILLIS
uint32_t currentTime = 0;
uint32_t lastOutputTime = 0;
uint32_t startTime = 0;
uint32_t startPauseTime = 0;
const uint32_t ARBEITSZEIT = 15000;   //15 Sek zum Testen    //1200000 = 20 Min
const uint32_t PAUSENZEIT  = 8000;    //8 Sek
byte buttonWasPressed = false;        //für die On/Off Funktion des Buttons

//Andere Globale Werte
#define Warte 400


/**************************************
  //SETUP
**************************************/

void setup() {
  Serial.begin(9600);

  // Definieren der Eingabe-Pins
  pinMode(echoPin, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  // Definieren der Ausgabe-Pins
  pinMode(trigPin, OUTPUT);
  pinMode(buzzPin, OUTPUT);

  // Initialisieren des Neo-Pixel Strips
  strip.begin();
  colorWipe(strip.Color(127,   127,   127), 70);  //Arduino an Strom angeschlossen, LEDs leuchten Weiß auf
  strip.clear();  //alle LEDS wieder auf off
  strip.show();  // Farbwert aktualisieren
}


/**************************************
  //Loop
**************************************/

void loop() {

  currentTime = millis();  //Speichert die aktuelle Zeit in der Variable ab

  //Wenn Button gedrückt wird
  if (digitalRead(buttonPin) == false) {
    buttonWasPressed = true;

    // Solange der Button noch gedrückt wird, warten.
    while (digitalRead(buttonPin) == false) {
      delay(5);
    }
  }

  switch (phase) {

    case WARTEN:
      colorWipe(strip.Color(127,   127,   0), 70);  //Gelbes Blinken
      delayButton(2000);
      strip.clear();

      //Wenn während der WARTEN-Phase der Button gedrückt wird, starte BILDSCHIRMPHASE.
      if (buttonWasPressed) {
        colorWipe(strip.Color(0, 127, 0), 50); // Grün aufleuchten
        strip.show();
        startTime = currentTime;
        phase = BILDSCHIRMPHASE;
        buttonWasPressed = false;
      }

      break;

    case BILDSCHIRMPHASE:
      abstandMessen();  //führe in der BILDSCHIRMPHASE die Abstandsmessung durch

      //Wenn während der BILDSCHIRMPHASE der Button gedrückt wird, zurück in WARTEN-Phase.
      if (buttonWasPressed) {
        phase = WARTEN;
        buttonWasPressed = false;
      }
      //Andernfalls warte bis ARBEITSZEIT abgelaufen ist und gehe zur PAUSENPHASE über.
      else if (currentTime - startTime >= ARBEITSZEIT) {
        startPauseTime = currentTime;
        colorWipeTone(strip.Color(0, 0, 127), 80, buzzPin, C5); // Blau aufleuchten + Tonsignal
        strip.show();
        phase = PAUSENPHASE;
      }

      break;

    case PAUSENPHASE:
      theaterChaseRainbow(5); //Spiele den Theater-Rainbow Effekt

      //Wenn während der PAUSENPHASE der Button gedrückt wird, zurück in WARTEN-Phase.
      if (buttonWasPressed) {
        phase = WARTEN;
        buttonWasPressed = false;
      }
      //Andernfalls warte bis PAUSENZEIT abgelaufen ist und gehe wieder in BILDSCHIRMPHASE über.
      else if (currentTime - startPauseTime >= PAUSENZEIT) {
        startTime = currentTime;
        colorWipeTone(strip.Color(0, 0, 127), 80, buzzPin, C4); // Blau aufleuchten + Tonsignal
        strip.show();
        phase = BILDSCHIRMPHASE;
      }

      break;
  }
}


/**************************************
  //Eigene Funktionen
**************************************/

void abstandMessen() {
  //Clear trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  //Schaltet den tripPin für 10 Mikrosekunden an
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  //Liest den echoPin, gibt die Reisezeit der Schallwelle in Mikrosekunden zurück
  Dauer = pulseIn(echoPin, HIGH);

  //Berechnet den Abstand
  Abstand = Dauer * 0.034 / 2;

  //NeoPixel Stick
  strip.clear(); // Alle Pixelfarben auf 'Off'

  //***WENN Abstand unter 50 cm***
  if (Abstand < minAbstand) {

    //Farbe ROT
    theaterChase(strip.Color(127, 0, 0), 50); // Rot Blinkend
    strip.show();
    delayButton(Warte);

    //Spiele Alarm-Jingle
    tone(buzzPin, D4);
    delayButton(Warte);
    tone(buzzPin, C5);
    delayButton(Warte);
    tone(buzzPin, G5);
    delayButton(Warte + 500);
    noTone(buzzPin);
  
    //ANDERNFALLS
  } else { 
    strip.show();
    delayButton(Warte);
    noTone(buzzPin);
  }
}


//Verhindert, dass lange Delays den Reset durch erneutes Drücken des Buttons blockieren
void delayButton(int milliseconds) {
  uint32_t startDelayTime = millis();

  while (millis() < startDelayTime + milliseconds) {
    if (digitalRead(buttonPin) == false) {
      return;
    }
    delay(2);
  }
}


void colorWipeTone(uint32_t color, int wait, int buzzPin, unsigned int frequency) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    strip.show();

    if (i == 1) {
      // Schalte Ton ein
      tone(buzzPin, frequency);
    }

    delayButton(wait);  // Pause for a moment

    if (i == 5) {
      // Schalte Ton ab
      noTone(buzzPin);
    }
  }
}


//KOPIERT AUS NEO-PIXEL BEISPIEL

void colorWipe(uint32_t color, int wait) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    strip.show();
    delayButton(wait);
  }
}

void theaterChase(uint32_t color, int wait) {
  for (int a = 0; a < 10; a++) {
    for (int b = 0; b < 3; b++) {
      strip.clear();

      for (int c = b; c < strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color);
      }
      strip.show();
      delayButton(wait);
    }
  }
}

void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;
  for (int a = 0; a < 30; a++) {
    for (int b = 0; b < 3; b++) {
      strip.clear();

      for (int c = b; c < strip.numPixels(); c += 3) {
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue));
        strip.setPixelColor(c, color);
      }
      strip.show();
      delayButton(wait);
      firstPixelHue += 65536 / 90;
    }
  }
}

Nochmals vielen Dank für eure Hilfe! :slight_smile:

Hallo Sandra,
ich finde das , wie Du es mit Deinem Gehäuse gelöst hast sehr ansprechend. Sieht toll aus.

Danke für das Video.

LG Stefan

Danke :slight_smile:

Bitte überlege, was nach etwas mehr als 49 Tagen beim Überlauf von millis() passiert.

Hallo,

und schalte bitte alle Warnungen ein.

In der IDE alle Ausgaben einschalten:
Datei > Voreinstellungen >

  • Ausführliche Ausgabe während > beide Haken rein
  • Compilerwarnungen > "ALLE"
    Zeilennummern und Codefaltung sind auch hilfreich.

Dann darfst du in paar for Schleifen den Datentyp korrigieren für Vergleiche.

Wenn das mit dem millis noch behoben ist sieht das schon ganz gut aus. Was mir persönlich nie gefällt ist der Mischmasch aus define und den verschiedenen Datentyp Schreibweisen. Man sollte sich dann schon entscheiden.