In a previous post I showed how to get started with Home Assistant and TwinCAT using Beckhoffs ADS. During research for this project I also stumbled over MQTT and I decided to do some test projects with it. In this series of post I will show the basis of MQTT communication with TwinCAT. Followed by some more advanced examples using JSON.
Used hardware:
For this post I made use of this hardware:
- A development laptop
- IPC C6015 from Beckhoff which will be our PLC. The IPC has Windows 10 IOT installed and TwinCAT 3 4022.
- EtherCAT bus coupler EK1100
- EL1008 – 8 channel digital input.
- a button connected to channel 1
- EL2008 – 8 channel digital output.
- a green led connected to channel 1
- EL3314 – 4 Channel thermouple input (temperature measurement).
- J-Thermocouple connected to channel 1.
- EL1008 – 8 channel digital input.
MQTT a short introduction
MQTT is an extremely lightweight publish/subscribe messaging transport protocol usually running over TCP-IP. Because it is such a lightweight protocol MQTT is widely used in IOT devices. But it is also supported by many home automation applications like Home Assistent. A MQTT network consists of one MQTT message broker, with one or more clients connected to it. Each client can publish message to the broker specified with a topic name. And each client can subscribe to message with a specified topic name. The broker thus receives all the messages and will publish them to the subscribed clients.
In this serie of posts I will use the Mosquitto message broker. This broker is open source, light weight and easy to use. An overview of how the MQTT broker in this post takes it place in the data flow:
Setting up the MQTT broker
I installed the Mosquitto broker on my Windows 10 laptop. To start the broker open command prompt, change the directory to the Mosquitto installation folder, and run Mosquitto. For debugging run Mosquitto with the ‘-v’ parameter to show all logging. Make sure you allow Mosquitto in your firewall!
Publish a message with TwinCAT
With the broker installed it’s time to to set up the PLC and send some data. Create a new PLC project in TwinCAT with a default ‘Main’ program. Then install the library TC3_IOTBase. In the main program add the following variables:
PROGRAM MAIN VAR fbMqttClient: FB_IotMqttClient; // MQTT client. TopicToPublish : STRING(255) := 'Temperatures'; // Mqtt topic on which we will broadcast the acual temperatures MessageToPublish : STRING(255); //String to send. fbSendMessageIntervalTimer : TON := (PT:=T#1S); //Interval timer for broadcasting. ai_RoomTemperature AT %I* : INT; //Actual room temperature, linked to thermocouple END_VAR
The variable ‘fbMqttClient‘ the main component here. It handles the communication from and to the message broker. ‘TopicToPublish‘ is the variable we use to indicate the topic we are publishing on. In this example we use a fixed topic: ‘Temperatures’.
‘MessageToPublish‘ will be the published string and is assigned in the program. The ‘fbSendMessageIntervalTimer ‘ timer defines the interval on which the messages will be published. The ‘ai_RoomTemperature‘ variable is linked to phsyical input with an connected thermocouple. Purely to make this example a bit more concrete ๐ .
In the implementation part of the main program write the following code:
IF _TaskInfo[GETCURTASKINDEXEX()].FirstCycle THEN fbMqttClient.sHostName := '192.168.xxx.xxx'; fbMqttClient.nHostPort := 1883; fbMqttClient.sTopicPrefix := ''; fbMqttClient.sClientId := 'Publishing PLC'; END_IF fbMqttClient.Execute(bConnect := TRUE); IF fbMqttClient.bConnected THEN fbSendMessageIntervalTimer(IN:=TRUE); IF fbSendMessageIntervalTimer.Q THEN fbSendMessageIntervalTimer(IN:=FALSE); MessageToPublish := CONCAT('Room temperature: ',REAL_TO_STRING(ai_RoomTemperature / 10.0)); fbMqttClient.Publish(sTopic:= TopicToPublish, pPayload:= ADR(MessageToPublish), nPayloadSize:= LEN2(ADR(MessageToPublish))+1, eQoS:= TcIotMqttQos.AtMostOnceDelivery, bRetain:= FALSE, bQueue:= FALSE); END_IF END_IF
The first part of the program configures the MQTT client. Specify the IP address of the Mosquitto broker, which in my case is my development laptop IP address. We also name the MQTT client here which is particularly useful for debugging. Notice that theย configuration of the MQTT client only happens during the first cycle of the PLC!.
The line ‘fbMqttClient.Execute(bConnect := TRUE);’ connects the client to the broker. This method must be called cyclic to keep the connection alive!
The last part of the program checks if the connection is alive and if so it composes a message on interval and publishes it. In this example we publish a message ‘Room temperature: **.*’ The publish method take a couple of arguments. a string containing the topic name, the address of the text to send and the size of the message. The other arguments are food for another post.
Running this program we immediately notice the arrival of message in the Mosquitto broker. The messages are easily identified by the named client : ‘Publishing PLC’.
Reading data with a smartphone
The fun thing with MQTT is that almost al devices supporting TCP-IP can implement it. This could mean a total different PLC brand like Siemens. But it could also be a smartphone! On my android smartphone I downloaded and installed the MQTT Dash app. with the smartphone being on the same network you can connect MQTT dash to the Mosquitto browser and subscribe to topic ‘Temperatures’.
Subscribe on a topic with TwinCAT
Receiving data on you phone is fun, but this post is about TwinCAT and MQTT ๐ . So I created a second separate PLC project. With again a single main program. Which makes by project structure as seen in this picture:
In the declaration part of the main program add the following variables:
PROGRAM MAIN VAR fbMqttClient: FB_IotMqttClient; fbMessageQueue: FB_IotMqttMessageQueue; fbMessage: FB_IotMqttMessage; Subscribed:BOOL; TopicToSubscribe : STRING(255) := 'Temperatures'; // Mqtt topic on which we will subscribe ReceivingTopic:STRING(255); ReceivingData:STRING(255); END_VAR
Same as in the program publishing data the variable ‘fbMqttClient‘ is the main function block to connect with the broker. ‘fbMessageQueue‘ is a queue which stores the received messages. The ‘fbMessage‘ is function block which contains the received messages.
Further we have a boolean ‘subscribed‘ indicating if we are subscribed to a topic and a variable ‘TopicToSubscribe‘ containing the string ‘Temperatures‘ the topic we will subscribe to. The variables ‘ReceivingTopic‘ and ‘ReceivingData‘ are used for storing the received messages.
In the implementation part of the main code add the following code:
IF _TaskInfo[GETCURTASKINDEXEX()].FirstCycle THEN fbMqttClient.sHostName := '192.168.xx.xx'; fbMqttClient.nHostPort := 1883; fbMqttClient.sTopicPrefix := ''; fbMqttClient.ipMessageQueue := fbMessageQueue; fbMqttClient.sClientId := 'Subscribing PLC'; END_IF fbMqttClient.Execute(bConnect :=true); IF fbMqttClient.bConnected THEN IF NOT Subscribed THEN Subscribed := fbMqttClient.Subscribe(sTopic:=TopicToSubscribe, eQoS:=TcIotMqttQos.AtMostOnceDelivery); END_IF END_IF IF fbMessageQueue.nQueuedMessages โบ 0 THEN IF fbMessageQueue.Dequeue(fbMessage:=fbMessage) THEN fbMessage.GetTopic(pTopic:=ADR(), nTopicSize:=SIZEOF(ReceivingTopic) ); fbMessage.GetPayload(pPayload:=ADR(ReceivingData), nPayloadSize:=SIZEOF(ReceivingData), bSetNullTermination:=FALSE); END_IF END_IF
Configuration and connecting are the same as with the publishing client, however we do now specify to the client the ‘fbMessageQueue‘ in which we want the messages stored. After the configuration and connecting the programs checks for an active subscription onto a topic. If this is not the case the programs subscribes to the topic ‘Temperatures’.
After that we continuously monitor our message queue. If a message is send to the queue we immediately dequeue it and store its topic and content in the variables ‘ReceivingTopic‘ and ‘ReceivingData‘.
Running both our PLC programs at the same time we immediately notice more data traffic at the Mosquitto broker:
Each time the broker receives a message from ‘Publishing PLC’ it directly sends this messages to the ‘Subscribing PLC’.
Of course we check the message also in the online view:
Conclusion
Enough lecture for this post! This post covered the first setup of TwinCAT and MQTT with some basic examples. Even with a small side step showing the data on a smart phone! Part 2 we will go in more detail about composing messages using JSON.