Note that there is a fair bit of breadboard wiring involved, with the usual reliability problems. If you would rather experiment with a ready-to-use board that integrates everything required (KNX interface, digital isolator, raspberry connector, and whatever sensor you might need), check out our automated design and prototyping service.
1/ Interfacing the bus coupling unit with the Raspberry Pi
In this article, we will be using the same network we previously set up except we won’t need the USB interface anymore:
- A power supply : KNX-20E-640
- A push button with built-in LED: 5WG1115-3AB21
- An Input/Output interface: 5WG1220-2AB21
We also need to add devices to connect to the Raspberry Pi:
- A bus coupling unit for UART: 5WG1117-2AB12, which converts the KNX telegrams into serial data.
- A digital isolator – unfortunately we couldn’t find any of these off-the-shelf. But if you have a soldering iron you can make your own, for instance with an ADUM3211ARZ soldered to a breakout board.
Finally, we need the host microcontroller: the Raspberry Pi. We used the Raspberry Pi 2 model B in our test.
The bus coupling unit will be connected to the KNX network and will be our entry point. Its pinouts looks like this:
See the module datasheet for more information.
We will also need a digital isolator between the bus coupling unit and the UART adapter, because they are powered by two unrelated sources:
- the KNX network
- the mains to which the Raspberry Pi is connected
This means that the two devices do not share the same ground, so we can’t connect them directly to each other. We have to use a digital isolator to get the signals across, without a single electron going through. This component will also adapt the signal levels since the serial output of the coupling unit is 5V whereas the Raspberry Pi’s pins only support 3.3V. Note that a level shifter would not work, as it would not keep the grounds isolated from each other.
The bus coupling unit will be connected to the digital isolator through pins number 1, 2, 4 and 5 (see image above) while the Raspberry Pi will be connected to it by pins +3V3, GND, TXD0 and RXD0:
Here is what the wiring looks like for these devices:
The wiring for the entire KNX system looks like this :
First of all, we will need to configure the Raspberry Pi:
- make sure that python is installed (cf. paragraph 2 and 3 of the cheat sheet)
- have access to a remote terminal: either directly or via SSH (cf. paragraph 1 of the cheat sheet). In this article, we will be using a SSH connection
- we must make sure the UART interface is also enabled at the software level. Paragraph 2 of this article explains how to do so
Then we need a way to interact with the devices in the KNX network. We developed a module for Python allowing us to communicate with the KNX network through the UART connection. It is an adaptation of the KnxDevice library for Arduino and is available on GitHub. It requires the monotonic module to time events.
Download and transfer it on your Raspberry Pi or clone the repository by entering the following command in a terminal window:
git clone https://github.com/ThingType/KNX_Raspberry_Pi_library
Move to the created directory. You might need to modify the example script depending on the configuration of your KNX system.
First, we need to define the Communication Objects attached to the KNX bus. In our case, we have a push button and output interface so we need to declare two objects in the list named Knx._comObjectsList.
For every object we are use, there are 3 things to define (the constructor takes 3 parameters):
- The group address: this is the same we chose in our ETS project when we set up the KNX network. If you followed the previously linked tutorial, it will be 0.0.1. Check it value in the “group addresses” panel.
For the first parameter, we need to write KnxDevice.G_ADDR(<GROUP_ADDRESS>). Replace <GROUP_ADDRESS> by the address with each figure separated by a comma. For example, in our case, it would be KnxDevice.G_ADDR(0, 0, 1)
- The data type used by the device: we can find this information in the ETS program by clicking on an object in the “Group Adresses” panel. In our case, it is a “switch” data type.
For the second parameter, we need to write the data type value, which can be found in KnxDPT.py under KnxDPT_ID comment block. Find the value matching your data Type. For instance, a switch means we have to write “0”.
- Finally, the “flags” configuration: in ETS “Group Addresses” panel, we can see the flags associated to each Object; C (communication), R (read), W (write), T (transmit) and U (update).
For the push button, the active flags are C, W, T and U. We need to calculate an 8 bit value according to the following rule:
// INDICATOR field : B7 B6 B5 B4 B3 B2 B1 B0 // xx xx C R W T U I #define KNX_COM_OBJ_C_INDICATOR 0x20 // Communication (C) #define KNX_COM_OBJ_R_INDICATOR 0x10 // Read (R) #define KNX_COM_OBJ_W_INDICATOR 0x08 // Write (W) #define KNX_COM_OBJ_T_INDICATOR 0x04 // Transmit (T) #define KNX_COM_OBJ_U_INDICATOR 0x02 // Update (U) #define KNX_COM_OBJ_I_INDICATOR 0x01 // Init Read (I)
For instance, the flag value for the push button (CWTU) would be:
0x20 + 0x08 + 0x04 + 0x02 = 0x2E
The same reasoning gives 0x2C for the output bloc (CWT).
Add the lines and replace the values if necessary by respecting the previous rules for every objects in your setup. The list looks like this :
Knx._comObjectsList = [ KnxComObject.KnxComObject(KnxDevice.G_ADDR(0, 0, 1), 0, 0x2E), KnxComObject.KnxComObject(KnxDevice.G_ADDR(0, 0, 1), 0, 0x2C) ]
3/ Interacting with KNX devices
Receiving a telegram to trigger an action on the Raspberry Pi
Every time a device is updated, the bus coupling unit will send a message over the UART interface. Knowing this, we defined a callback triggering on a device’s update. The function is called “KnxEvents” and in the example script, will print the state of the LED when the push-button is pressed.
The function Knx.read(1) will return the value sent to the device with index 1 in the list (the output bloc, in our case). When the push button is pressed, the callback function will be triggered. Then, depending on the state of the LED (read in the telegram), the terminal will display either “ON” or “OFF”.
In the “try” code block, we need to define the raspberry pi as a Communication Object with a physical address and a serial port. Pick a physical address not used by another device of your KNX system. In our case, we chose 1.1.3. Write the serial port related to the Raspberry Pi you are using. For Raspberry Pi 3, it is /dev/ttyS0 whereas it is /dev/ttyAMA0 in our case.
Run the script by entering:
Now, try to press on the push button: you should see the LED’s state displayed on the terminal.
Sending a telegram to another device
Now that we successfully used the KNX device to “control” the Raspberry Pi, let’s try to do the opposite. We will send a telegram from the Raspberry Pi and try to control one of the device. In this example, we will simply turn on the LED connected to the output interface. To send a telegram from the microcontroller to the KNX bus, we need to use the function Knx.write(index, value). For instance, to turn on the LED connected to the channel 1 of the interface, call the function as follows:
To turn it off, we can write 0 to it by changing the value :
Switch on the KNX system’s power supply and then run the example script. The LED should be turned on before pressing the push button.
Now that we can send and receive telegrams, there are a lot of things we can do, like interfacing with some long range networks, sensors, displays and so on.