Ankündigung

Einklappen
Keine Ankündigung bisher.

ARDUINO am KNX

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Bonscha
    antwortet
    Reagiert leider auch nicht bei: groupwrite ip:localhost 15/0/0 1. Auch wenn ich per ETS sende versteht der Arduino das Telegramm nicht... Der Schaltaktor kann damit wunderbar umgehen.
    Ist es nicht sowieso egal, in welcher Form das Telegramm ankommt? Die LED müsste ja immer angehen, oder nicht?

    Einen Kommentar schreiben:


  • vento66
    antwortet
    1 Bit mit groupwrite senden

    Einen Kommentar schreiben:


  • Bonscha
    antwortet
    So, nachdem mir mal aufgefallen ist, dass RX und TX über Kreuz verbunden werden müssen, und ich das entsprechend am Arduino getauscht habe, schaltet der Sketch jetzt fleißig alle 3 Sekunden meinen Schaltaktor.

    Leider passiert noch immer nichts, wenn ich per eibd ein Telegramm an 15/0/0 sende: groupswrite ip:localhost 15/0/0 1
    Liegt das jetzt daran, wie ich es sende, oder am Arduino?

    Einen Kommentar schreiben:


  • Bonscha
    antwortet
    Moin Thorsten,

    bis eben hatte ich mit Karduino probiert. Dann habe ich auf deine Library umgestellt. Hier mein aktueller und noch immer nicht funktioneller Code:

    Code:
    #include <KnxTpUart.h>
    #include <EEPROM.h>
    
    KnxTpUart knx(&Serial, "1.1.199");
    int LED = 6;
    
    
    void setup() {
    
      pinMode(LED, OUTPUT); // Setting up status LED
    
      Serial.begin(19200);
      UCSR0C = UCSR0C | B00100000; // Even Parity
    
      knx.uartReset();
      knx.setListenToBroadcasts(true);
    
      knx.addListenGroupAddress("15/0/0");
    
    }
    
    
    void loop() {
    
      digitalWrite(LED, HIGH);
      knx.groupWriteBool("0/0/1", 1);
      delay(3000);
    
      digitalWrite(LED, LOW);
      knx.groupWriteBool("0/0/1", 0);
      delay(3000);
    
    }
    
    
    void serialEvent()
    {
      //Get Serial Event
      KnxTpUartSerialEventType eType = knx.serialEvent();
    
      //Check Serial Event
      if (eType == KNX_TELEGRAM)
      {
        KnxTelegram* telegram = knx.getReceivedTelegram();
    
        // Telegrammauswertung auf KNX (bei Empfang immer notwendig)
        String target =
          String(0 + telegram->getTargetMainGroup())   + "/" +
          String(0 + telegram->getTargetMiddleGroup()) + "/" +
          String(0 + telegram->getTargetSubGroup());
    
        // Auswertung der Gruppenadresse des empfangenen Telegrammes und Zwischenspeicherung in Variable target
        if (telegram->getCommand() == KNX_COMMAND_WRITE)
        {
          // Auswertung des empfangenen KNX-Telegrammes mit Schreibbefehl (Flag) -> Aktion
          if (target == "15/0/0") {
            digitalWrite(LED, HIGH);
            delay(30000);
          }
        }
      }
    }
    Die LED blinkt fleißig, und das wars dann auch.

    Läuft übrigens auf einem Nano, falls das ein Grund sein könnte... Kann ich mir aber nicht vorstellen...

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Du solltest dazuschreiben welche Lib du verwendest (meine ist hier: https://bitbucket.org/thorstengehrig...nx-user-forum/ ).
    Falls du "meine" Einsetzt ist die Schreibweise definitiv falsch!
    Ich habs extra einfach gehalten -

    KnxTpUart knx(&Serial, PA_INTEGER(1,1,199));
    knx.groupWrite(GA_INTEGER(0,0,1), 1);
    wäre da
    KnxTpUart knx(&Serial, “1.1.199”);
    knx.groupWriteBool(“0/0/1”, 1);



    Gruß
    Thorsten
    Zuletzt geändert von ThorstenGehrig; 25.10.2015, 20:08.

    Einen Kommentar schreiben:


  • Bonscha
    antwortet
    Moin,

    ich habe jetzt auch ein wenig probiert und leider funktioniert selbst folgender Code nicht bei mir:

    Code:
    #include <KnxTpUart.h>
    #include <EEPROM.h>
    
    #define KNX_BAUDRATE       19200 // Define Serial Baudrate to Siemens 5WG1
    // #define KNX_SEND_ALIVE_GA  "0/0/1"
    KnxTpUart knx(&Serial, PA_INTEGER(1,1,199));
    int LED = 6;
    
    
    void setup() {
      pinMode(LED, OUTPUT); // Setting up status LED
        
      Serial.begin(19200);
      UCSR0C = UCSR0C | B00100000; // Even Parity
    
      knx.uartReset();
    }
    
    
    void loop() {
    
      knx.groupWrite(GA_INTEGER(0,0,1), 1);
      delay(3000);
      knx.groupWrite(GA_INTEGER(0,0,1), 0);
      delay(3000);
    }
    Auf der 0/0/1 sitzt ein Schaltkanal, das Licht sollte blinken, doch nichts passiert.
    Telegramme empfangen war ebenfalls Fehlanzeige.

    Da ich Probleme hatte mit den unterschiedlichen Schreibweisen der GA/PA, z.B. als GA_INTEGER(0,0,1) bzw. einfach (0/0/1), und hier leider unzählige verschiedene Versionen kursieren, habe ich gehofft, euch fällt da direkt ein Fehler ins Auge...

    Einen Kommentar schreiben:


  • tuxedo
    antwortet
    Dann liegt die Latenz irgendwo bei mehreren Wochen. Hat sich gefühlt seit einer halben Ewigkeit nichts mehr geändert ;-)
    Ich warte dann mal bis ihr aufgeholt habt.

    Einen Kommentar schreiben:


  • JuMi2006
    antwortet
    Dito hier ... und bis ich die erste Änderung von Dir verfolgen kann hast Du schon 3 weitere gebracht -> Meine Latenz ist wohl zu hoch .

    Einen Kommentar schreiben:


  • Ing-Dom
    antwortet
    Ja leider sehr beschäftigt als Bauherr

    Einen Kommentar schreiben:


  • tuxedo
    antwortet
    Was ist denn aus dem Enthusiasmus des gemeinsamen TPUART KNX Stacks für den Arduino geworden? --> https://github.com/KNX-on-Arduino

    Bin beim Prototypen der erste Daten auf dem Arduino programmieren kann (Karduino Tools) stehen geblieben (da andere Dinge mal wieder wichtiger waren).

    Von JuMi2006 und Ing-Dom (https://github.com/orgs/KNX-on-Arduino/people) hab ich quasi noch nix gehört/gelesen :-(

    Sind alle so beschäftigt?

    Um Omegacontrol ist es auch sehr still geworden.

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Hallo Chris,

    vielen Dank für Deinen Beitrag - das ist der Wahnsinn, was mittlerweile alles geht....

    Einen Kommentar schreiben:


  • ChristianM
    antwortet
    An der Stelle möchte ich mich auf gerne für diese super Beiträge bedanke. Diese haben es ermöglicht, dass ich heute mein Projekt erfolgreich zu Ende bringen zu können.
    Es ging darum die Werte meiner Lüftungsanlage Zehnder Comfoair 350 auszulesen und auf meiner SmartVisu darzustellen. An der Lüftungsanlage habe ich kabelmäßig nur KNX zur Verfügung. Darum habe ich einen Umsetzer gebaut, der die Lüftungsanlage an ihrer seriellen Schnittstelle ausliest und die Daten auf den KNX sendet.
    Etwa so:
    RS232-Port der Lüftungsanlage --> MAX232-Anpasschaltung --> Serieller Port 1 eines Arduino MEGA --> BCU 5WG1117-2AB12 am seriellen Port 2 des Arduino MEGA --> KNX
    In meinem Fall geht es nur um das Auslesen der Daten aus der Lüftungsanlage, nicht um das Steuern der Lüftungsanlage.
    Arduino Sketch ist diesem Beitrag beigefügt. Vielleicht kann das jemand brauchen.

    Gruß
    Chris

    Code:
    #include <KnxTpUart.h>
    
    // Initialisiert KNX TP-UART library auf Serial2 des Arduino Mega mit der pysikalischen Adresse 1/1/142
    KnxTpUart knx(&Serial2, 1, 1, 142);
    
    void setup() {
      // Serieller Port0 für Debug-Ausgabe (USB)
      Serial.begin(9600);
      // Serieller Port1 an Lüftungsanlage angeschlossen über MAX232-Anpassschaltung
      Serial1.begin(9600);
      // Serieller Port2 am KNX angeschlossen über Busankoppler 5WG11172AB12
      Serial2.begin(19200);
      UCSR2C = UCSR2C | B00100000; // Even Parity setzen (wird für KNX benötigt)
    
      knx.uartReset();  //TP-UART zurücksetzen
    }
    //########### Variablendeklarationen ########### 
    //Zähler für Programmschritte der State-Machine
    int progcounter = 0;  
    
    //Variablen für Ventilatorwerte
    //(Datenzyp Float passt zwar nicht so richtig, aber für float gibt es eine Methode in der TP-UART library 
    float f_ventilatorzuluftprozent= 999.0;
    float f_ventilatorabluftprozent= 999.0;
    float f_ventilatorzuluftprozent_old= 999.0;
    float f_ventilatorabluftprozent_old= 999.0;
    
    //Variablen für Bypasswerte
    //(Datenzyp Float passt zwar nicht so richtig, aber für float gibt es eine Methode in der TP-UART library 
    float f_bypassprozent = 999.0;
    float f_bypassprozent_old = 999.0;
    
    //Variablen für Temperaturwerte 
    float f_tempaussenluft = 999.0;
    float f_tempzuluft = 999.0;
    float f_tempabluft = 999.0;
    float f_tempfortluft = 999.0;
    float f_tempaussenluft_old = 999.0;
    float f_tempzuluft_old = 999.0;
    float f_tempabluft_old = 999.0;
    float f_tempfortluft_old = 999.0;
    
    //Variablen für Filterwechselwerte 
    float f_filterwechsel = 999.0;
    float f_filterwechsel_old = 999.0;
    
    //Konstanten für die Kommandobytes laut www.see-solutions.de/sonstiges/Protokollbeschreibung_ComfoAir.pdf
    const byte a_command_ventilatorstatus[] = { 0x07, 0xF0, 0x00, 0x0B, 0x00, 0xB8, 0x07, 0x0F }; //Ventilatorwerte
    const byte a_command_klappenstatus[] = { 0x07, 0xF0, 0x00, 0x0D, 0x00, 0xBA, 0x07, 0x0F }; //Bypasswerte
    const byte a_command_temperaturstatus[] = { 0x07, 0xF0, 0x00, 0x0F, 0x00, 0xBC, 0x07, 0x0F }; //Temperaturwerte
    
    //Variablen für serielle Kommunikation mit Lüftungsanlage
    byte b_received = 0xFF ;
    byte b_ack[2] = {0xFF, 0xFF} ;
    byte b_start[2] = {0xFF, 0xFF} ;
    byte b_command[2] = {0xFF, 0xFF} ;
    byte b_count_data = 0xFF ;
    byte b_data[7] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} ; //Wenn es nur sechs Elemente sind kommt es beim Datenempfang zu komischen Überlaufeffekten !?!
    byte b_checksum = 0xFF ;
    byte b_end[2] = {0xFF, 0xFF} ;
    
    //Variablen zur Erkennung, welches Kommando grade bearbeitet wird
    boolean bo_telegramm_ventilatorstatus = false;
    boolean bo_telegramm_klappenstatus = false;
    boolean bo_telegramm_temperaturstatus = false;
    
    // Zähler i für Schleifen aller Art
    byte i = 1;
    
    // KNX TP-UART library
    boolean sucess = false; //Rückgabewert der KNX TP-UART library
    long merker = 0; //Schmiermerker für Variablenumwandlung
    
    // ############# Programmsteuerung ########################
    //true: Die Daten werden in der angegebenen Zykluszeit auf den KNX geschrieben, auch wenn sich diese nicht verändern.
    //false: Die Daten werden nur dann auf den KNX gesendet, wenn diese sich zum vorherigen Wert verändern. Die Zykluszeit ist dennoch aktiv und sorgt für Verzögerung.
    boolean zyklisch_senden = false;
    long zykluszeit = 10;
    // ########################################################
    
    void loop()
    {
      if (Serial1.available())
      {
        b_received = Serial1.read();  //empfangenes Datum speichern
        switch (progcounter)
        {
          case 0:  //Startwert
            progcounter = 1;
            break;
          case 1:  //Acknowledge
            {
              //****** Acknowledge Byte1 **************
              if (b_received == 0x07)
              {
                b_ack[1] = b_received;
                Serial.println("Acknowledge Byte1 empfangen: " + String(b_ack[1], HEX));
              }
              //****** Acknowledge Byte2 **************
              else if (b_received == 0xF3)
              {
                b_ack[2] = b_received;
                Serial.println("Acknowledge Byte2 empfangen: " + String(b_ack[2], HEX));
                progcounter = 2;
                Serial.println("Acknowlegde korrekt erkannt. Weiter mit Start-Byte. --> Progcounter: " + String(progcounter));
              }
              else
              {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Erkennen von Acknowlegde! --> Progcounter: " + String(progcounter));
              }
              break;
            }
          case 2: //Start
            {
              //****** Start Byte1 **************
              if (b_received == 0x07)
              {
                b_start[1] = b_received;
                Serial.println("Start Byte1 empfangen: " + String(b_start[1], HEX));
              }
              //****** Start Byte2 **************
              else if (b_received == 0xF0)
              {
                b_start[2] = b_received;
                Serial.println("Start Byte2 empfangen: " + String(b_start[2], HEX));
                progcounter = 3;
                Serial.println("Start-Sequenz korrekt erkannt. Weiter mit Kommando-Bytes. --> Progcounter: " + String(progcounter));
              }
              else
              {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Erkennen von ´Start! --> Progcounter: " + String(progcounter));
              }
              break;
            }
          case 3: //Kommando
            {
              //****** Kommando Byte1 **************
              if (b_command[1] == 0xFF)
                {
                b_command[1] = b_received;
                Serial.println("Kommando Byte1 empfangen: " + String(b_command[1], HEX));
                }
              //****** Kommando Byte2 **************
              else if (b_command[1] != 0xFF)
                {
                b_command[2] = b_received;
                Serial.println("Kommando Byte2 empfangen: " + String(b_command[2], HEX));
                if (b_command[1] == 0x00 && b_command[2] == 0x0C)
                  {
                  bo_telegramm_ventilatorstatus = true;
                  bo_telegramm_klappenstatus = false;
                  bo_telegramm_temperaturstatus = false;
                  Serial.println("Kommando Ventilatorstatus erkannt");
                  }
                else if (b_command[1] == 0x00 && b_command[2] == 0x0E)
                  {
                  bo_telegramm_ventilatorstatus = false;
                  bo_telegramm_klappenstatus = true;
                  bo_telegramm_temperaturstatus = false;
                  Serial.println("Kommando Klappenstatus erkannt");
                  }
                else if (b_command[1] == 0x00 && b_command[2] == 0x10)
                  {
                  bo_telegramm_ventilatorstatus = false;
                  bo_telegramm_klappenstatus = false;
                  bo_telegramm_temperaturstatus = true;
                  Serial.println("Kommando Temperaturstatus erkannt");
                  }
                else
                  {
                  progcounter = 99; //Fehler ist aufgetreten
                  Serial.println("Fehler bei Erkennen von Kommando! --> Progcounter: " + String(progcounter)); 
                  }            
                progcounter = 4;
                Serial.println("Kommando-Sequenz korrekt erkannt. Weiter mit Anzahl Daten. --> Progcounter: " + String(progcounter));
                }
              else
                {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Erkennen von Kommando! --> Progcounter: " + String(progcounter));
                }
              break;
            }
          case 4: //Anzahl Daten
            {
              //****** Anzahl Daten Byte **************
              if (b_received <= 6)
              {
                b_count_data = b_received;
                Serial.println("Anzahl-Daten-Byte empfangen: " + String(b_count_data, HEX));
                progcounter = 5;
                Serial.println("Anzahl-Daten-Byte erkannt. Weiter mit Daten. --> Progcounter: " + String(progcounter));
              }
              else
              {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Erkennen von Anzahl der Daten! --> Progcounter: " + String(progcounter));
              }
              break;
            }
          case 5: //Daten
            {
              //****** Daten Byte1-6 **************
              if (b_count_data <= 6)
              {
                if (i <= b_count_data)
                {
                  b_data[i] = b_received;
                  Serial.println("Daten Byte" + String(i) + " empfangen: " + String(b_data[i], HEX));
                  i++;
                }
                else
                {
                  progcounter = 6;
                  Serial.println("Alle Daten empfangen! --> Progcounter: " + String(progcounter));
                  i = 1;
                }
              }
              else
              {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Datenempfang! --> Progcounter: " + String(progcounter));
              }
              break;
            }
          case 6: //Checksumme
            {
              //****** Checksumme **************
              for (i=1;i<=4;i++)
                {
                b_checksum = b_checksum + b_data[i];
                }
              b_checksum = b_checksum + b_command[1] + b_command[2] + b_count_data;
                if (b_checksum  = b_received)
                {
                progcounter = 7;  
                Serial.println("Checksumme korrekt. --> Progcounter: " + String(progcounter));
                } 
              else
                {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Checksummen-Empfang! --> Progcounter: " + String(progcounter));
                }
              break;
            }
          case 7: //Ende
            {
              //****** Ende Byte1 **************
              if (b_received == 0x07)
              {
                b_end[1] = b_received;
                Serial.println("Ende Byte1 empfangen: " + String(b_end[1], HEX));
              }
              //****** Ende Byte2 **************
              else if (b_received == 0x0F)
              {
                b_end[2] = b_received;
                Serial.println("Ende Byte2 empfangen: " + String(b_end[2], HEX));
                //KNX-Versand vorbereiten und durchführen
                if (bo_telegramm_ventilatorstatus) //Erkennung welche Daten aus der Lüftung ausgelesen wurden
                 {
                   //################# Ventilatorstatus Zuluft schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];
                   merker=0;
                   merker = merker | b_data[1];
                   f_ventilatorzuluftprozent = merker;
                   //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   if ((f_ventilatorzuluftprozent != f_ventilatorzuluftprozent_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_ventilatorzuluftprozent_old = f_ventilatorzuluftprozent; //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,10, f_ventilatorzuluftprozent); //Wert auf den KNX schreiben
                      Serial.println("-----> Ventilator Zuluft %: " + String(f_ventilatorzuluftprozent) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_ventilatorzuluftprozent_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird
                   }
                   //################# Ventilatorstatus Abluft schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];              
                   merker=0;
                   merker = merker | b_data[2];
                   f_ventilatorabluftprozent = merker;
                   if ((f_ventilatorabluftprozent != f_ventilatorabluftprozent_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_ventilatorabluftprozent_old = f_ventilatorabluftprozent; //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,11, f_ventilatorabluftprozent); //Wert auf den KNX schreiben
                      Serial.println("-----> Ventilator Abluft %: " + String(f_ventilatorzuluftprozent) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_ventilatorabluftprozent_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird
                   }
                 }
                 if (bo_telegramm_klappenstatus) //Erkennung welche Daten aus der Lüftung ausgelesen wurden
                 {
                   //################# Klappenstatus Bypass schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];              
                   merker=0;
                   merker = merker | b_data[1];
                   f_bypassprozent = merker;
                   if ((f_bypassprozent != f_bypassprozent_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_bypassprozent_old = f_bypassprozent;  //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,14, f_bypassprozent); //Wert auf den KNX schreiben
                      Serial.println("-----> Klappenstatus Bypass %: " + String(f_bypassprozent) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_bypassprozent_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird
                   }  
                 }
                 if (bo_telegramm_temperaturstatus) //Erkennung welche Daten aus der Lüftung ausgelesen wurden
                 {
                   //################# Teperaturstatus Aussenluft schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];
                   merker=0;
                   merker = merker | b_data[1];
                   f_tempaussenluft = (merker/2)-20;
                   if ((f_tempaussenluft != f_tempaussenluft_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_tempaussenluft_old = f_tempaussenluft; //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,18, f_tempaussenluft); //Wert auf den KNX schreiben
                      Serial.println("-----> Teperaturstatus Aussenluft %: " + String(f_tempaussenluft) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_tempaussenluft_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird                  
                   }
                   //################# Teperaturstatus Zuluft schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];
                   merker = merker | b_data[2];
                   f_tempzuluft = (merker/2)-20;
                   if ((f_tempzuluft != f_tempzuluft_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_tempzuluft_old = f_tempzuluft;  //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,19, f_tempzuluft); //Wert auf den KNX schreiben
                      Serial.println("-----> Teperaturstatus Zuluft %: " + String(f_tempzuluft) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_tempzuluft_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird
                   }
                   //################# Teperaturstatus Abluft schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];
                   merker=0;
                   merker = merker | b_data[3];
                   f_tempabluft = (merker/2)-20;
                   if ((f_tempabluft != f_tempabluft_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_tempabluft_old = f_tempabluft;  //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,20, f_tempabluft); //Wert auf den KNX schreiben
                      Serial.println("-----> Teperaturstatus Abluft %: " + String(f_tempabluft) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_tempabluft_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird
                   }
                   //################# Teperaturstatus Fortluft schreiben
                   //Die nächsten drei Schritte sind eigentlich nicht nötig um ein Byte in ein Float zu überführen.
                   //Wenn ein Wert mal aus zwei Bytes bestehen würde, kann das dann so gemacht werden: 
                   //merker = (merker << 8) | b_data[1];
                   merker=0;
                   merker = merker | b_data[4];    
                   f_tempfortluft = (merker/2)-20;
                   if ((f_tempfortluft != f_tempfortluft_old) || zyklisch_senden) //Der Wert wird nur dann auf den KNX geschrieben, wenn er sich verändert hat, oder "zyklisch_senden" aktiv ist
                   {
                      f_tempfortluft_old = f_tempfortluft;  //Altwert wegspeichern
                      sucess = knx.groupWrite2ByteFloat(6,0,21, f_tempfortluft); //Wert auf den KNX schreiben
                      Serial.println("-----> Teperaturstatus Fortluft %: " + String(f_tempfortluft) + " auf KNX gesenden. Erfolgreich: " + String(sucess));
                      if (sucess==0) f_tempfortluft_old = 999.0; //Wenn das Schreiben nicht erfolgreich war, wird hier dafür gesorgt, dass beim nächsten Zyklus wieder geschrieben wird
                   }
                 }
                Serial.println("KNX-Daten versendet!");
                clear_data(); //Unterprogramm zum Löschen aller Werte aufrufen
                Serial.println("Ende-Sequenz korrekt erkannt. Weiter mit neuem Kommando. --> Progcounter: " + String(progcounter));
              }
              else
              {
                progcounter = 99; //Fehler ist aufgetreten
                Serial.println("Fehler bei Erkennen von Ende! --> Progcounter: " + String(progcounter));
              }
              break;
            }     
          case 99: //Fehler ist aufgetreten
            {
            clear_data(); //Unterprogramm zum Löschen aller Werte aufrufen
            }
            break;          
          default:
            {
            clear_data(); //Unterprogramm zum Löschen aller Werte aufrufen
            Serial.println("Empfangenes Byte konnte nicht zugeordnet werden: " + String(b_received, HEX));
            }
        } //Switch-Case-Verteiler abschließen
    
      }  //If-Statement abschließen
      else
      
      {
        delay(zykluszeit * 1000);  //Zykluszeit warten
        if (bo_telegramm_ventilatorstatus == true) //Erkennung welche Daten aus der Lüftung ausgelesen wurden
          {
          Serial1.write(a_command_klappenstatus, sizeof(a_command_klappenstatus)); //Kommando an Lüftungsanlage senden
          Serial.println("");
          Serial.println("++++++++++ Kommando 'Klappenstatus auslesen' versendet ++++++++++");
          }
        else if (bo_telegramm_klappenstatus == true)  //Erkennung welche Daten aus der Lüftung ausgelesen wurden
          {
          Serial1.write(a_command_temperaturstatus, sizeof(a_command_temperaturstatus)); //Kommando an Lüftungsanlage senden
          Serial.println("");
          Serial.println("++++++++++ Kommando 'Temperaturstatus auslesen' versendet ++++++++++");
          }    
        else //Erkennung welche Daten aus der Lüftung ausgelesen wurden
          {
          Serial1.write(a_command_ventilatorstatus, sizeof(a_command_ventilatorstatus)); //Kommando an Lüftungsanlage senden
          Serial.println("");
          Serial.println("++++++++++ Kommando 'Ventilalatorstatus auslesen' versendet ++++++++++");
          }
        delay(100);  //Comfoair Zeit zum Antworten geben
      }
    }
    
    void clear_data()
    {
            b_received = 0xFF ;
            b_ack[1] = 0xFF;
            b_ack[2] = 0xFF;
            b_start[1] = 0xFF;
            b_start[2] = 0xFF;
            b_command[1] = 0xFF;
            b_command[2] = 0xFF;
            b_count_data = 0xFF ;
            b_data[1] = 0xFF;
            b_data[2] = 0xFF;
            b_data[3] = 0xFF;
            b_data[4] = 0xFF;
            b_data[5] = 0xFF;
            b_data[6] = 0xFF;
            b_data[7] = 0xFF;
            b_checksum = 0xFF ;
            b_end[1] = 0xFF;
            b_end[2] = 0xFF;
            i = 1;      
            progcounter = 0;    
            Serial.println("Alle Variablen zurückgesetzt");
    }

    Einen Kommentar schreiben:


  • wintermute
    antwortet
    Hallo,

    Zitat von gunnar Beitrag anzeigen
    Gibt es ein funktionierendes Arduino+RFID Setup, was die notwendige Sicherheit für die vertrauenswürdige Identifizierung der Schlüssel (keiner Kopien/Mitschnitte) bietet?
    alle mir bekannten Lösungen können maximal Mifare Classic, was dann auch der verbreitetste Standard im Arduino Umfeld aber leider alles andere als sicher ist. Zur Zeit böte sich (noch) zB die Verwendung aktueller DesFire Chips an, aber ich bezweifle, dass ein Arduino mit der Verschlüsselung klar kommen würde. Also: nein, in wirklich sicher leider nicht.

    gruesse :: Michael

    Einen Kommentar schreiben:


  • gunnar
    antwortet
    Hallo,

    Wie ist bezüglich des Themas der letzte Stand? Gibt es ein funktionierendes Arduino+RFID Setup, was die notwendige Sicherheit für die vertrauenswürdige Identifizierung der Schlüssel (keiner Kopien/Mitschnitte) bietet? Ich würde gern eine Nachricht auf dem Bus haben, wenn ein bekannter Schlüssel erkannt wurde und wenn er die Reichweite wieder verlassen hat.

    -Gunnar

    Einen Kommentar schreiben:


  • kettheik
    antwortet
    Hier mein Code:
    Code:
    /* ------------------------------------------------------------------------------- */
    /* FAN CONTROL via KNX                                                             */
    /* ------------------------------------------------------------------------------- */
    /* V1: 09/2015 kettheik - 6PWM based Fans could be regulated via KNX Telegrams     */
    /* ------------------------------------------------------------------------------- */
    /* Thanks to Mag Gyver and ThorstenGehrig from knx-user-forum                      */
    /* ------------------------------------------------------------------------------- */
    /* Used Hardware: uC: Arduino Uno R3                                               */
    /* Used Hardware: KNX: Siemens 5WG1 117-2AB12                                      */
    /* Used Hardware: Fan: ebmpapst 4412 FGMPR (PWM 50% Off - 2 Directions possible    */
    /* UsedSoftware https://bitbucket.org/thorstengehrig/arduino-tpuart-knx-user-forum */
    /* ------------------------------------------------------------------------------- */
    /* Infos:                                                                          */
    /* ------------------------------------------------------------------------------- */
    /*  Der Arduino Uno hat 3 Timer und 6 PWM Ausgänge.                                */
    /*  Der Zusammenhang zwischen Timern und PWM Kanälen ist:                          */
    /*  Pins 5 und 6: gesteuert von timer0                                             */
    /*  (ACHTUNG, dieser Timer beinflusst auch Funktionen wie "delay" und "millis")    */
    /*  Pins 9 und 10: gesteuert von timer1                                            */
    /*  Pins 11 und 3: gesteuert von timer2                                            */
    /*                                                                                 */
    /*  Beim Arduino Mega gibt es 6 Zimer und 15 PWM Ausgänge:                         */
    /*  Pins 4 und 13: gesteuert von timer0                                            */
    /*  (ACHTUNG, dieser Timer beinflusst auch Funktionen wie "delay" und "millis")    */
    /*  Pins 11 und 12: gesteuert von timer1                                           */
    /*  Pins 9 und 10: gesteuert von timer2                                            */
    /*  Pin 2, 3 und 5: gesteuert von timer 3                                          */
    /*  Pin 6, 7 und 8: gesteuert von timer 4                                          */
    /*  Pin 46, 45 und 44:: gesteuert von timer 5                                      */
    /*                                                                                 */
    /*  Nachzulesen:                                                                   */
    /*  http://playground.arduino.cc/Main/TimerPWMCheatsheet                           */
    /*                                                                                 */
    /*  Pins 5 and 6: controlled by Timer 0 in fast PWM mode (cycle length = 256)      */
    /*                                                                                 */
    /*  Setting   Divisor   Frequency                                                  */
    /*  0x01      1         62500                                                      */
    /*  0x02      8         7812.5                                                     */
    /*  0x03      64        976.5625   <--DEFAULT                                      */
    /*  0x04      256       244.140625                                                 */
    /*  0x05      1024      61.03515625                                                */
    /*                                                                                 */
    /*  TCCR0B = (TCCR0B & 0b11111000) | <setting>;                                    */
    /*                                                                                 */
    /*  Pins 9 and 10: controlled by timer 1 in phase-correct PWM mode (cycle = 510)   */
    /*                                                                                 */
    /*  Setting   Divisor   Frequency                                                  */
    /*  0x01      1         31372.55                                                   */
    /*  0x02      8         3921.16                                                    */
    /*  0x03      64        490.20   <--DEFAULT                                        */
    /*  0x04      256       122.55                                                     */
    /*  0x05      1024      30.64                                                      */
    /*                                                                                 */
    /*  TCCR1B = (TCCR1B & 0b11111000) | <setting>;                                    */
    /*                                                                                 */
    /*  Pins 11 and 3: controlled by timer 2 in phase-correct PWM mode (cycle = 510)   */
    /*                                                                                 */
    /*  Setting   Divisor   Frequency                                                  */
    /*  0x01      1         31372.55                                                   */
    /*  0x02      8         3921.16                                                    */
    /*  0x03      32        980.39                                                     */
    /*  0x04      64        490.20   <--DEFAULT                                        */
    /*  0x05      128       245.10                                                     */
    /*  0x06      256       122.55                                                     */
    /*  0x07      1024      30.64                                                      */
    /*                                                                                 */
    /*  TCCR2B = (TCCR2B & 0b11111000) | <setting>;                                    */
    /*                                                                                 */
    /*  All frequencies are in Hz and assume a 16000000 Hz system clock.               */
    /* ------------------------------------------------------------------------------- */
    #include <KnxTpUart.h>
    
    /* ------------------------------------------------------------------------------- */
    /* General Defines                                                                 */
    /* ------------------------------------------------------------------------------- */
    #define U32_MAX              4294967295 /* 2^32 */
    #define DEBUGPRINT                    2 /* 0=dont print 1= print Serial 2=useLEDs  */
    
    /* ------------------------------------------------------------------------------- */
    /* KNX Defines                                                                     */
    /* ------------------------------------------------------------------------------- */
    #define KNX_BAUDRATE              19200 /* Define Serial Baudrate to Siemens 5WG1  */
    
    #define KNX_PYSICAL_ADRESS          "1.1.52"
    
    #define KNX_SEND_ALIVE_GROUPADRESS  "0/0/1"
    
    #define KNX_LISTEN_GROUPADRESS_0    "1/2/12"
    #define KNX_LISTEN_GROUPADRESS_1    "1/2/10"
    
    /* ------------------------------------------------------------------------------- */
    /* Debugdefines                                                                    */
    /* ------------------------------------------------------------------------------- */
    #define LED_RED                       4 /* io channel */
    #define LED_YEL                       7 /* io channel */
    #define LED_GRE                       8 /* io channel */
    #define LED_WHI                      12 /* io channel */
    #define LED_YEL10                    13 /* io channel */
    #define LED_RED10                     2 /* io channel */
    #define DEBUG_LEDCNT                 10 /* Number of events */
    
    /* ------------------------------------------------------------------------------- */
    /* Zeit Defines in ms                                                              */
    /* ------------------------------------------------------------------------------- */
    #define CYCLE_TIME_MS                 (50)                          /* ------ 50ms */
    #define CYCLE_TIME_US                 ((long)CYCLE_TIME_MS*1000)
    
    #define TIMER_FAKTOR                  (1)
    #define CYCLE_TIME_MOD_US             ((long)CYCLE_TIME_US * TIMER_FAKTOR)
    
    #define DT_STARTUPTIME                (5000/CYCLE_TIME_MS)          /* ----  5secs */
    #define DT_KNX_ALIVE_SIGNAL           (60000/CYCLE_TIME_MS)         /* ---- 60secs */
    #define DT_DEBUG_ALIVE_PRINT          (1000/CYCLE_TIME_MS)          /* ----  1secs */
    
    #define DT_RUN_TIME_LONG              ((long)3600000/CYCLE_TIME_MS) /* -- one hour */
    #define DT_STOP_TIME_LONG             ((long)300000/CYCLE_TIME_MS)  /* ---- 300sec */
    
    #define DT_DIRECTION_CHANGE_LONG      ((long)600000/CYCLE_TIME_MS)  /* ---- 600sec */
    #define DT_DIRECTION_CHANGE_MED       ((long)300000/CYCLE_TIME_MS)  /* ---- 300sec */
    #define DT_DIRECTION_CHANGE_NORM      ((long)90000/CYCLE_TIME_MS)   /* ----  90sec */
    #define DT_DIRECTION_CHANGE_TEST      (12000/CYCLE_TIME_MS)         /* ----  12sec */
    #define DT_STOP_TIME                  (10000/CYCLE_TIME_MS)         /* ----  10sec */
    
    #define DT_LEV1_to_LEV2               (500/CYCLE_TIME_MS)           /* ----  500ms */
    #define DT_LEV2_to_LEV3               (100/CYCLE_TIME_MS)           /* ----  100ms */
    #define DT_LEV3_to_LEV4               (100/CYCLE_TIME_MS)           /* ----   50ms */
    #define DT_LEV4_to_LEV5               (100/CYCLE_TIME_MS)           /* ----   50ms */
    #define DT_DECREASE_LEVEL             (1000/CYCLE_TIME_MS)          /* ---- 1000ms */ 
    
    /* ------------------------------------------------------------------------------- */
    /* Functionality Defines                                                           */
    /* ------------------------------------------------------------------------------- */
    #define SPEED_LEVEL_0                 0
    #define SPEED_LEVEL_1                 1
    #define SPEED_LEVEL_2                 2
    #define SPEED_LEVEL_3                 3
    #define SPEED_LEVEL_4                 4
    #define SPEED_LEVEL_5                 5
    
    #define DIR_IN                        0
    #define DIR_OUT                       1
    
    #define FANMODE_REVERSING             0
    #define FANMODE_1st_OUT_2nd_IN        1
    #define FANMODE_1st_IN_2nd_OUT        2
    
    /* ------------------------------------------------------------------------------- */
    /* Measured Values from Scope                                                      */
    /* ------------------------------------------------------------------------------- */
    #define SPEED_OFF     127 //50%DC
    #define SPEED_OUT_1   106 //41%DC
    #define SPEED_OUT_2    80 //31%DC
    #define SPEED_OUT_3    70 //27%DC
    #define SPEED_OUT_4    52 //20%DC
    #define SPEED_OUT_5    16 //6%DC
    #define SPEED_IN_1    146 //57%DC
    #define SPEED_IN_2    170 //66%DC
    #define SPEED_IN_3    188 //73%DC
    #define SPEED_IN_4    204 //80%DC
    #define SPEED_IN_5    236 //92%DC
    
    /* ------------------------------------------------------------------------------- */
    /* Define Slots for fans                                                           */
    /* ------------------------------------------------------------------------------- */
    #define FAN1_KUECHE          9
    #define FAN2_WOZI           10
    #define FAN3_OGKINDGROSS     3
    #define FAN4_OGFLUR         11
    #define FAN5_OGKINDKLEIN     5
    #define FAN6_OGELTERN        6
    
    /* ------------------------------------------------------------------------------- */
    /* Define variables                                                                */
    /* ------------------------------------------------------------------------------- */
    unsigned long mytimestamp_last; 
    unsigned long mytimestamp_now; 
    unsigned long mytimestamp_delta;
    
    unsigned long cnt_secs;
    unsigned long cnt_freecycletime;
    
    int mode12;
    int save_mode12;
    unsigned long cnt12_dt_cycle;
    unsigned long dt12_reversing;
    unsigned long dt12_stoptime;
    
    int mode34;
    int save_mode34;
    unsigned long cnt34_dt_cycle;
    unsigned long dt34_reversing;
    unsigned long dt34_stoptime;
    
    int mode56;
    int save_mode56;
    unsigned long cnt56_dt_cycle;
    unsigned long dt56_reversing;
    unsigned long dt56_stoptime;
    
    int direction_fan1;
    int direction_fan2;
    int direction_fan3;
    int direction_fan4;
    int direction_fan5;
    int direction_fan6;
    
    int target_dutycycle_fan1;
    int target_dutycycle_fan2;
    int target_dutycycle_fan3;
    int target_dutycycle_fan4;
    int target_dutycycle_fan5;
    int target_dutycycle_fan6;
    
    int act_dutycycle_fan1;
    int act_dutycycle_fan2;
    int act_dutycycle_fan3;
    int act_dutycycle_fan4;
    int act_dutycycle_fan5;
    int act_dutycycle_fan6;
    
    int speed1;
    int speed2;
    int speed3;
    int speed4;
    int speed5;
    int speed6;
    
    int save_speed1;
    int save_speed2;
    int save_speed3;
    int save_speed4;
    int save_speed5;
    int save_speed6;
    
    boolean led_whi_state;
    boolean led_gre_state;
    boolean led_yel_state;
    boolean led_red_state;
    boolean led_yel10_state;
    boolean led_red10_state;
    boolean knx_startup_done;
    int cnt_yel10;
    int cnt_red10;
    
    /* ------------------------------------------------------------------------------- */
    /* Initialize the KNX TP-UART library on the Serial port of Arduino Uno            */
    /* with KNX physical address 1.1.52                                                */
    /* ------------------------------------------------------------------------------- */
    KnxTpUart knx(&Serial, KNX_PYSICAL_ADRESS);
    
    /* ------------------------------------------------------------------------------- */
    /* Init                                                                            */
    /* ------------------------------------------------------------------------------- */
    void setup() 
    {
      /* **** KNX **** Initialize Bus with KNX Baudrate ****************************** */
      Serial.begin(KNX_BAUDRATE);
      while (!Serial) {
        ; // wait for serial port to connect
      }    
      /* Even Parity */          
      UCSR0C = UCSR0C | B00100000;
      /* Reset Uart */
      knx.uartReset();             
      /* ListentoGAs*/
      knx.addListenGroupAddress(KNX_LISTEN_GROUPADRESS_0);
      knx.addListenGroupAddress(KNX_LISTEN_GROUPADRESS_1);
      knx.addListenGroupAddress(KNX_SEND_ALIVE_GROUPADRESS);
    
      /* **** LEDS ******************************************************************* */
      if(DEBUGPRINT==2) pinMode(LED_RED, OUTPUT);
      if(DEBUGPRINT==2) pinMode(LED_YEL, OUTPUT);
      if(DEBUGPRINT==2) pinMode(LED_GRE, OUTPUT);
      if(DEBUGPRINT==2) pinMode(LED_WHI, OUTPUT);
      if(DEBUGPRINT==2) pinMode(LED_RED10, OUTPUT);
      if(DEBUGPRINT==2) pinMode(LED_YEL10, OUTPUT);
    
      /* **** PWMs ******************************************************************* */
      /* BE AWARE:  Timer0 must be default (0x03) elsewise KNX Lib doesnt work         */
      /* **** PWMs ******************************************************************* */
      TCCR0B = (TCCR0B & 0b11111000) | 0x03; // Setzt Timer0 (Pin 5 und 6) auf 980Hz
      TCCR1B = (TCCR1B & 0b11111000) | 0x02; // Setzt Timer1 (Pin 9 und 10) auf 3900Hz
      TCCR2B = (TCCR2B & 0b11111000) | 0x02; // Setzt Timer2 (Pin 3 und 11) auf 3900Hz
    
      /* **** FANs ******************************************************************* */
      mytimestamp_now   = micros();
      mytimestamp_last  = 0;
      mytimestamp_delta = 0;  
    
      mode12         = FANMODE_REVERSING;
      mode34         = FANMODE_REVERSING;
      mode56         = FANMODE_REVERSING;
      save_mode12    = mode12;
      save_mode34    = mode34;
      save_mode56    = mode56;
    
      direction_fan1 = DIR_OUT;
      direction_fan2 = DIR_IN;
      direction_fan3 = DIR_OUT;
      direction_fan4 = DIR_IN;
      direction_fan5 = DIR_OUT;
      direction_fan6 = DIR_IN;
    
      cnt_secs        = 0;
      cnt12_dt_cycle  = 0;
      cnt34_dt_cycle  = 0;
      cnt56_dt_cycle  = 0;
    
      dt12_reversing = DT_DIRECTION_CHANGE_NORM;
      dt34_reversing = DT_DIRECTION_CHANGE_NORM;
      dt56_reversing = DT_DIRECTION_CHANGE_NORM;
      dt12_stoptime = DT_STOP_TIME;
      dt34_stoptime = DT_STOP_TIME;
      dt56_stoptime = DT_STOP_TIME;
      
      target_dutycycle_fan1 = SPEED_OFF;
      target_dutycycle_fan2 = SPEED_OFF;
      target_dutycycle_fan3 = SPEED_OFF;
      target_dutycycle_fan4 = SPEED_OFF;
      target_dutycycle_fan5 = SPEED_OFF;
      target_dutycycle_fan6 = SPEED_OFF;
      act_dutycycle_fan1 = target_dutycycle_fan1;
      act_dutycycle_fan2 = target_dutycycle_fan2;
      act_dutycycle_fan3 = target_dutycycle_fan3;
      act_dutycycle_fan4 = target_dutycycle_fan4;
      act_dutycycle_fan5 = target_dutycycle_fan5;
      act_dutycycle_fan6 = target_dutycycle_fan6;
      
      speed1 = SPEED_LEVEL_0;
      speed2 = SPEED_LEVEL_0;
      speed3 = SPEED_LEVEL_0;
      speed4 = SPEED_LEVEL_0;
      speed5 = SPEED_LEVEL_0;
      speed6 = SPEED_LEVEL_0;
      save_speed1 = speed1;
      save_speed2 = speed2;
      save_speed3 = speed3;
      save_speed4 = speed4;
      save_speed5 = speed5;
      save_speed6 = speed6;
    
      if(DEBUGPRINT==2) {
        digitalWrite(LED_WHI, LOW); 
        led_whi_state=false;
        digitalWrite(LED_GRE, LOW);
        led_gre_state=false;
        digitalWrite(LED_YEL, LOW);
        led_yel_state=false;
        digitalWrite(LED_RED, LOW);
        led_red_state=false;
        digitalWrite(LED_YEL10, LOW);
        led_yel10_state=false;
        digitalWrite(LED_RED10, LOW);
        led_red10_state=false;
        cnt_yel10=DEBUG_LEDCNT;
        cnt_red10=DEBUG_LEDCNT;    
      }
    
      knx_startup_done = false;
      cnt_freecycletime = 0;
    
      if(DEBUGPRINT==1) {
        Serial.print("--- CYCLE_TIME_MOD_US -- ");
        Serial.println(CYCLE_TIME_MOD_US);
        Serial.print("--- DT_KNX_ALIVE_SIGNAL -- ");
        Serial.println(DT_KNX_ALIVE_SIGNAL);
        Serial.print("--- DT_DIRECTION_CHANGE_LONG -- ");
        Serial.println(DT_DIRECTION_CHANGE_LONG);
        Serial.print("--- CYCLE_TIME_US -- ");
        Serial.println(CYCLE_TIME_US);
      }
    
      /* Startup with fans off */
      analogWrite(FAN1_KUECHE,   target_dutycycle_fan1);
      analogWrite(FAN2_WOZI,     target_dutycycle_fan2);   
      analogWrite(FAN3_OGKINDGROSS,    target_dutycycle_fan3);
      analogWrite(FAN4_OGFLUR,   target_dutycycle_fan4);
      analogWrite(FAN5_OGKINDKLEIN, target_dutycycle_fan5);
      analogWrite(FAN6_OGELTERN, target_dutycycle_fan6);
    }
    
    /* ------------------------------------------------------------------------------- */
    /* Main                                                                            */
    /* ------------------------------------------------------------------------------- */
    void loop() 
    {
      /* ----------------------------------------------------------------------------- */
      /* Try to work in 50ms slots                                                     */
      /* ----------------------------------------------------------------------------- */
      mytimestamp_now = micros();
          
      if ( mytimestamp_now >= mytimestamp_last ) {
        mytimestamp_delta = mytimestamp_now - mytimestamp_last;
      }
      else { /*case overflow*/
        mytimestamp_delta = ( U32_MAX - mytimestamp_last ) + mytimestamp_now;
      }
    
      if (cnt_freecycletime == 0)
      {
        if ( mytimestamp_delta < CYCLE_TIME_MOD_US ){
          cnt_freecycletime = (CYCLE_TIME_MOD_US - mytimestamp_delta);
          if ( (cnt_secs % DT_DEBUG_ALIVE_PRINT) == 0){
            if (DEBUGPRINT==1) Serial.print("--- free [us] in CyclicTask -- ");
          }
        }
        else {
          cnt_freecycletime = (mytimestamp_delta - CYCLE_TIME_MOD_US);
          if ( (cnt_secs % DT_DEBUG_ALIVE_PRINT) == 0){
            if (DEBUGPRINT==1) Serial.print("--- !!! break !!! [us] in CyclicTask -- ");
          }
        }
        if ( (cnt_secs % DT_DEBUG_ALIVE_PRINT) == 0){
          if (DEBUGPRINT==1) Serial.print( cnt_freecycletime );
          if (DEBUGPRINT==1) Serial.println(" us");
        }
      }    
    
      if(mytimestamp_delta < CYCLE_TIME_MOD_US)
      {
        return; /* do ******************** next ********************* loop */
      }
      else 
      {
        /* Save new last timestamp */
        mytimestamp_last = mytimestamp_now;
        /* Reset mytimestamp_delta to zero */
        mytimestamp_delta = 0;
        /* Reset freecycletimecounter */
        cnt_freecycletime = 0;  
      }  
    
      if ( knx_startup_done )
      { 
        /* --------------------------------------------------------------------------- */
        /* Get Input from knx or whatever                                              */
        /* --------------------------------------------------------------------------- */
    
        /* TODO */
        
        speed1 = SPEED_LEVEL_4;
        speed2 = SPEED_LEVEL_5;
        speed3 = SPEED_LEVEL_5;
        speed4 = SPEED_LEVEL_5;
        speed5 = SPEED_LEVEL_2;
        speed6 = SPEED_LEVEL_3;
      
        mode12 = FANMODE_REVERSING;
        mode34 = FANMODE_REVERSING;
        mode56 = FANMODE_1st_IN_2nd_OUT;
      
        dt12_reversing = DT_DIRECTION_CHANGE_NORM;
        dt34_reversing = DT_DIRECTION_CHANGE_NORM;
        dt56_reversing = DT_RUN_TIME_LONG;
      
        dt12_stoptime = DT_STOP_TIME;
        dt34_stoptime = DT_STOP_TIME;
        dt56_stoptime = DT_STOP_TIME_LONG;
      
        /* --------------------------------------------------------------------------- */
        /* Call the function                                                           */
        /* --------------------------------------------------------------------------- */
          
        /* Call the functions for reversing the fans */
        do_reversing( /*FanNr*/             FAN1_KUECHE,            FAN2_WOZI,
                      /*TargetSpeedLevel*/  speed1,                 speed2,
                      /*Reverse/Stoptime*/  dt12_reversing,         dt12_stoptime,
                      /*Target/LastMode*/   &mode12,                &save_mode12,                
                      /*LastSpeed*/         &save_speed1,           &save_speed2,
                      /*DirectionFan*/      &direction_fan1,        &direction_fan2,
                      /*TargetDutycycle*/   &target_dutycycle_fan1, &target_dutycycle_fan2,
                      /*CurrentDutycycle*/  &act_dutycycle_fan1,    &act_dutycycle_fan2,
                      /*Timecounter*/       &cnt12_dt_cycle  );
      
        /* Call the functions for reversing the fans */
        do_reversing( /*FanNr*/             FAN3_OGKINDGROSS,       FAN4_OGFLUR,
                      /*TargetSpeedLevel*/  speed3,                 speed4,
                      /*Reverse/Stoptime*/  dt34_reversing,         dt34_stoptime,
                      /*Target/LastMode*/   &mode34,                &save_mode34,                
                      /*LastSpeed*/         &save_speed3,           &save_speed4,
                      /*DirectionFan*/      &direction_fan3,        &direction_fan4,
                      /*TargetDutycycle*/   &target_dutycycle_fan3, &target_dutycycle_fan4,
                      /*CurrentDutycycle*/  &act_dutycycle_fan3,    &act_dutycycle_fan4,
                      /*Timecounter*/       &cnt34_dt_cycle  );
      
        /* Call the functions for reversing the fans */
        do_reversing( /*FanNr*/             FAN5_OGKINDKLEIN,       FAN6_OGELTERN,
                      /*TargetSpeedLevel*/  speed5,                 speed6,
                      /*Reverse/Stoptime*/  dt56_reversing,         dt56_stoptime,
                      /*Target/LastMode*/   &mode56,                &save_mode56,                
                      /*LastSpeed*/         &save_speed5,           &save_speed6,
                      /*DirectionFan*/      &direction_fan5,        &direction_fan6,
                      /*TargetDutycycle*/   &target_dutycycle_fan5, &target_dutycycle_fan6,
                      /*CurrentDutycycle*/  &act_dutycycle_fan5,    &act_dutycycle_fan6,
                      /*Timecounter*/       &cnt56_dt_cycle  );
      }                
      
      /* ----------------------------------------------------------------------------- */
      /* Timecounter                                                                   */
      /* ----------------------------------------------------------------------------- */
      if (cnt_secs < U32_MAX){
        cnt_secs++;
      }
      else{
        cnt_secs=0;
      }
    
      /* ----------------------------------------------------------------------------- */
      /* Startup timer                                                                 */
      /* ----------------------------------------------------------------------------- */
      if (cnt_secs >= DT_STARTUPTIME ){
        knx_startup_done = true; /* never set back, is just done in startup */ 
      }
    
      /* ----------------------------------------------------------------------------- */
      /* KNX send cyclic message  -- every DT_KNX_ALIVE_SIGNAL*10ms                    */
      /* ----------------------------------------------------------------------------- */
      if ( ( (cnt_secs % DT_KNX_ALIVE_SIGNAL) == 0) && knx_startup_done )
      {
        if (DEBUGPRINT==1) Serial.println("--- Send Alive signal to bus -- ");
        knx.groupWriteBool(KNX_SEND_ALIVE_GROUPADRESS, led_gre_state);  
      }  
    
      /* ----------------------------------------------------------------------------- */
      /* Debugprint                                                                    */
      /* ----------------------------------------------------------------------------- */
      if ( (cnt_secs % DT_DEBUG_ALIVE_PRINT) == 0){
        if (DEBUGPRINT==1) Serial.print("--- timecounter -- ");
        if (DEBUGPRINT==1) Serial.print(cnt_secs / DT_DEBUG_ALIVE_PRINT);
        if (DEBUGPRINT==1) Serial.println(" sec");
      } 
    
      if(DEBUGPRINT==2) {
        if(led_gre_state==false) digitalWrite(LED_GRE, LOW);
        if(led_gre_state==true) digitalWrite(LED_GRE, HIGH);
        if(led_whi_state==false) digitalWrite(LED_WHI, LOW);
        if(led_whi_state==true) digitalWrite(LED_WHI, HIGH);
        if(led_yel_state==false) digitalWrite(LED_YEL, LOW);
        if(led_yel_state==true) digitalWrite(LED_YEL, HIGH);
        if(led_red_state==false) digitalWrite(LED_RED, LOW);
        if(led_red_state==true) digitalWrite(LED_RED, HIGH);
        if(led_yel10_state==false) digitalWrite(LED_YEL10, LOW);
        if(led_yel10_state==true) digitalWrite(LED_YEL10, HIGH);
        if(led_red10_state==false) digitalWrite(LED_RED10, LOW);
        if(led_red10_state==true) digitalWrite(LED_RED10, HIGH);
      }
    
      /* New loop */ 
    }
    
    
    /* ------------------------------------------------------------------------------- */
    /* REVERSING                                                                       */
    /* ------------------------------------------------------------------------------- */
    void do_reversing ( int fan1, int fan2, 
                        int speed1, int speed2, 
                        unsigned long dt_reverse, unsigned long dt_stoptime,
                        int *mode, int *lastmode,
                        int *saveSpeed1, int *saveSpeed2, 
                        int *dirFan1, int *dirFan2, 
                        int *targetDC_Fan1, int *targetDC_Fan2, 
                        int *actDC_Fan1, int *actDC_Fan2, 
                        unsigned long *cnt_cycles )
    { 
      int dc_percent_fan1;
      int dc_percent_fan2;
      int first_start_after_mode_change;
    
      /* -------------------------------------------------------------- */
      /* Reset Timerfunction if mode was changed *                      */
      /* -------------------------------------------------------------- */
      if ( *mode != *lastmode ){
        *cnt_cycles = 0;
        *lastmode = *mode;
        first_start_after_mode_change = 1;
      } 
      else {
        first_start_after_mode_change = 0;
      } 
    
      /* -------------------------------------------------------------- */
      /* Start DC Stop Time                                             */
      /* -------------------------------------------------------------- */ 
      if( *cnt_cycles == 0 )
      {
        /* Always startup with off */
        if (DEBUGPRINT==1) Serial.print("--- Stop FANPIN");
        if (DEBUGPRINT==1) Serial.print(fan1);
        if (DEBUGPRINT==1) Serial.println(" --- PWM DC = 50% ---");
        if (DEBUGPRINT==1) Serial.print("--- Stop FANPIN");
        if (DEBUGPRINT==1) Serial.print(fan2);
        if (DEBUGPRINT==1) Serial.println(" --- PWM DC = 50% ---");
    
        if (DEBUGPRINT==1) Serial.print(" Runtime [sec] --- ");
        if (DEBUGPRINT==1) Serial.println((dt_reverse*CYCLE_TIME_MS)/1000);
        if (DEBUGPRINT==1) Serial.print(" Stoptime [sec] --- ");
        if (DEBUGPRINT==1) Serial.println((dt_stoptime*CYCLE_TIME_MS)/1000);
    
        *actDC_Fan1 = SPEED_OFF;
        *actDC_Fan2 = SPEED_OFF; 
        analogWrite(fan1, *actDC_Fan1);
        analogWrite(fan2, *actDC_Fan2);
    
        if ( ( *mode != FANMODE_REVERSING ) && first_start_after_mode_change)
        {
          /* Don´t wait the long timer for initial start*/
          *cnt_cycles = DT_STOP_TIME_LONG - DT_STOP_TIME;
        }   
      }
      /* -------------------------------------------------------------- */
      /* Set Direction and Startup values                               */
      /* -------------------------------------------------------------- */
      else if ( *cnt_cycles == dt_stoptime )
      {
        /* ***** Dependend on Mode change direction ******************* */
        if ( *mode == FANMODE_REVERSING )
        {
          if (      (*dirFan1 == DIR_OUT) && (*dirFan2 == DIR_IN ) ) { 
            *dirFan1 = DIR_IN;
            *dirFan2 = DIR_OUT;
          }
          else /* ( (*dirFan1 == DIR_IN ) && (*dirFan2 == DIR_OUT) )*/ {
            *dirFan1 = DIR_OUT;
            *dirFan2 = DIR_IN;
          }
        }
        else if ( *mode == FANMODE_1st_OUT_2nd_IN ) {
          *dirFan1 = DIR_OUT;
          *dirFan2 = DIR_IN;
        }
        else /* ( *mode == FANMODE_1st_IN_2nd_OUT ) */ {
          *dirFan1 = DIR_IN;
          *dirFan2 = DIR_OUT;
        }
    
        /* ***** Always startup with slowest level if not zero ******** */
        if ( *dirFan1 == DIR_IN ) {
          if (speed1 != SPEED_LEVEL_0) {
            *actDC_Fan1 = SPEED_IN_1;
          }
          if (speed2 != SPEED_LEVEL_0) {
            *actDC_Fan2 = SPEED_OUT_1;
          }
        }
        else /* *dirFan1 == DIR_OUT */ {
          if (speed1 != SPEED_LEVEL_0) {
            *actDC_Fan1 = SPEED_OUT_1;
          }
          if (speed2 != SPEED_LEVEL_0) {
            *actDC_Fan2 = SPEED_IN_1;
          }
        }
    
        /* ***** Get new target dutycylce ***************************** */
        *targetDC_Fan1 = get_dutycycle ( speed1, *dirFan1 );
        *targetDC_Fan2 = get_dutycycle ( speed2, *dirFan2 );
        dc_percent_fan1 = ((*targetDC_Fan1*100)/255);
        dc_percent_fan2 = ((*targetDC_Fan2*100)/255);
        
        /* save speed values */
        *saveSpeed1 = speed1;
        *saveSpeed2 = speed2;    
    
        /* ***** Debug output ***************************************** */
        if (DEBUGPRINT==1)
        {
          if ( *dirFan1 == DIR_IN ) 
          {         
            Serial.print("--- Start FANPIN");
            Serial.print(fan1);      
            Serial.print(" ---IN  --- TARGET PWM DC =");
            Serial.print(dc_percent_fan1);
            Serial.println("%");
            
            Serial.print("--- Start FANPIN");
            Serial.print(fan2);      
            Serial.print(" ---OUT --- TARGET PWM DC =");
            Serial.print(dc_percent_fan2);
            Serial.println("%");
          }
          else 
          {
            Serial.print("--- Start FANPIN");
            Serial.print(fan1);      
            Serial.print(" ---OUT --- TARGET PWM DC =");
            Serial.print(dc_percent_fan1);
            Serial.println("%");
            
            Serial.print("--- Start FANPIN");
            Serial.print(fan2);      
            Serial.print(" ---IN  --- TARGET PWM DC =");
            Serial.print(dc_percent_fan2);
            Serial.println("%");
          }
        }   
        
        /* ***** Write output ***************************************** */  
        analogWrite(fan1, *actDC_Fan1);
        analogWrite(fan2, *actDC_Fan2);    
      }
      /* -------------------------------------------------------------- */
      /* Do slight startup                                              */
      /* -------------------------------------------------------------- */
      else if ( (*cnt_cycles > dt_stoptime) && ( (*actDC_Fan1 != *targetDC_Fan1) || (*actDC_Fan2 != *targetDC_Fan2) ) )
      {
        int change_done=0;
        
        if ( (*dirFan1 == DIR_OUT) && (*dirFan2 == DIR_IN) )
        {
          if ( *actDC_Fan1 != *targetDC_Fan1) 
          {         
            /* FAN1: OUT: Increase speed to next level every 100ms */
            if (      ((*actDC_Fan1 <= SPEED_OUT_1) && (*actDC_Fan1 > SPEED_OUT_2 )) && (( *cnt_cycles % DT_LEV1_to_LEV2 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_OUT_2;
              change_done=1;
            }
            else if ( ((*actDC_Fan1 <= SPEED_OUT_2) && (*actDC_Fan1 > SPEED_OUT_3 )) && (( *cnt_cycles % DT_LEV2_to_LEV3 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_OUT_3;
              change_done=1;
            }
            else if ( ((*actDC_Fan1 <= SPEED_OUT_3) && (*actDC_Fan1 > SPEED_OUT_4 )) && (( *cnt_cycles % DT_LEV3_to_LEV4 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_OUT_4;
              change_done=1;
            }
            else if ( ((*actDC_Fan1 <= SPEED_OUT_4) && (*actDC_Fan1 > SPEED_OUT_5 )) && (( *cnt_cycles % DT_LEV4_to_LEV5 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_OUT_5;
              change_done=1;
            } 
            else {
              ;
            }   
          }
    
          if ( *actDC_Fan2 != *targetDC_Fan2) 
          {
            /* FAN2: IN: Increase speed to next level every 100ms */
            if (      ((*actDC_Fan2 >= SPEED_IN_1) && (*actDC_Fan2 < SPEED_IN_2 )) && (( *cnt_cycles % DT_LEV1_to_LEV2 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_IN_2;
              change_done=1;
            }
            else if ( ((*actDC_Fan2 >= SPEED_IN_2) && (*actDC_Fan2 < SPEED_IN_3 )) && (( *cnt_cycles % DT_LEV2_to_LEV3 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_IN_3;
              change_done=1;
            }
            else if ( ((*actDC_Fan2 >= SPEED_IN_3) && (*actDC_Fan2 < SPEED_IN_4 )) && (( *cnt_cycles % DT_LEV3_to_LEV4 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_IN_4;
              change_done=1;
            }
            else if ( ((*actDC_Fan2 >= SPEED_IN_4) && (*actDC_Fan2 < SPEED_IN_5 )) && (( *cnt_cycles % DT_LEV4_to_LEV5 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_IN_5;
              change_done=1;
            }
            else {
              ;
            }
          }     
        }
        else /* (*dirFan1 == DIR_IN) && (*dirFan2 == DIR_OUT) */
        {
          if ( *actDC_Fan1 != *targetDC_Fan1) 
          {
            /* FAN1: IN: Increase speed to next level every 100ms */
            if (      ((*actDC_Fan1 >= SPEED_IN_1) && (*actDC_Fan1 < SPEED_IN_2 )) && (( *cnt_cycles % DT_LEV1_to_LEV2 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_IN_2;
              change_done=1;
            }
            else if ( ((*actDC_Fan1 >= SPEED_IN_2) && (*actDC_Fan1 < SPEED_IN_3 )) && (( *cnt_cycles % DT_LEV2_to_LEV3 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_IN_3;
              change_done=1;
            }
            else if ( ((*actDC_Fan1 >= SPEED_IN_3) && (*actDC_Fan1 < SPEED_IN_4 )) && (( *cnt_cycles % DT_LEV3_to_LEV4 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_IN_4;
              change_done=1;
            }
            else if ( ((*actDC_Fan1 >= SPEED_IN_4) && (*actDC_Fan1 < SPEED_IN_5 )) && (( *cnt_cycles % DT_LEV4_to_LEV5 ) == 0 ) ) {
              *actDC_Fan1 = SPEED_IN_5;
              change_done=1;
            }
            else {
              ;
            }
          }
        
          if ( *actDC_Fan2 != *targetDC_Fan2) 
          {         
            /* FAN2: OUT: Increase speed to next level every 100ms */
            if (      ((*actDC_Fan2 <= SPEED_OUT_1) && (*actDC_Fan2 > SPEED_OUT_2 )) && (( *cnt_cycles % DT_LEV1_to_LEV2 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_OUT_2;
              change_done=1;
            }
            else if ( ((*actDC_Fan2 <= SPEED_OUT_2) && (*actDC_Fan2 > SPEED_OUT_3 )) && (( *cnt_cycles % DT_LEV2_to_LEV3 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_OUT_3;
              change_done=1;
            }
            else if ( ((*actDC_Fan2 <= SPEED_OUT_3) && (*actDC_Fan2 > SPEED_OUT_4 )) && (( *cnt_cycles % DT_LEV3_to_LEV4 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_OUT_4;
              change_done=1;
            }
            else if ( ((*actDC_Fan2 <= SPEED_OUT_4) && (*actDC_Fan2 > SPEED_OUT_5 )) && (( *cnt_cycles % DT_LEV4_to_LEV5 ) == 0 ) ) {
              *actDC_Fan2 = SPEED_OUT_5;
              change_done=1;
            }
            else {
              ;
            } 
          }           
        }
    
        if (change_done==1){
    
          dc_percent_fan1 = ((*actDC_Fan1*100)/255);
          if (DEBUGPRINT==1) Serial.print("--- Increase FANPIN");
          if (DEBUGPRINT==1) Serial.print(fan1);      
          if (DEBUGPRINT==1) Serial.print(" --- PWM DC =");
          if (DEBUGPRINT==1) Serial.print(dc_percent_fan1);
          if (DEBUGPRINT==1) Serial.println("%");
    
          dc_percent_fan2 = ((*actDC_Fan2*100)/255);
          if (DEBUGPRINT==1) Serial.print("--- Increase FANPIN");
          if (DEBUGPRINT==1) Serial.print(fan2);      
          if (DEBUGPRINT==1) Serial.print(" --- PWM DC =");
          if (DEBUGPRINT==1) Serial.print(dc_percent_fan2);
          if (DEBUGPRINT==1) Serial.println("%");
                
          analogWrite(fan1, *actDC_Fan1);
          analogWrite(fan2, *actDC_Fan2); 
        }    
    
      }  
      /* -------------------------------------------------------------- */
      /* Slightly decrease before stopping                              */
      /* -------------------------------------------------------------- */
      else if ( *cnt_cycles >= (dt_reverse - DT_DECREASE_LEVEL))
      {
        if (speed1 != SPEED_LEVEL_0)
        {
          /* Get new target dutycylce */
          *targetDC_Fan1 = get_dutycycle ( SPEED_LEVEL_1, *dirFan1 );
          *actDC_Fan1 = *targetDC_Fan1;
          dc_percent_fan1 = ((*targetDC_Fan1*100)/255);
          
          if (DEBUGPRINT==1) Serial.print("--- Decrease FANPIN");
          if (DEBUGPRINT==1) Serial.print(fan1);      
          if (DEBUGPRINT==1) Serial.print(" --- PWM DC =");
          if (DEBUGPRINT==1) Serial.print(dc_percent_fan1);
          if (DEBUGPRINT==1) Serial.println("%");
          
          analogWrite(fan1, *actDC_Fan1);
        }
        if (speed2 != SPEED_LEVEL_0)
        {
          /* Get new target dutycylce */
          *targetDC_Fan2 = get_dutycycle ( SPEED_LEVEL_1, *dirFan2 );
          *actDC_Fan2 = *targetDC_Fan2;
          dc_percent_fan2 = ((*targetDC_Fan2*100)/255);
          
          if (DEBUGPRINT==1) Serial.print("--- Decrease FANPIN");
          if (DEBUGPRINT==1) Serial.print(fan2);      
          if (DEBUGPRINT==1) Serial.print(" --- PWM DC =");
          if (DEBUGPRINT==1) Serial.print(dc_percent_fan2);
          if (DEBUGPRINT==1) Serial.println("%");
          
          analogWrite(fan1, *actDC_Fan2);
        }
      }
       /* -------------------------------------------------------------- */
      /* loop (but do change of speed if necessary)                     */
      /* -------------------------------------------------------------- */
      else if ( *cnt_cycles > dt_stoptime)
      {
        if (speed1 != *saveSpeed1)
        {
          /* Get new target dutycylce */
          *targetDC_Fan1 = get_dutycycle ( speed1, *dirFan1 );
          dc_percent_fan1 = ((*targetDC_Fan1*100)/255);
          
          /* save speed values */
          *saveSpeed1 = speed1;  
          
          if (DEBUGPRINT==1) Serial.print("--- New Target FANPIN");
          if (DEBUGPRINT==1) Serial.print(fan1);      
          if (DEBUGPRINT==1) Serial.print(" --- PWM DC =");
          if (DEBUGPRINT==1) Serial.print(dc_percent_fan1);
          if (DEBUGPRINT==1) Serial.println("%");
          
          analogWrite(fan1, *actDC_Fan1);
        }
    
        if (speed2 != *saveSpeed2)
        {
          /* Get new target dutycylce */
          *targetDC_Fan2 = get_dutycycle ( speed2, *dirFan2 );
          dc_percent_fan2 = ((*targetDC_Fan2*100)/255);
      
          /* save speed values */
          *saveSpeed2 = speed2;    
          
          if (DEBUGPRINT==1) Serial.print("--- New Target FANPIN");
          if (DEBUGPRINT==1) Serial.print(fan2);      
          if (DEBUGPRINT==1) Serial.print(" --- PWM DC =");
          if (DEBUGPRINT==1) Serial.print(dc_percent_fan2);
          if (DEBUGPRINT==1) Serial.println("%");
            
          analogWrite(fan2, *actDC_Fan2);  
        }        
      }
      else {
        /* Else... do nothing */
        ;
      }
    
      /* -------------------------------------------------------------- */
      /* update timer                                                   */
      /* -------------------------------------------------------------- */
      if ( *cnt_cycles >= dt_reverse )
      {
        *cnt_cycles = 0;
      }
      else 
      {
        *cnt_cycles = *cnt_cycles + 1;
      }
    }
    
    /* ------------------------------------------------------------------------------- */
    /* GET FAN DUTYCYLCES                                                              */
    /* ------------------------------------------------------------------------------- */
    int get_dutycycle ( int speed, int direction )
    {
      int ret_dc;
      
      if (speed == SPEED_LEVEL_0) 
      {
        ret_dc = SPEED_OFF;
      }
      else if ( ( direction == DIR_IN ) && speed == SPEED_LEVEL_1 )
      {
        ret_dc = SPEED_IN_1;
      }
      else if ( ( direction == DIR_IN ) && speed == SPEED_LEVEL_2 )
      {
        ret_dc = SPEED_IN_2;
      }
      else if ( ( direction == DIR_IN ) && speed == SPEED_LEVEL_3 )
      {
        ret_dc = SPEED_IN_3;
      }
      else if ( ( direction == DIR_IN ) && speed == SPEED_LEVEL_4 )
      {
        ret_dc = SPEED_IN_4;
      }
      else if ( ( direction == DIR_IN ) && speed == SPEED_LEVEL_5 )
      {
        ret_dc = SPEED_IN_5;
      }
      else if ( ( direction == DIR_OUT ) && speed == SPEED_LEVEL_1 )
      {
        ret_dc = SPEED_OUT_1;
      }
      else if ( ( direction == DIR_OUT ) && speed == SPEED_LEVEL_2 )
      {
        ret_dc = SPEED_OUT_2;
      }
      else if ( ( direction == DIR_OUT ) && speed == SPEED_LEVEL_3 )
      {
        ret_dc = SPEED_OUT_3;
      }
      else if ( ( direction == DIR_OUT ) && speed == SPEED_LEVEL_4 )
      {
        ret_dc = SPEED_OUT_4;
      }
      else if ( ( direction == DIR_OUT ) && speed == SPEED_LEVEL_5 )
      {
        ret_dc = SPEED_OUT_5;
      }
      else
      {
        ; /* should never been reached */
        ret_dc = SPEED_OFF;  
      }
    
      return ret_dc;
    }
    
    /* ------------------------------------------------------------------------------- */
    /* KNX RECEIVE MESSAGES                                                            */
    /* ------------------------------------------------------------------------------- */
    void serialEvent() 
    {
      if ( knx_startup_done ) 
      {
        //Get Serial Event
        KnxTpUartSerialEventType eType = knx.serialEvent();
        
        //Check Serial Event
        if (eType == KNX_TELEGRAM) 
        {
          KnxTelegram* telegram = knx.getReceivedTelegram();
    
          // Telegramauswertung auf knx (immer notwendig fur empfangen)
          String target = 
            String(0 + telegram->getTargetMainGroup())   + "/" +                
            String(0 + telegram->getTargetMiddleGroup()) + "/" +              
            String(0 + telegram->getTargetSubGroup());
    
          // Auswertung der Gruppenadresse des empfangenen Telegrames und Zwischenspeicherung in Variable target
          if (telegram->getCommand() == KNX_COMMAND_WRITE) 
          {
            // Auswertung empfangenes KNX Telegrames mit Schreibbefehl (Flag)
            if (target == KNX_LISTEN_GROUPADRESS_0) 
            {
              // Auswertung empfangenes KNX Telegrames mit passender Gruppenadresse
              led_gre_state = telegram->getBool();
              //led_gre_state = !led_gre_state;
            }
          }
    
          // oder für die Auswertung eines empfangene KNX Telegrames mit Lesebefehl (Flag)
          if (telegram->getCommand() == KNX_COMMAND_READ) 
          {
            // Auswertung empfangenes KNX Telegrames mit Lesebefehl (Flag)
            if (target == KNX_SEND_ALIVE_GROUPADRESS) 
            {
              // Auswertung empfangenes KNX Telegrames mit passender Gruppenadresse
              knx.groupAnswerBool(KNX_SEND_ALIVE_GROUPADRESS, led_gre_state);
            }
          } 
        } 
        else if ( eType == IRRELEVANT_KNX_TELEGRAM )
        {
          led_whi_state = !led_whi_state; 
        }
        else if ( eType == TPUART_RESET_INDICATION )
        {
          led_yel_state = !led_yel_state;   
          cnt_yel10--;
          if ( cnt_yel10 == 0 )
          {
            led_yel10_state = !led_yel10_state;
            cnt_yel10 = DEBUG_LEDCNT;
          }      
        }
        else if ( eType == UNKNOWN )
        {
          led_red_state = !led_red_state;
          cnt_red10--;
          if ( cnt_red10 <= 0 )
          {
            led_red10_state = !led_red10_state;
            cnt_red10 = DEBUG_LEDCNT;
          }   
        }
        else
        {
          ;
        }
      }
    }

    Einen Kommentar schreiben:

Lädt...
X