KNX in Eigenregie mit dem Arduino

Mit ** gekennzeichnete Links auf dieser Seite sind Affiliatelinks.

Jetzt gibt es für KNX tausende von fertigen Komponenten, welche man einfach kaufen und hinzufügen kann. Wie genau das geht und wie diese mit der ETS verknüpft werden, habe ich bereits in einer mehrteiligen Reihe gezeigt. Leider sind einige Komponenten für KNX extrem teuer, obwohl der Leistungsumfang gar nicht so super mächtig ist. Um mir mal ein Beispiel rauszusuchen, habe ich einen CO2-Sensor gewählt. Von MDT liegt so eine Lösung bei über 180 Euro, Gira ruft sogar über 220 Euro aktuell dafür auf. Das sind natürlich extreme Preise. Und da habe ich mich gefragt (wie schon viele vor mir auch): Geht das nicht in Eigenregie ein wenig günstiger? Und genau da kommt der Arudino ins Spiel.

Die kleinen Mikrocontroller sind perfekt geeignet, um die verschiedensten Sensoren und Aktoren anschließen zu können. Für die meisten Komponenten gibt es fertige Libraries (Bibliotheken), sodass man diese mit wenigen Zeilen Code bereits nutzen kann. I2C, SPI, CAN und andere Systeme können ebenfalls angesprochen werden. Also müsste man doch auch eine Schnittstelle zu KNX schaffen können, oder? Ja! Allerdings nicht einfach so. Wir brauchen noch ein Gerät, welches die Vermittlung zum KNX-Bus für uns übernimmt. Dafür nehmen wir einen Buskoppler von Siemens - soweit ich weiß, muss auch genau dieses Modell sein. Und damit haben wir auch schon alles zusammen, was wir für die ersten eigenen KNX-Komponenten brauchen.

Das Projekt ist nur eine Demo - das Projekt kann Fehler enthalten und ist kein fertiges Produkt

Video

Arduino-Kurs

Produkte

Busankoppler

Der Busankoppler ** hat insgesamt 10 Pins (2x5), von welchen insgesamt 7 belegt sind. Die genaue Belegung habe ich hier für Dich aufbereitet:

KNX-Busankoppler Pinout

Bitte nicht wundern, dass ich die Pins anders nummeriert habe als in den offiziellen Dokumenten von Siemens. Das war nötig, damit sich diese mit den Pin-Nummern in KiCad auf meinen Platinen decken.

Code und Schaltpläne

Teil 1

KNX-Busankoppler am Arduino

Als erstes muss die folgende Library eingebunden werden:

Erster Test: Sende alle 5 Sekunden auf “Ein” auf die Gruppenadresse 31/1/1.

#include <Arduino.h>
#include <KnxTpUart.h>

KnxTpUart knx(&Serial1, "1.1.25");

void setup() {
  Serial1.begin(19200, SERIAL_8E1);
  knx.uartReset();
}

void loop() {
  bool success = knx.groupWriteBool("31/1/1", true);
  delay(5000);
}

Teil 2

KNX-Busankoppler mit CO2-Sensor am Arduino

Für den zweiten Test brauchen wir die MHZ-19 Library. Hier habe ich den KNX-Teil noch einmal auskommentiert, damit wir uns erstmal auf das Auslesen der Werte vom Sensor konzentrieren können. Sobald beides funktioniert wird die Verknüpfung von Sensor und KNX im Code hergestellt.

Dafür muss zusätzlich noch diese Library eingebunden werden

#include <Arduino.h>
#include <KnxTpUart.h>
#include <MHZ19.h>

//KnxTpUart knx(&Serial1, "1.1.25");
MHZ19 mhz19;

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

//  Serial1.begin(19200, SERIAL_8E1);
//  knx.uartReset();

  mhz19.begin(8, 9);
  mhz19.setAutoCalibration(false);
}

