Since the main program was running through Codesys and the communication between the robot and the PLC was Modbus, we needed to implement MQTT connection from the PLC as well. This was needed for Stockfish and our 3D simulation in blender. This was done in the PLC's configuration online. 

  • The correct network "TP-Link_8208" where the PLC is configured to was connected to, then the PLC ID was searched up on google "158.38.140.87" this gives access to the configurations. After logging in the we go to; Configuration>Cloud Connectivity>connection 1 where the configuration looks as such;

  • The settings are set as such; where the Hostname matches the IP address of the device that's running the broker and the port number is 1883, the client ID is set to WAGO as we're connecting a Wago PLC and the Data protocol is set to Native MQTT as the publish subscribe function blocks that we will be using require this protocol. More can be read about this later on in this section
  • This was for connection 1, we decided to configure this for both connections 1 and 2 so that if we ended up needing another connection we would have it available. 

Publishing and subscribing the PLC (Codesys)

As highlighted in the flow chart in the overview, the PLC must subscribe to the stockfish script and it has to publish the states to blender and feed in the input to stockfish. this means we needed to implement a publisher and subscriber code. This was done using the wagoAppCloud library. This was added from library manager>add library> wagoAppCloud. The publisher function block is "FbPublishMQTT_2" which is under Native MQTT, and in its documentation it says the protocol must be Native MQTT for this block to run which is why we configured it in the section above.  The inputs, outputs and its specification can be found in the documentation inside the library. This was used as a guidepost when implementing. The first step was to create an overview of the message we want to send, this is shown in the figure below; 

It shows the variable that's being published, its type and which entity is publishing. 


Once we have that we can start generating the message, since we were dealing with so many different types of data, another function block was used to write a string dictionary that can handle all data types and not just string, this allowed dynamic publishing within Codesys and we didn't have to only work with strings.  The function block responsible for this was "WagoappJSON.Fb_JSON_Writer_02" which is from another library that was added called WagoappJSON, this gives a JSON string out which is a universal format so it can be handled dynamically in python as well. The documentation used was https://help.ubidots.com/en/articles/6959980-connect-a-wago-pfc200-to-ubidots-using-codesys#h_e450c0f042

  • The following code is the initialization of the two function blocks and the variables that we will be publishing and writingThe topic is "PLCupdates" which is used to differentiate between the several publishers. 
  •    
  •  
    • We are working with 5 different variables shown under the comment // Game variables. These are the variables that will be published
    • the JSON function block writes a string in the format :'{"val1": #Parameter, "val2" : #Parameter, "val3": #Parameter}';
    • In our case, it looks like ; '{"robotMove": "#Parameter", "playerMove": "#Parameter", "playerIsWhite": "#Parameter","PlayerTurn": "#Parameter" ,"gameState": "#Parameter"}';
      • The reason why we had to use " " around the parameters is because this was being published to python scripts and the json.loads function in python requires this otherwise you'll run into a parsing error. 
      • Additionally, CODESYS uses single quotes for strings whereas python uses double so to make up for this the whole string was encoded into utf-8 so the published string now looked like;  UTF8#'{"robotMove": "#Parameter", "playerMove": "#Parameter", "playerIsWhite": "#Parameter","PlayerTurn": "#Parameter" ,"gameState": "#Parameter"}'; If this is not done, the python scripts won't parse the variables correctly into a dictionary, so the outputs become strings which is not compatible when we wanna use the variables to update the simulation. Due to this reasons, the variables that were initially bool had to be converted into strings.

  • The subscriber was much more simpler so the only thing that needed to be planned when creating the subscriber was what was the message that was gonna be received. The reason for this was because we need to initialize the variables.  The subscriber was subscribing to the stockfish python file so that it get's the robot's move. Other variables were needed for sequence logic handling (for more information refer to 24_6 PLS software).  The function block we are using is the corresponding subscriber function block to the publisher block we used earlier. It's from the same library wagoAppCloud and is called "FbSubscribeMQTT_2"(the documentation is found in the library manager in Codesys). 


Publisher Code; 




Explanation;


  • The code on the left highlights how we make up for the fact that the published variabel had to be a string. 
    • We introduced global variables that were set to the local variables so that they update with the rest of the code and the right values are published
    • We used x_TO_STRING to switch to strings as the global variables were in different types so we didn't want to change the local variable's data type. This gave us a more dynamic way to handle the publisher
    • The last block JSON serialization is just to show how to implement the function block, the variables are added to each index of the string to be published. Each index corresponds to one variable and its value


  • The second code to the left shows, the publishing of the written message from JSON function block, the condition allows for control of when the code is to publish
    • dwBusyCounter and dwErrorCounter were variables introduced to keep track of whether the publisher was busy or in error. This will help in cases where we might have to debug. 
    • MemCopy is used to take off load from the processor as it's easier to copy the data from one place to another rather than handling it element by element. It also makes it more reliable when the publisher is publishing frequently, the mem copy allows for proper queuing and data transfer.

Video here. 

Subscriber code;



Explanation;

  • The code to the left shows the initialisation of the function block we are using,  with the topic being "chess/robot_moves". The publisher from VScode python publishes to this topic. 
    • The message being published is; "Robot move: {robot_move}, Piece type: {move_piece}, Player Move: {player_move}, gameState: {game_state}, Capture Piece: {capture_piece}" . The {} hold the variables corresponding to each variable(for more information refer to MQTT via VScode python). 
    • The debugging parameters were similar to those of the publisher. The extra debugging variable added were oStatus which is an inbuilt debugger of the function block. This specifies if everything is okay with the block or not. This code is missing only the variable for capture piece but it was added in the final code. This is because while we were going through the logic we realized more and more things we might need so we were constantly updating the publishers and subscribers.

  • The second code to the left highlights the serialization of the function block which was done with the help of https://www.youtube.com/watch?v=UnhG15JFjao&t=556s 
    • Once the data was received it was handled with the use of MID which is a function that splits the message into the corresponding variables. The documentation to this function can be found here: https://product-help.schneider-electric.com/Machine%20Expert/V1.1/en/standard/topics/mid.htm
      • For some reason, the start of each was R from robot move so the character number which is the last number in the MID function had to be calibrated so it printed the right values. 
    • Lastly, the extracted values were set to the local variables which were then set to the global variables with the correct data type conversion(if needed)


Results; 


The photos above show successful subscription and publishing through PLC, the subscriber shows the value being processed to the variables and the publisher shows the message being copied to payload which will then be set to true to be published. (To check out the result of the publisher and where it is being sent and received, go to MQTT via VScode python )

  • No labels