Die void loop()-Methode ist äquivalent zu einer main()-Methode in einem C++/C-Programm. Sie wird, so lange wie der ESP32 läuft und keine anderweitigen Befehle erhält, kontinuierlich wiederholt. Um das Programm etwas optimaler zu gestalten und den Programmcode etwas zu verkürzen, haben wir eine globale Methode geschrieben, die die drei Zahlenwerte zwischen 0 und 255 übergeben bekommt und diese direkt per PWM auf die drei LEDs überträgt. Beim Programmieren von C/C++ ist es üblich eigens geschriebene, globale Methoden unterhalb der main-Methode zu platzieren, da auf diese sowieso von überall aus dem Programm zugegriffen werden kann. Auch wenn diese Methode in der Reihenfolge des Programmes also eigentlich am Schluss steht, gehen wir nun trotzdem als erstes auf sie ein, um größerer Verwirrung beim Durchgehen des restlichen Programmcodes auszuweichen. Die Methode sieht folgendermaßen aus:


/*        Globale Methode zur Programmoptimierung        */

void RGB_Color(int red, int green, int blue) //Methode zur Farbwahl der RGB-LED mit Zahlen von 0 bis 255
{
  ledcWrite(R_channel, red);  //Zuweisen eines Wertes zwischen 0 und 255 für den PWM-Channel der roten LED der RGB-LED
  ledcWrite(G_channel, green);  //Zuweisen eines Wertes zwischen 0 und 255 für den PWM-Channel der grünen LED der RGB-LED
  ledcWrite(B_channel, blue);  //Zuweisen eines Wertes zwischen 0 und 255 für den PWM-Channel der blauen LED der RGB-LED
}

Die Methode verwendet die Funktion ledcWrite(PWM-Kanal, Zahlenwert); und weist jeden der drei eingegebenen Zahlenwerte direkt dem richtigen PWM-Kanal zu, welcher die Zahl dann in einen äquivalenten Spannungspegel zwischen 3,3 V und 0 V umwandelt und diesen an die richtige LED weitergibt. Auf diese weise ersparst du dir die Arbeit die in der Methode enthaltenen Codezeilen im Laufe des Programmiervorgangs wiederholt eintippen zu müssen und schreibst lediglich den Methodennamen und die Argumente nieder.


Nachdem die Funktion dieser Methode nun klar ist, können wir uns dem Rest des Programmcodes, dem Loop, widmen:

/*        Abfragen und Einlesen eines Befehls und umsetzen dieses        */

