Modern industrial communication is often performed over Ethernet protocols, especially within the Siemens product ecosystem. However, some external devices (especially non-Siemens devices) communicate using serial protocols. Luckily, Siemens provides communication modules and a library of communication functions to facilitate communication. All that said, smooth implementation requires a stable driver which predictably handles requests, responses, and edge cases.
I recently implemented such a driver for RS232 using Siemens SCL, and I hope to share some key tips to avoid frustrations later.
Hardware Configuration
Siemens provides a line of communication modules which allow for sending and receiving serial communication messages.
Be sure to select the communication protocol in use for the external device. In this case, RS232.
![Select a communication protocol](/Portals/0/Select%20the%20Communication%20Protocol.png)
Baud rate (the rate that bits are sent on the wires) is also important to match with the external device. This is configured through the “Data transmission rate” option.
![Data Transmission Rate Configuration](/Portals/0/Data%20Transmission%20Rate%20Configuration.png)
Driver Structure
![Driver structure](/Portals/0/Driver%20Structure.png)
Before the sequencing logic, the driver should check for the done receipt from the calling function.
IF #bInReceipt THEN
#bOutDone := FALSE;
END_IF;
The bulk of the code should be set up in the form of a sequence with three steps, shown below as a basic skeleton in SCL.
CASE #iStep OF
#iIdle:
IF #bInExecute THEN
[SET sInRequest]
#iStep := #iSend;
END_IF;
#iSend:
IF [TIMEOUT] OR [ERROR] THEN
[HANDLE ERROR]
#iStep := #iIdle;
ELSIF Send_P2P.DONE THEN
#iStep := #iReceive;
END_IF;
#iReceive:
IF [TIMEOUT] OR [ERROR] THEN
[HANDLE ERROR]
#bOutDone := TRUE;
#iStep := #iIdle;
ELSIF Receive_P2P.NDR THEN
[Parse buffer string, assign to sOutResponse]
#iStep := #idle;
END_IF;
END_REGION;
At the bottom of the driver, there should be a call to the following built-in functions for interacting with the communication module card. These should be called every scan.
#Send_P2P(REQ := (#iStep = #iSend),
"PORT" := [Found in PLC tags > System constants > Hw_Submodule],
BUFFER := #sBufferCommand);
#Receive_P2P("PORT" := [Found in PLC tags > System constants > Hw_Submodule],
BUFFER := #sBufferResponse);
NOTE: [brackets] intentionally left ambiguous to provide application-specific opportunities for customization.
Using the Driver in a Larger Project
The calling function for the driver should follow this basic structure, within a larger state machine.
First, at the top of the calling function, place the following lines, to force single-scan behavior from these values.
bRS232_Execute := FALSE;
bRS232_Receipt := FALSE;
Then, at the bottom, place an instance of the driver. It should be called every scan.
#RS232_Driver(bInExecute := bRS232_Execute,
sInRequest := sRS232_Request,
bInReceipt := bRS232_Receipt,
sOutResponse => sRS232_Response,
bOutDone => bRS232_Done,
bOutError => bRS232_Error);
For a given state in the larger state machine of the project, the driver is used with the following syntax.
CASE #iState OF
...
#iExampleState:
bRS232_Execute := TRUE;
sRS232_Request := 'FizzBuzz';
IF bRS232_Done THEN
bRS232_Receipt := TRUE;
bRS232_Execute := FALSE;
END_IF;
...
END_CASE;
Conclusion
While this example has highlighted how SCL can be used to create a driver for RS232 serial communication, the framework presented can be extended to many different communication protocols.
Learn more about DMC's Siemens PLC programming services.