void loop() {
  int co2ppm = mhz19.getPPM(MHZ19_POTOCOL::UART);
  int temp = mhz19.getTemperature();

  Serial.print("co2: "); Serial.println(co2ppm);
  Serial.print("temp: "); Serial.println(temp);

  delay(5000);
}

Teil 3

Jetzt muss das Ganze nur noch miteinander verknüpft werden. Kurz vor weg: So klappt es nicht am KNX-Ankoppler. Über USB läuft alles wunderbar, aber das wars. Warum? Der Sensor zieht zu viel Strom. Teilweise über 100mA an 5V. Laut diversen Angaben im Netz dürfen wir aber nur maximal 50mA über den 5V-Pin ziehen. Nicht gut. Wenn man sich nun ausrechnet, wie groß ein Kondensator sein müsste, um diesen Strom bei der Spannung kurzzeitig bereitstellen zu können, ist das praktisch unmöglich zu erreichen. Also bauen wir die Schaltung auf den 20V-Pin um.

#include <Arduino.h>
#include <KnxTpUart.h>
#include <MHZ19.h>

KnxTpUart knx(&Serial1, "1.1.25");
MHZ19 mhz19;

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

  Serial1.begin(19200, SERIAL_8E1);
  knx.uartReset();

  mhz19.begin(8, 9);
  mhz19.setAutoCalibration(false);
}

void loop() {
  int co2ppm = mhz19.getPPM(MHZ19_POTOCOL::UART);
  knx.groupWrite2ByteInt("31/1/2", co2ppm);

  //int temp = mhz19.getTemperature();

  //Serial.print("co2: "); Serial.println(co2ppm);
  //Serial.print("temp: "); Serial.println(temp);

  delay(10000);
}

Damit es auch am Busankoppler funktioniert, muss das Ganze wie folgt umgebaut werden:

KNX-Busankoppler mit CO2-Sensor am Arduino

Ergebnis

Das Projekt ist nur eine Demo - das Projekt kann Fehler enthalten und ist kein fertiges Produkt

Das Ganze wurde dann auf eine eigene Platine mit ein paar mehr Funktionen übertragen (Button, 3 LEDs, …). Die restlichen Komponenten wurden genau so übernommen wie bereits im vorigen Schritt gezeigt. Danach wurder der Code natürlich noch so angepasst, dass die verschiedenen LEDs und der Button auch nutzbar werden.

Die Platine habe ich natürlich auf GitHub veröffentlicht (Gerber-Datei direkt unter den Releases).

Da auf der Platine neben dem CO2-Sensor noch drei LEDs und ein Taster platz gefunden haben, wurden diese in den Code natürlich ebenfalls integriert. Dieser Taster muss noch entprellt werden - dafür nutze ich gerne die Bounce2-Lib. Alternativ kann man den Weg natürlich auch “zu Fuß” gehen. Genau wie bei den anderen Bibliotheken muss diese auch im Lib-Verzeichnis des Projektes abgelegt werden.

#include <Arduino.h>
#include <KnxTpUart.h>
#include <MHZ19.h>
#include <Bounce2.h>

#define PHYSICAL_ADDRESS "1.1.25"

#define CO2_REFRESH_INTERVAL 10000
#define CO2_PPM_GROUP_ADDRESS "10/1/2"

#define LED1_GROUP_ADDRESS "10/1/11"
#define LED2_GROUP_ADDRESS "10/1/12"
#define LED3_GROUP_ADDRESS "10/1/13"

#define BUTTON_GROUP_ADDRESS "10/1/3"

#define LED1 10 // Green
#define LED2 16 // Yellow
#define LED3 14 // Red

#define BUTTON1 15 // Test Button and Terminal Block