void loop() //Diese Funktion wird nach der setup()-Funktion immer wieder durchlaufen, so lange der ESP32 eingeschaltet ist
{
  if (SerialBT.available()) //Abfrage, ob an der seriellen Bluetooth-Schnittstelle Daten zum Einlesen anliegen
  {
    order = "";  //String order wird zurückgesetzt

    while (SerialBT.available())  //So lange Daten an der seriellen Bluetooth-Schnittstelle anliegen, werden diese eingelesen
    {
      incomingChar = SerialBT.read(); //Einlesen eines Char aus dem übersendeten String
      order += incomingChar;  //Der String order wird um den eingelesenen Char erweitert
    }

    if (order == "flush") //Abfrage, ob der übersendete Befehl flush lautet
    {
      RGB_Color(0, 0, 0); //RGB-LED mit eigens definierter Funktion RGB_Color ausschalten
    }
    else if (order != "flush" && order != "a_on" && order != "")  //Abfrage, ob der übersendete Befehl eine Farbcodierung beinhaltet
    {
      String red; //Erzeugen eines Strings zum Zwischenspeichern der Zahl für die Farbe Rot
      String green; //Erzeugen eines Strings zum Zwischenspeichern der Zahl für die Farbe Grün
      String blue;  //Erzeugen eines Strings zum Zwischenspeichern der Zahl für die Farbe Blau
      int count = 0;  //Variable zum Zählen der Trennkommata
      String part;  //String zum Zwischenspeichern einzelner Chars

      for (int string_pos = 0; string_pos < order.length(); string_pos++) //for-Schleife, die die per Bluetooth übertragene RGB-Farbe mit der Sytax "Rot,Grün,Blau" auftrennt
      {
        part = order.charAt(string_pos);  //Dem String "part" wird der dem Index entsprechende Teil des Strings "order" zugewiesen

        if (count == 0 && part != ",")  //Wurde noch kein Komma detektiert und ist der momentane Char kein Komma, wird dieser Fall bearbeitet
        {
          red += order.charAt(string_pos);  //Die Zahl für die rote LED wird iterativ eingelesen
        }
        else if (count == 1 && part != ",") //Wurde ein Komma detektiert und ist der momentane Char kein Komma, wird dieser Fall bearbeitet
        {
          green += order.charAt(string_pos);  //Die Zahl für die grüne LED wird iterativ eingelesen
        }
        else if (count == 2)  //Wurden zwei Kommata detektiert, wird dieser Fall bearbeitet
        {
          blue += order.charAt(string_pos); //Die Zahl für die blaue LED wird iterativ eingelesen
        }
        else  //Entspricht der Char mit dem momentanen Index einem Komma, wird dieser Fall bearbeitet
        {
          count ++; //Es wurde ein Komma mehr detektiert
        }
      }
      
      RGB_Color(red.toInt(), green.toInt(), blue.toInt());  //Die aufgenommenen Zahlenwerte für die einzelnen LEDs werden in einen int umgewandelt und der LED als Farbe zugewiesen
    }
  }

  if (order == "a_on")  //Abfrgae, ob der übersendete Befehl a_on lautet
  {
    dallasTemp.requestTemperatures();  //Diese Methode ermöglicht das Anfordern von Temperaturwerten
    temp = dallasTemp.getTempCByIndex(0);  //Diese Methode fordert den momentanen Temperaturwert in °C an

    if (temp >= 35) //Prüfung, ob die Temperatur größer oder gleich 35 °C ist
    {
      RGB_Color(255, 0, 0); //RGB-LED leuchtet rot.
    }
    else if (temp < 35 && temp >= 25) //Prüfung, ob die Temperatur kleiner als 35 °C und größer oder gleich 25 °C ist
    {
      RGB_Color(255, 50, 0);  //RGB-LED leuchtet orange
    }
    else if (temp < 25 && temp >= 10) //Prüfung, ob die Temperatur kleiner als 25 °C oder größer oder gleich 10 °C ist
    {
      RGB_Color(238, 100, 0); //RGB-LED leuchtet gelb
    }
    else if (temp < 10 && temp >= -10)  //Prüfung, ob die Temperatur kleiner als 10 °C oder größer oder gleich -10 °C ist
    {
      RGB_Color(0, 0, 255); //RGB-LED leuchtet blau
    }
    else  //Die Temperatur unter -10 °C liegt
    {
      RGB_Color(148, 0, 211); //RGB-LED leuchtet lila
    }
  }
}

Zu Beginn der void loop-Methode wird mit if (SerialBT.available())  aus der BluetoothSerial-Bibliothek abgefragt, ob Daten an der Bluetooth-Schnittstelle zur Verfügung stehen und eingelesen werden können. Stehen keine Daten zur Verfügung, wird der gesamte if-Block übersprungen und das Programm springt direkt zu der Abfrage von if (order == "a_on") etwas weiter unten im Programmcode, welche überprüft, ob der Automatikmodus eingeschaltet wurde. Liegen allerdings Daten zum Einlesen an der seriellen Bluetooth-Schnittstelle an, so wird erst order zurückgesetzt. Anschließend wird mit der folgenden Schleifenstruktur so lange der vorderste Buchstabe der an der Bluetooth-Schnittstelle anliegenden Zeichenkette in incomingChar zwischengespeichert und an die bestehende Zeichenkette von order angereiht, bis keine Daten mehr an der seriellen Bluetooth-Schnittstelle anliegen. Das Einlesen funktioniert dabei über die SerialBT.read()-Methode aus der Bibliothek BluetoothSerial. Wenn die an der Bluetooth-Schnittstelle anliegende Zeichenkette abgearbeitet wurde, wurde das per Bluetooth übersendete Codewort komplett eingelesen und in order gespeichert.

