Ankündigung

Einklappen
Keine Ankündigung bisher.

ARDUINO am KNX

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

    Hallo kettheik,

    ich habe ein paar Probleme gefunden.

    Die KNX_BAUDRATE sollte 19200 betragen.
    Die void serialEvent() werte alles mögliche aus, aber nicht das was du machen willst.

    So hier mal das "void serialEvent()" welches ich auch benütze:

    Code:
    void serialEvent() {                                                                  
      KnxTpUartSerialEventType eType = knx.serialEvent();                                
      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
    // Die Zeilen in deinem Code bezüglich der Auswertung der Gruppenadressen gehen auch,
    // aber man muss eine Zahl in der Auswertung der Gruppenadresse eingeben,
    // von diesem Schema bin ich abgekommen, weil dies keine Mensch lesen/verstehen kann
                    
        if (telegram->getCommand() == KNX_COMMAND_WRITE) {
                                  
    // Auswertung empfangenes KNX Telegrames mit Schreibbefehl (Flag)
    // ***
          if (target == "3/2/7") {
                                                          
    // Auswertung empfangenes KNX Telegrames mit passender Gruppenadresse
    
            led_red_9_state = telegram->getBool();
                                                
    // Übernahme des Inhaltes des KNX Telegrames in die Variable led_red_9_state
    
          }
    // ***
    // Der Abschnitt zwischen *** und *** wird pro benötigter Gruppenadresse notwendig
        }
    
    // 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 == "3/2/7") {
                                                          
    // Auswertung empfangenes KNX Telegrames mit passender Gruppenadresse
          
            knx.groupAnswerBool("3/2/7", led_red_9_state);
                                                
    // Senden des Inhaltes der Variable led_red_9_state auf das angegebene KNX Telegrames
    
          }
    // ***
    // Der Abschnitt zwischen *** und *** wird pro benötigter Gruppenadresse notwendig
        }
      }
    }
    Zum Programmieren des Arduino musst du natürlich den TP-UART wieder entfernen (RxD und TxD),
    die Brücke am (ICSP1 Pin 5 mit ICSP1 Pin 6) muss ebenfalls entfernt werden und danach
    den USB-Stecker ausstecken und wieder einstecken (Zwischen dem Ein- und Ausstecken ein bisschen Zeit vergehen lassen).

    Deinen Code im "void loop ()" entsprechend anpassen, der kann so auch nicht funktionieren und achte darauf das du in
    "void serialEvent()" nur das aller nötigste machst. Die Ansteuerungen der Ausgänge bitte in die "void loop ()" verlagern.

    Wenn du selber Telegramme mit Lesebefehlen an den KNX verschicken möchtest, dann muss man die Libary entsprechend anpassen.



    Mit freundlichen Grüßen

    Mag Gyver
    Zuletzt geändert von Mag Gyver; 13.09.2015, 11:28.

    Kommentar


      Fehlermeldung beim Hochladen
      Zuletzt geändert von Mag Gyver; 12.09.2015, 06:16.

      Kommentar


        Fehlermeldung beim Hochladen
        Zuletzt geändert von Mag Gyver; 12.09.2015, 06:16.

        Kommentar


          Hallo Mag Gyver,

          vielen Dank..., mit 19200 komme ich jetzt ein wenig weiter...
          Komisch ich dachte der KNX Bus läuft auf 9600 ???

          Zumindest komme ich nun in alle Zweige rein...
          Mir ist schon klar, dass ich aktuell da noch nichts wirklich auswerte... das dürfte aber ja kein Problem sein.

          Mein Problem ist vielmehr, dass ich eben nicht nur in die Zweige
          KNX_TELEGRAM und IRRELEVANT_KNX_TELEGRAM reinlaufe,

          sondern eben auch in die Zweige UNKNOWN (was mich ja noch nicht mal stört, obwohl ich da am häufigsten reinlaufe (ca. 20mal in der Minute)
          und vor allem auch den Zweig TPUART_RESET_INDICATION (... ca. 3mal in der Minute)

          Und wenn ich das richtig deute, bedeutet dies, dass der TPUART resets macht...
          Ich möchte halt keinen Busteilnehmer schaffen, der sich irgendwie ständig resetet.

          Auch erfasse ich definitiv nicht immer das entsprechende Telegramm auf das ich hören möchte...
          Also das ist schon ziemlich "suboptimal"...

          Hast du noch ne Idee, oder andersrum gefragt, bekommst du auch diese TPUART Resets oder UNKNOWN Telegramme?

          Code:
            
          void serialEvent()
          {    
          if ( knx_startup_done )    
          {    
          //Get Serial Event    
          [B]KnxTpUartSerialEventType eType = knx.serialEvent();[/B]
          //Check Serial Event    
          if (eType == [COLOR=#006400][B]KNX_TELEGRAM[/B][/COLOR])      
          {        
          if(DEBUGPRINT==2)
          {          
          if(led_gre_state==false) digitalWrite(LED_GRE, HIGH);
          if(led_gre_state==true) digitalWrite(LED_GRE, LOW);
          led_gre_state = !led_gre_state;
          }
          }
          else if ( eType == [COLOR=#808080][B]IRRELEVANT_KNX_TELEGRAM [/B][/COLOR])
          {      
          if(DEBUGPRINT==2)
          {          
          if(led_whi_state==false) digitalWrite(LED_WHI, HIGH);
          if(led_whi_state==true) digitalWrite(LED_WHI, LOW);
          led_whi_state = !led_whi_state;        
          }    
          }    
          else if ( eType == [COLOR=#FF8C00][B]TPUART_RESET_INDICATION [/B][/COLOR])
          {      
          if(DEBUGPRINT==2)
          {          
          if(led_yel_state==false) digitalWrite(LED_YEL, HIGH);
          if(led_yel_state==true) digitalWrite(LED_YEL, LOW);
          led_yel_state = !led_yel_state;        
          }    
          }    
          else if ( eType == [COLOR=#FF0000][B]UNKNOWN [/B][/COLOR])    
          {      
          if(DEBUGPRINT==2)
          {
          if(led_red_state==false) digitalWrite(LED_RED, HIGH);          
          if(led_red_state==true) digitalWrite(LED_RED, LOW);          
          led_red_state = !led_red_state;      
          }    
          }    
          else    
          {      
          ;    
          }  
          }
          }
          Zuletzt geändert von kettheik; 17.09.2015, 23:47.

          Kommentar


            Hallo kettheik,

            kein Problem.

            Ja, bekomme auch ab und zu UNKNOWN-Telegrame (im Monat ca. 2-3 Stück).
            Nein, ich bekomme nur bei Störungen auf dem KNX-Bus TPUART_RESET_INDICATION-Telegrame.


            Der TP-UART im 5WG1 117-2AB12 hat eine KNX-Seite (9600 Baud) und eine serielle Schnittstellen-Seite (19200 Baud). An dieser Schnittstellenseite hängst du mit deinem Mikrocontroller (Arduino Uno) dran.

            Zu dem Zweig UNKNOWN oder dem Zweig TPUART_RESET_INDICATION gibt es auch noch jede Menge andere Antworten.
            Wenn du mit deinem Code, den TP-UART unbeabsichtigt falsch ansprichst oder zwischendurch irgendwelche Ausgaben auf der Schnittstelle machst (keine TP-UART-Befehle) kommt es zu solche Problemen. Wenn der Mikrocontroller ein Arduino Uno ist, geht nur die Kommunikation mit dem TP-UART über die serielle Schnittstelle. Alle anderen Befehle für die serielle Schnittstelle dürfen nicht verwendet werden. Desgleichen tritt auch auf wenn der Empfangspuffer der seriellen Schnittstelle des Mikrocontroller überläuft. Die UNKNOWN-Telegrame sind auch KNX-Telegrame, aber diese werden durch die Library nicht ausgewertet bzw. behandelt.

            Woher bezieht dein Arduino Uno seine Spannung ?

            Grundsätzliches im Code:

            In "void setup()" : Alle Einstellungen treffen und TP-UART initialisieren (hilfreich ist nur hier das kontrollierte Einsetzen der "delay()" Funktion)
            Code:
             knx.addListenGroupAddress("9/2/0");
             delay(1000);
            }
            // Ende void setup
            In "void loop()" : Dein Programm -> Hier kommen zum Beispiel deine Anweisungen DEBUGPRINT rein und das Setzen bzw. Rücksetzen von Mikrocontrollerpins

            In "void serialEvent()" : Die Abfragen der notwendigen bzw. der notwendigsten KNX-Telegramm
            (je mehr Zeit der Mikrocontroller für die Abarbeitung dieser Funktion benötigt, desto wahrscheinlicher eines Empfangspufferüberlauf und damit verbundenen Problemme)


            Der Zweig IRRELEVANT_KNX-Telegrame hat welche Sinn?

            Am besten du machst dir eine Skizze, was dein Code alles können soll. Danach erarbeitest du eine Ablaufskizze und anschließend daran deinen Code.


            Mit freundlichen Grüßen

            Mag Gyver
            Zuletzt geändert von Mag Gyver; 18.09.2015, 03:17.

            Kommentar


              Hallo Mag Gyver,
              ich glaube ich habe einen entscheidenden Fehler gefunden...!
              Nachdem ich nochmal deinen Post verinnerlicht habe,
              habe ich mir nochmal meine Timer angeschaut.
              Da ich 6 verschiedene Lüfter per PWM ansteuern möchte und ich dachte das die Standard PWM von 1KhZ für Timer0 nicht reicht
              (was sie nach Tests aber doch tut),
              habe ich die höher gesetzt. Für sämtliche Timings innerhalb meines Codes habe ich das auch berücksichtigt.

              Woran ich nicht gedacht habe ist, dass die KNX Library anscheinend auch Befehle wie millis/micros nutzt...

              Ich habe das jetzt mal wieder auf 1Khz zurückgestellt und siehe da,
              seit 1ner Stunde kein einziges Reset TPUART, ... selten bekomme ich zwar noch UNKNOWN (ca. 2-3mal in 10minuten?) ...

              Und das tollste überhaupt,
              nun reagiert er, denke ich, auch auf jede KNX-Botschaft... JUHUUU, jetzt warens doch einige mehr Stunden, aber mein Prototypenaufbau steht jetzt...
              Hier mal mein ganzer Code... ist sicherlich noch optimierungswürdig, aber erstmal läuft er...

              Ich poste gleich nochmal den kompletten Code, falls jemand interesse hat..

              Viele Grüße
              Heiko


              Kommentar


                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
                    {
                      ;
                    }
                  }
                }

                Kommentar


                  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
                  Gunnar Wagenknecht
                  http://gunnar.ausapolda.de/

                  Kommentar


                    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

                    Kommentar


                      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");
                      }

                      Kommentar


                        Hallo Chris,

                        vielen Dank für Deinen Beitrag - das ist der Wahnsinn, was mittlerweile alles geht....
                        Viele Grüße,
                        Stefan

                        DIY-Bastelprojekte: || >> Smelly One << || >> BURLI << ||

                        Kommentar


                          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.

                          Kommentar


                            Ja leider sehr beschäftigt als Bauherr
                            OpenKNX www.openknx.de | NanoBCU und OpenKNX-HW verfügbar

                            Kommentar


                              Dito hier ... und bis ich die erste Änderung von Dir verfolgen kann hast Du schon 3 weitere gebracht -> Meine Latenz ist wohl zu hoch .
                              Umgezogen? Ja! ... Fertig? Nein!
                              Baustelle 2.0 !

                              Kommentar


                                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.

                                Kommentar

                                Lädt...
                                X