Bounce debouncer = Bounce();
KnxTpUart knx(&Serial1, PHYSICAL_ADDRESS);
MHZ19 mhz19;

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

  // LED config
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  digitalWrite(LED1, LOW);
  digitalWrite(LED2, LOW);
  digitalWrite(LED3, LOW);

  // Button config
  pinMode(BUTTON1, INPUT_PULLUP);
  debouncer.attach(BUTTON1, INPUT_PULLUP);
  debouncer.interval(25);

  // KNX config
  Serial1.begin(19200, SERIAL_8E1);
  knx.uartReset();
  knx.addListenGroupAddress(CO2_PPM_GROUP_ADDRESS);
  knx.addListenGroupAddress(LED1_GROUP_ADDRESS);
  knx.addListenGroupAddress(LED2_GROUP_ADDRESS);
  knx.addListenGroupAddress(LED3_GROUP_ADDRESS);

  // CO2 sensor config
  mhz19.begin(8, 9);
  mhz19.setAutoCalibration(false);
}

void maintainCo2Sensor() {
  static unsigned long lastRefreshTime = 0;

  if (millis() - lastRefreshTime >= CO2_REFRESH_INTERVAL) {
    lastRefreshTime += CO2_REFRESH_INTERVAL;
    knx.groupWrite2ByteFloat(CO2_PPM_GROUP_ADDRESS, getCo2SensorPpm());
  }
}

float getCo2SensorPpm() {
  int co2ppm = mhz19.getPPM(MHZ19_POTOCOL::UART);
  Serial.println(co2ppm);
  return float(co2ppm);
}

void maintainKnxSerial() {
  if (Serial1.available() > 0) {
    KnxTpUartSerialEventType eType = knx.serialEvent();
    if (eType == KNX_TELEGRAM) {
      KnxTelegram* telegram = knx.getReceivedTelegram();

      String target =
        String(0 + telegram->getTargetMainGroup()) + "/" +
        String(0 + telegram->getTargetMiddleGroup()) + "/" +
        String(0 + telegram->getTargetSubGroup());

      if (telegram->getCommand() == KNX_COMMAND_READ) {
        // Answer to Read
        if (target == CO2_PPM_GROUP_ADDRESS) {
          knx.groupAnswer2ByteFloat(CO2_PPM_GROUP_ADDRESS, getCo2SensorPpm());
        }
      } else if (telegram->getCommand() == KNX_COMMAND_WRITE) {
        // Write commands
        if (target == LED1_GROUP_ADDRESS) {
          digitalWrite(LED1, telegram->getBool() ? HIGH : LOW);
        } else if (target == LED2_GROUP_ADDRESS) {
          digitalWrite(LED2, telegram->getBool() ? HIGH : LOW);
        } else if (target == LED3_GROUP_ADDRESS) {
          digitalWrite(LED3, telegram->getBool() ? HIGH : LOW);
        }
      }
    }
  }
}

void loop() {
  maintainCo2Sensor();
  maintainKnxSerial();

  // Button Event
  debouncer.update();
  if (debouncer.fell()) {
    knx.groupWriteBool(BUTTON_GROUP_ADDRESS, true);
  }
}


Newsletter

Trage Dich jetzt in den Newsletter ein und genieße dadurch viele exklusive Vorteile:

  • 5€-Gutschein für den Online-Shop
  • Zugang zu exklusiven Inhalten
  • Angebote für Produkte
  • Immer auf dem Laufenden

* Durch Angabe meiner E-Mail-Adresse erkläre ich mich damit einverstanden, dass mir regelmäßig Informationen und Produktempfehlungen aus dem Fachgebiet Smart Home zugesendet werden. Mit dem Eintrag akzeptieren Sie unsere Datenschutzbestimmungen. Meine Einwilligung kann ich jederzeit widerrufen.

Auf YouTube und hier im Blog gibt es bereits unzählige kostenlose Videos, Informationen und Tutorials. Wenn Dir das noch nicht reicht, ist ein Training genau das richtige für Dich! Die folgenden Trainings haben den Vorteil, dass immer von Anfang an gestartet wird und Du ohne Vorwissen teilnehmen kannst.