while (SerialBT.available()) //So lange Daten an der seriellen Bluetooth-Schnittstelle anliegen, werden diese eingelesen
{
incomingChar = SerialBT.read(); //Einlesen eines Char aus dem übersendeten String
order += incomingChar; //Der String order wird um den eingelesenen Char erweitert
}


Danach folgen noch im selben Block zwei weitere if-Abfragen. Diese können noch in diesem großen if-Block stehen, da sie bei Empfangen eines bestimmten Befehls nur ein Mal durchlaufen werden müssen. Die Abfrage if (order == "a_on") darf nicht in dieser if-Struktur stehen, da sie ansonsten nur abgefragt werden würde, wenn ein Befehl von dem Smartphone versendet werden würde, was nicht kontinuierlich der Fall ist. Sobald der Automatikmodus aktiviert wurde, muss der Temperatursensor dauerhaft Werte liefern, welche ausgewertet und über die RGB-LED wiedergegeben werden müssen. Nun aber wieder zurück zu den anderen beiden abfragen. Der folgende Teil ist die erste der beiden Abfragen. Es wird nach dem Befehl "flush" gefragt, welcher das Codewort zum Rücksetzen des Steuerungsscreens in den Grundzustand und zum Ausschalten der RGB-LED darstellt. An diesem Beispiel wird auch gut die Funktion der eigens definierten Methode deutlich.

if (order == "flush") //Abfrage, ob der übersendete Befehl flush lautet
{
  RGB_Color(0, 0, 0); //RGB-LED mit eigens definierter Funktion RGB_Color ausschalten
}


Die zweite dieser beiden if-Abfragen kontrolliert, ob der übersendete Befehl ein Farbcode für den manuellen Modus ist. Die Smartphone-App wird so erstellt, dass lediglich drei Arten von Codewörtern versendet werden können. Entweder "flush""a_on" oder ein Farbcode mit der Syntax "rot,grün,blau". Die Textfelder werden so eingestellt, dass dort nur ganze Zahlen Zahlen eingegeben werden können. Wird eines der drei Textfelder leer gelassen, so wird der Code "0,0,0" an den ESP32 gesendet, die RGB-LED bleibt also aus. Ist der übersendete Befehl nun also weder "flush" noch "a_on" noch unverändert "", so kann es nach dem Ausschlussprinzip lediglich ein Farbcode für den manuellen Modus sein. Dieser wird dann mit dem folgenden Algorithmus aufgetrennt, indem die darin enthaltenen Kommata gezählt werden, da diese sich in ihrer Anzahl nicht verändern. Die drei Zahlen werden als Strings red, green und blue zwischengespeichert und können mit der Methode toInt() in einen Integer umgewandelt werden. Der Algorithmus verwendet die Methoden length() und charAt(...), um zum einen die Länge einer Zeichenkette herauszufinden und die Grenze der for-Schleifenstruktur danach zu richten und zum anderen auf einzelne Elemente der Zeichenkette mit bestimmtem Index zuzugreifen.

else if (order != "flush" && order != "a_on" && order != "") //Abfrage, ob der übersendete Befehl eine Farbcodierung beinhaltet
{
String red; //Erzeugen eines Strings zum Zwischenspeichern der Zahl für die Farbe Rot
String green; //Erzeugen eines Strings zum Zwischenspeichern der Zahl für die Farbe Grün
String blue; //Erzeugen eines Strings zum Zwischenspeichern der Zahl für die Farbe Blau
int count = 0; //Variable zum Zählen der Trennkommata
String part; //String zum Zwischenspeichern einzelner Chars

      for (int string_pos = 0; string_pos < order.length(); string_pos++) //for-Schleife, die die per Bluetooth übertragene RGB-Farbe mit der Sytax "Rot,Grün,Blau" auftrennt
      {
        part = order.charAt(string_pos);  //Dem String "part" wird der dem Index entsprechende Teil des Strings "order" zugewiesen

        if (count == 0 && part != ",")  //Wurde noch kein Komma detektiert und ist der momentane Char kein Komma, wird dieser Fall bearbeitet
        {
          red += order.charAt(string_pos);  //Die Zahl für die rote LED wird iterativ eingelesen
        }
        else if (count == 1 && part != ",") //Wurde ein Komma detektiert und ist der momentane Char kein Komma, wird dieser Fall bearbeitet
        {
          green += order.charAt(string_pos);  //Die Zahl für die grüne LED wird iterativ eingelesen
        }
        else if (count == 2)  //Wurden zwei Kommata detektiert, wird dieser Fall bearbeitet
        {
          blue += order.charAt(string_pos); //Die Zahl für die blaue LED wird iterativ eingelesen
        }
        else  //Entspricht der Char mit dem momentanen Index einem Komma, wird dieser Fall bearbeitet
        {
          count ++; //Es wurde ein Komma mehr detektiert
        }
}


Abschließend wird nach dem Einlesen der drei Ziffern die definierte Farbe per PWM auf die RGB-LED übertragen. Die Abfrage, ob die eingegebenen Werte in der App außerhalb der gesetzten Grenzen der RGB-Codierung liegen, wird in der App durchgeführt und muss hier nicht mehr beachtet werden. Liegen die Werte außerhalb der Grenzen oder wurde nichts in eines der Textfelder eingegeben, so wird der Code "0,0,0" übersendet.

RGB_Color(red.toInt(), green.toInt(), blue.toInt());  //Die aufgenommenen Zahlenwerte für die einzelnen LEDs werden in einen int umgewandelt und der LED als Farbe zugewiesen     


In dem letzten Teil des Loops, der Abfrage nach dem Befehl "a_on", also dem Automatikmodus, wird mit Hilfe einer if-Struktur abgefragt, welchen Wert der in der Variable temp gespeicherte Temperaturwert besitzt. Liegt dieser wert über oder auf 35 °C, so färbt sich die RGB-LED rot. Unterhalb von 35 °C und oberhalb und auf 25 °C leuchtet die RGB-LED orange. Unter 25 °C und über sowie auf 10 °C nimmt die Unterbodenbeleuchtung die Farbe Gelb an. Unterhalb von 10 °C bis einschließlich -10 °C leuchtet die RGB-LED blau und unterhalb von -10 °C lila. Die in die Methode RGB_Color(...) eingegebenen Werte sind dabei Erfahrungswerte, welche mithilfe einer Farbtabelle verfeinert wurden. Die beiden zu Beginn dieses Blockes verwendeten Methoden sind für die Temperaturerfassung dabei essentiell. Sie entstammen der DallasTemperture-Bibliothek und werden durch ihre Kommentare bereits ausreichend beschrieben. Der Index 0 bei der zweiten Methode signalisiert dem ESP32 und dem DS18B20, dass nur ein einziger Sensor an die OneWire-Leitung angeschlossen wurde.

Mit der Vollendung von dem Loop ist der Programmcode für den ESP32 fertig und wurde ganz nach der erstellten Planung programmiert. Anschließend kann der Code auf den ESP32 hochgeladen werden. Wie das funktioniert und was du beachten musst wird im nächsten Abschnitt behandelt.

Last modified: Tuesday, 23 January 2024, 3:14 PM